



    ________________________________________________________________________
                                                        Appendixes   277
    ________________________________________________________________________


    APPENDIX 1: PADTALK ERROR MESSAGES

    This appendix contains a complete set of error messages you may
    encounter using the PADtalk scripting language. The compiler error
    messages are listed first, followed by the runtime error messages.

    For general error messages received when working with HyperPAD features
    not involving PADtalk, see "General Error Messages" in the User's Guide.


    COMPILER ERROR MESSAGES

    When you compile a script from the Script Editor or the message box,
    HyperPAD checks for any PADtalk syntax errors you have made, displaying
    an error message if necessary.

    The messages produced by the HyperPAD compiler are listed below in
    numerical order. Each error message is described briefly.

    0.  General syntax error.

    The compiler has detected an unknown syntax error. Please report this
    condition to Brightbill-Roberts.

    1.  "handler" or "function" expected.

    HyperPAD was unable to compile a handler or function because it was not
    preceded by a handler or function keyword.

    2.  Reserved.

    Reserved for future use.

    3.  "begin..end" block must follow handler or function.

    HyperPAD was unable to compile a statement following a handler or
    function keyword because the statement was not enclosed by a begin...end
    block.

    4.  Reserved.

    Reeserved for future use.

    5.  Reserved.

    Reserved for future use.

    6.  Incomplete statement.

    The compiler reached the end of a script before it expected to.

    Check the syntax of your script and make any necessary corrections.



    ________________________________________________________________________
                                                        Appendixes   278
    ________________________________________________________________________


    7.  Reserved.

    Reserved for future use.

    8.  Can't use "begin..end" block in message box or do command.

    A begin...end block can only be used within a HyperPAD script.

    9.  String too long.

    Your script contains a string that is too long.

    A string used in a script cannot exceed 255 characters.

    10.  Identifier too long.

    Your script contains an identifier that is too long, preventing HyperPAD
    from compiling the handler or function in which the identifier is used.

    An identifier in a script cannot exceed 255 characters.

    11.  "do" expected.

    The compiler has encountered a while statement without a matching do.

    12.  "then" expected.

    The compiler has encountered an if statement without a matching then.

    13.  "hyperpad" expected.

    The compiler has encountered an exit to or pass to statement and expects
    HyperPAD to be the destination reference.

    14.  "return" statement only allowed in functions.

    HyperPAD has found a return statement in a handler.

    15.  Invalid or missing object reference.

    The compiler has encountered a reference to an object that does not
    exist, or one that does not suit the operation being performed.

    16.  Reserved.

    Reserved for future use.

    17.  Invalid number of arguments for this property.

    HyperPAD cannot compile your statement, because you have specified too
    many or two few arguments for a property.



    ________________________________________________________________________
                                                        Appendixes   279
    ________________________________________________________________________


    18.  } expected.

    The compiler has encountered an open brace without a matching close
    brace.

    19.  Reserved.

    Reserved for future use.

    20.  "of" expected.

    The compiler has encountered a statement such as set, edit, or case
    without a matching of.

    21.  ) expected.

    The compiler has encountered an open parenthesis without a matching
    close parenthesis.

    22.  Identifier can't be a destination reference.

    The compiler has located the use of an identifier (such as a keyword
    like begin) that cannot be used as a destination reference.

    23.  Invalid identifier in expression.

    The compiler has encountered an expression that incorrectly uses an
    identifier such as a function or a quoted string.

    24.  Page and/or pad reference expected.

    The compiler has encountered a statement, such as go to, without a
    required page or pad reference.

    25.  "pause" or "programDirectory" expected.

    The compiler encountered a run command that uses the with preposition
    with an identifier other than pause or program directory.

    26.  Identifier is not a property.

    The compiler has encountered a statement that attempts to set or get
    something that is not a valid HyperPAD property.

    27.  Can't set this property.

    The compiler has encountered an attempt to set a property that cannot be
    set; for example, you cannot set properties such as layer, markedLines,
    currentLine, longName, ID, or longID.



    ________________________________________________________________________
                                                        Appendixes   280
    ________________________________________________________________________


    28.  Identifier can't be made global.

    A global statement was encountered in which the identifier being
    declared global was previously used as a local variable.

    29.  Quoted string not allowed.

    The compiler has encountered a statement whose handler name is a quoted
    string.

    A statement must be in the form:  handlerName [arm 1,arm 2,...]

    where handlerName is the unquoted name of the handler.

    30.  ; expected.

    The compiler has encountered consecutive statements without a semicolon
    to separate them.

    31.  ( expected.

    The compiler has encountered a close parenthesis without a matching open
    parenthesis.

    32.  Reserved.

    Reserved for future use.

    33.  Invalid parameter to "number of".

    A number of function was encountered using a text parameter.

    Check the required syntax for the number of function and try again.

    34.  Only 3 replies allowed in "answer" statement.

    The compiler has encountered an answer statement with four or more
    replies.

    Check your answer statement.

    35.  "to" expected.

    The compiler has encountered a statement, such as set, send, for, add,
    convert, or write, without a matching to.

    36.  "from" expected.

    The compiler has encountered a statement, such as subtract or read,
    without a matching from.



    ________________________________________________________________________
                                                        Appendixes   281
    ________________________________________________________________________


    37.  "by" expected.

    The compiler has encountered a multiply or divide statement without a
    matching by.

    38.  Reserved.

    Reserved for future use.

    39.  Reserved.

    Reserved for future use.

    40.  "until" expected.

    The compiler has encountered a statement, such as repeat or read, that
    requires a matching until.

    41.  "end" expected.

    The compiler has encountered a case statement without an end keyword.

    42.  : expected.

    The compiler has encountered a statement, that requires a colon.

    43.  = expected.

    The compiler expected to find a statement in the form, for statement for
    <variable> = <number>, but the = sign was left out.

    The compiler has encountered a for statement without the required
    assignment operator.

    44.  Invalid container name.

    The compiler has encountered a statement that contains an improper
    reference to a container.

    Make sure that your identifier reference is a valid identifier, i.e.,
    one that starts with an alphabetic character, _ or $, and is followed by
    only alphanumeric (A..2, O..9) characters, or the _ or $ character.

    45.  Duplicate handler name.

    The compiler has encountered the use of a single handler name twice in
    the same script.

    46.  Duplicate function name.

    The compiler has encountered the use of a single function name twice in
    the same script.



    ________________________________________________________________________
                                                        Appendixes   282
    ________________________________________________________________________


    47.  Invalid characters in container name.

    The compiler has used an invalid character in a container name.

    Use only the alphanumeric characters (A..Z and 1..9), or the $ and _
    characters, in your container names.

    48.  "page" expected.

    The compiler has encountered a pop statement without a page reference.

    49.  Page reference expected.

    The compiler has encountered push statement without a page number.

    50.  More than one statement encountered.

    You have entered an invalid statement into the message box and the
    compiler cannot process it.

    Make sure that you enter only a single statement in the message box.

    51.  Container name not allowed.

    The compiler has encountered a do statement where a container name is
    improperly used as the operand.

    52.  Can't use reserved word as container name.

    The compiler has encountered the improper use of a reserved word such as
    begin as a container name.

    53.  Can't change local container to global.

    The compiler has encountered an attempt to change a local container into
    a global variable.

    54.  Container is already global.

    The compiler has encountered a global statement whose operand is already
    a global.

    Delete the global statement from your script, or place the global
    statement at the beginning of the script.

    55.  "left" or "right" expected.

    An effect has been used, the direction it expected is missing.



    ________________________________________________________________________
                                                        Appendixes   283
    ________________________________________________________________________


    56.  Effect name expected.

    The compiler has encountered a visual statement without a matching
    effect name.

    57.  Can't use this direction with the specified effect.

    The compiler has encountered a visual statement with an invalid
    direction.

    Check the syntax of the effect you chose and try again.

    58.  "delay" expected.

    The compiler has encountered a visual statement that uses the with
    preposition, but the delay is not specified.

    59.  Object reference expected.

    The compiler has encountered an edit statement without a valid object
    reference.

    60.  "script" expected.

    The compiler has encountered the statement, edit the, without a proper
    script reference.

    61.  Incomplete expression.

    The compiler has reached the end of an expression unexpectedly.

    62.  "pause" already specified.

    The compiler has encountered a run statement with two pauses.

    63.  "directory" already specified

    A run statement was encountered in which the program directory keyword
    was used more than once.

    64.  Sort option already specified.

    Conflicting options were encountered in a sort statement.

    65.  Reserved.

    Reserved for future use.



    ________________________________________________________________________
                                                        Appendixes   284
    ________________________________________________________________________


    66.  "dateTime", "numeric", "text", "ascending", "descending" or "by"
    expected.

    The compiler has encountered a sort by statement without a sort
    specification.

    67.  Background field reference expected.

    The compiler has encountered a find statement in which the "in"
    parameter is specified,  but the reference to a background field not.

    68.  "paramCount" and "params" do not take arguments.

    The compiler has encountered a paramCount or params function that
    incorrectly uses arguments.

    69.  "param" must take one argument.

    The compiler has encountered a param function that uses zero or more
    than one argument.

    70.  Color name expected.

    The compiler has encountered a set statement that requires a color name.

    71.  "chars", "words", "items" or "lines" expected.

    The compiler has encountered a chunking statement where the chunking
    reference is not found.

    72.  , expected

    An incorrect number of arguments to a command has been encountered by
    the compiler.

    73.  " expected.

    The compiler has encountered an open quote without a matching close
    quote.

    74.  Background reference not allowed with page id.

    A background has been specified with a page referred to by its ID.

    Since pages referenced by their ID are unique, the background
    specification is unnecessary.

    75.  Invalid or no target object specified in "send".

    The compiler has encountered a send statement that does not properly
    refer to a HyperPAD object.



    ________________________________________________________________________
                                                        Appendixes   285
    ________________________________________________________________________


    RUNTIME ERROR MESSAGES

    Runtime errors occur as HyperPAD executes a compiled script. When a
    runtime error occurs, HyperPAD displays an error message with two
    choices: <<Script>> and <Cancel>.  If you select <Cancel>, HyperPAD will
    stop execution of the script. If you select <<Script>>, HyperPAD loads
    the Script Editor and displays the script that caused the runtime error.

    Note: If you compiled the original script with the Debug option on,
    HyperPAD will place the cursor on the line that caused the error. If the
    Debug option was off at the time of the compile, the cursor will be
    placed at the top of the script after an error.

    0.  Unknown runtime error

    Your script has generated an unknown runtime error. Please report this
    condition to Brightbill-Roberts.

    1.  Argument to arithmetic routine is not a number

    Your script attempted an arithmetic operation upon a string instead of a
    number.

    2.  Argument to "param" is not a number

    An argument passed to the param function was text, rather than a number
    as required.

    3.  Argument to "param" is less than 1

    You passed a number less than 1 to the param function.

    The number passed to the param function must be between 1 and the number
    of parameters. If you pass a number larger than the number of
    parameters, the param function will return empty.

    4.  Argument to "print" is not a number

    The number of pages parameter passed to a print command contained text,
    rather than a number as required.

    5.  Argument to "character" is not a number

    A character chunk parameter did not evaluate to a number.

    6.  Argument to "word" is not a number

    A word chunk parameter did not evaluate to a number.

    7.  Argument to "item" is not a number

    An item chunk parameter did not evaluate to a number.



    ________________________________________________________________________
                                                        Appendixes   286
    ________________________________________________________________________


    8.  Argument to "line" is not a number

    A line chunk parameter did not evaluate to a number.

    9.  Invalid object ID

    An object was referred to with a non-existent ID number.

    10.  Can't find object ID

    An object was referred to with a non-existent ID number.

    11.  Can't find object offset or name

    An object was referenced using a non-existent name or number.

    12.  Invalid characters in date/time format

    An argument contained an unrecognizeed date or time format.

    13.  Parameter to function is not a number

    An text argument was passed to a function that requires a number.

    14.  Reserved.

    Reserved for future use.

    15.  Reserved.

    Reserved for future use.

    16.  No corresponding "case"

    A case statement has been evaluated with a selector that has no
    corresponding case.

    Use an otherwise statement to handle unexpected values for the selector.

    17.  Argument to unary minus is not a number

    The minus sign was placed before a text value.

    The minus sign can only be used with numeric arguments.

    18.  "pop" encountered with no previous "push"

    The pop page command was executed with no page on the page stack.

    Use the push statement to push pages onto the page stack.



    ________________________________________________________________________
                                                        Appendixes   287
    ________________________________________________________________________


    19.  Delay is not a number

    The parameter specified as the delay for the visual command is not a
    number.

    20.  Target can't be used with this operation

    The target object is not being used in accordance with its type.

    21.  Invalid use of current object

    The currentObject is not being used in accordance with its type.

    22.  Invalid number of arguments for function

    A built-in function has been called with too many or too few arguments.

    23.  Invalid argument to "domenu"

    The doMenu command has been called with an invalid choice.

    The parameters to doMenu are the commands exactly as displayed in the
    menus; a dimmed choice cannot be used as an argument to doMenu.

    24.  Invalid chunking parameter

    An argument used in a chunking expression is either negative or not a
    number.

    25.  Invalid argument to "keypress"

    The keyPress message has been received, but the argument is not numeric.

    26.  Can't modify scripts at current user level

    An attempt to edit a script was made with the user level less than
    Scripting.

    The userLevel property must be set to Scripting to edit scripts.

    27.  "true" or "false" expected

    An attempt has been made to set a property that requires a boolean value
    to something other than true or false.

    28.  Accelerator key out of range

    An attempt has been made to set the acceleratorKey of a button or field
    to a value less than 0 or greater than 255.



    ________________________________________________________________________
                                                        Appendixes   288
    ________________________________________________________________________


    29.  Invalid coordinates

    An attempt has been made to set the rectangle or location to coordinates
    that make it impossible to display the object on screen.

    30.  "on" or "off" expected

    An attempt has been made to set a property that requires a value of on
    or off to something other than on or off.

    31.  "layer" or "position" expected

    An attempt has been made to set the tabbing property to a value other
    than layer or position.

    32.  "thin" "fat" or "off" expected

    An attempt has been made to set the cursor property to a value other
    than thin, fat, or off.

    33.  Text size too big for operation

    An attempt has been made to increase the number of fields in a container
    to a number greater than 30,000.

    34.  Not enough memory to get field content

    There is not enough memory for HyperPAD to make an internal copy of the
    content of a field.

    35.  Invalid insertion point

    An attempt has been made to set the insertPoint property of a field to a
    value less than zero or greater than number of characters in field.

    36.  Invalid file number

    An invalid number was used with the read, write, or close command.

    Only numbers returned from open(), append(), or create() can be used as
    a reference to a file.

    37.  Number expected for "chars"/"words"/"items"/"lines"

    The read command was used with a non-numeric value specifying how many
    characters, words, items, or lines to read from a file.

    38.  File has not been opened

    A read, write, or close command has been used to refer to a file that is
    not open.



    ________________________________________________________________________
                                                        Appendixes   289
    ________________________________________________________________________


    Use open(), append(), or create() to prepare a file for use with read or
    write.

    39.  Can't print without starting print job

    A print command has been used with the printer property set to off.

    40.  Query expression must evaluate to "true" or "false"

    The expression supplied to the query command does not evaluate to true
    or false.

    41.  Invalid style

    The style of a button or field has been set to an improper value for
    that object type.

    42.  "top" or "left" expected

    An attempt has been made to set the namePosition property of a field to
    a value other than top or left.

    43.  "left", "right", or "centered" expected

    An attempt has been made to set the align property of a button or field
    to a value other than left, right, or centered.

    44.  Invalid argument to "send"

    An attempt has been made to send an invalid message with the send
    command.

    Messages sent with the send command must be a single, non-hyphenated
    word.

    45.  Math error - invalid

    A floating point math error has occurred.

    46.  Math error - denormal

    Your script generated a very small floating-point number resulting in a
    possible loss of significance.

    47.  Math error - divide by zero

    Your script attempted to divide by zero.

    48.  Math error - overflow

    Your script generated an overflow in a floating-point operation.



    ________________________________________________________________________
                                                        Appendixes   290
    ________________________________________________________________________


    49.  Math error - underflow

    Your script generated an underflow in a floating-point operation.

    50.  Math error - inexact

    Your script generated a loss of precision in a floating-point operation.

    51.  Math error - invalid argument to math function

    A built-in math function was called with a non-numeric argument.

    52.  Math error - loss of significance

    Your script generated a loss of significance in a floating-point
    operation.

    53.  Invalid number format

    An attempt has been made to set the numberFormat property to an improper
    value.

    The numberFormat is a text value consisting of a number of zeros,
    followed by a decimal point, followed by 0 or more zeros, followed by 0
    or more pound signs (#).

    54.  Too much recursion

    HyperPAD has run out of stack space, a condition caused either by a
    handler that repeatedly calls itself or other nested handlers.

    55.  Invalid communications port setting

    An improper value for the modem, baud, parity, stopBits, or dataBits
    property was encountered.

    56.  Can't find page

    An attempt has been made to a number less than zero or greater than the
    number of pages in the pad.

    57.  Out of memory

    An operation requiring a large amount of memory has been attempted at a
    time when memory is low and cannot be recovered by HyperPAD.

    This condition occurs when you have pending handlers on pages that
    cannot all be contained in memory at the same time.



    ________________________________________________________________________
                                                        Appendixes   291
    ________________________________________________________________________


    APPENDIX 2: KEY CODES

    The following table contains all of the keystrokes recognized by
    HyperPAD. Use the table for:

    1.  Determining the numbers passed to the keyPress handler. For example:

    handler keypress(keyNumber);
    begin
      if keyNumber is 7181 then
        answer "ENTER was pressed";
    end;

    2.  Determining the text returned by the key() function. For example,
    key(7181) returns "enter". The following example uses the key() function
    to evaluate a keypress:

    handler keyPress(keyNumber);
    begin
      get key(keyNumber);
      if it is "ENTER" then
        answer "the ENTER key was pressed"
      else if it is "SHIFT+PGDN" then
        go to the next page
      else if it is in "0123456789" then
        answer "A number was pressed";
      pass;
    end;

    If the key pressed was a letter, number, or punctuation, then that
    character is returned by key().

    3.  Determining special key combination for the record command. For
    example,

    record "{alt+f}{enter}";



    ________________________________________________________________________
                                                        Appendixes   292
    ________________________________________________________________________


    Key:           Key Code:            Key:            Key Code:
    ------------------------------------------------------------------------
    ENTER          7181                 CTRL+PGUP       33792
    ESCAPE         283                  CTRL+PGDN       30208
    TAB            3849                 SHIFT+UP        18488
    SHIFT+TAB      3840                 SHIFT+DOWN      20530
    BACKSPACE      13592                SHIFT+LEFT      19252
    SLASH          13615                SHIFT+RIGHT     19766
    SPACE          14624                SHIFT+PGUP      18745
    ALT+EQUAL      33536                SHIFT+PGDN      20787
    ALT+DASH       33280                SHIFT+HOME      18231
    CTRL+BACKSPACE 3711                 SHIFT+END       20273
    CTRL+ENTER     7178                 F1              15104
    ALT+SLASH      13808                F2              15360
    ALT+PERIOD     13552                F3              15616
    CTRL+MINUS     3103                 F4              15872
    BIGPLUS        20011                F5              16128
    BIGMINUS       18989                F6              16384
    PERIOD         13358                F7              16640
    SHIFT+DEL      21294                F8              16896
    UP             18432                F9              17152
    DOWN           20224                F10             17408
    RIGHT          19712                F11             34048
    LEFT           19200                F12             34304
    HOME           18176                ALT+F1          26624
    END            20224                ALT+F2          26880
    PGUP           18688                ALT+F3          27136
    PLUS           20011                ALT+F4          27392
    MINUS          18989                ALT+F5          27648
    INS            20992                ALT+F6          27904
    DEL            21248                ALT+F8          28416



    ________________________________________________________________________
                                                        Appendixes   293
    ________________________________________________________________________


    Key:           Key Code:            Key:            Key Code:
    ------------------------------------------------------------------------
    ALT+F9         28672                ALT+V           12032
    ALT+F10        28928                ALT+W           4352
    ALT+F11        35584                ALT+X           11520
    ALT+F12        35840                ALT+Y           5376
    CTRL+F1        24064                ALT+Z           11264
    CTRL+F2        24320                ALT+1           30720
    CTRL+F3        24576                ALT+2           30976
    CTRL+F4        24832                ALT+3           31232
    CTRL+F5        25088                ALT+4           31488
    CTRL+F6        25344                ALT+5           31744
    CTRL+F7        25600                ALT+6           32000
    CTRL+F8        25856                ALT+7           32256
    CTRL+F9        26112                ALT+8           32512
    CTRL+F10       26368                ALT+9           32768
    CTRL+F11       35072                ALT+0           33024
    CTRL+F12       35328                CTRL+A          7681
    SHIFT+F1       21504                CTRL+B          12290
    SHIFT+F2       21760                CTRL+C          11779
    SHIFT+F3       22016                CTRL+D          8196
    SHIFT+F4       22272                CTRL+E          4613
    SHIFT+F5       22528                CTRL+F          8454
    SHIFT+F6       22784                CTRL+G          8711
    SHIFT+F7       23040                CTRL+H          8968
    SHIFT+F8       23296                CTRL+I          5897
    SHIFT+F9       23552                CTRL+J          9226
    SHIFT+F10      23808                CTRL+K          9483
    SHIFT+F11      34560                CTRL+L          9740
    SHIFT+F12      34816                CTRL+M          12813
    ALT+A          7680                 CTRL+N          12558
    ALT+B          12288                CTRL+O          6159



    ________________________________________________________________________
                                                        Appendixes   294
    ________________________________________________________________________


    Key:           Key Code:            Key:            Key Code:
    ------------------------------------------------------------------------
    ALT+C          11776                CTRL+P          6416
    ALT+D          8192                 CTRL+Q          4113
    ALT+E          4608                 CTRL+R          4882
    ALT+F          8448                 CTRL+S          7955
    ALT+G          8704                 CTRL+T          5140
    ALT+H          8960                 CTRL+U          5653
    ALT+I          5888                 CTRL+V          12054
    ALT+J          9216                 CTRL+W          4375
    ALT+K          9472                 CTRL+X          11544
    ALT+L          9728                 CTRL+Y          5401
    ALT+M          12800                CTRL+Z          11290
    ALT+N          12544                ALT+TAB         45056
    ALT+O          6144                 ALT+SPACE       45568
    ALT+P          6400                 ALT+BACKSPACE   46080
    ALT+Q          4096                 CTRL+ALT        46336
    ALT+R          4864                 BOTHSHIFTS      47104
    ALT+S          7936                 CTRL+EQUAL      47360
    ALT+T          5120                 CTRL+INSERT     47616



    ________________________________________________________________________
                                                        Appendixes   295
    ________________________________________________________________________

    The remaining keys will only be understood by HyperPAD. These key
    combinations will not be understood by other programs (if you use the
    record and playback commands to force keys into a running program).

    Key:             Key Code:            Key:            Key Code:
    ------------------------------------------------------------------------
    ALT+SHIFT        47872                CTRL+RIGHT      51968
    CTRL+1           48128                CTRL+DOWN       53248
    CTRL+2           48129                CTRL+CENTER     53504
    CTRL+3           48130                CENTER          53760
    CTRL+4           48131                CTRL+HOME       54016
    CTRL+5           48132                CTRL+END        54272
    CTRL+6           48133                CTRL+SHIFT+HOME 54528
    CTRL+7           48134                CTRL+SHIFT+END  54784
    CTRL+8           48135                CTRL+SHIFT+I    55552
    CTRL+9           48136                SPACEPRESS      55808
    CTRL+0           48137                CTRL+BIGPLUS    56320
    CTRL+DEL         50688                CTRL+BIGMINUS   56576
    CTRL+SHIFT+UP    50944                ALT+ESC         56832
    CTRL+SHIFT+DOWN  51200                SHIFT+INSERT    57088
    CTRL+SHIFT+LEFT  51456                CTRL+SHIFT+PGUP 57344
    CTRL+SHIFT+RIGHT 51712                CTRL+SHIFT+PGDN 57600
    CTRL+RIGHT       51968                ALT             57856
    CTRL+LEFT        52480                CTRL            58112



    ________________________________________________________________________
                                                        Appendixes   296
    ________________________________________________________________________
         



    ________________________________________________________________________
                                                        Appendixes   297
    ________________________________________________________________________

    APPENDIX 3 WRITING EXTENSIONS


    INTRODUCTION

    Extensions are .EXE programs created using the Microsoft C compiler
    (version 4.0 or later) or the Microsoft Macro Assembler (version 5 or
    later). An extension consists of a number of routines that appear to
    HyperPAD as handlers or functions. Sample uses for an extension are:

        0  Display a graphics picture (like the supplied GX2 extension)

        0  Send the content of a field to the COM1 port

        0  Sort the lines of text in a field

        0  Control a videodisk player

    You can define new handlers or functions in an extension, or intercept
    existing messages, like idle or select. You pass messages to external
    handlers and call external functions just as you would any other handler
    or function in a script. In fact, you can think of your extensions as
    being a script that is made up of handlers and functions.

    Extensions receive messages just before the pad script. If you define
    extensions in your Home pad, the handlers and functions in that
    extension will be accessible from every pad. If you define extensions in
    any other pad, the handlers and functions will only be accessible from
    that pad.

    You can pass parameters between HyperPAD and the handlers and functions
    in your extension. Each parameter is passed as a HANDLE to text (a
    handle is a pointer to another pointer). There are routines available
    that you can call to assist in converting handles to other more usable
    forms. These routines are called callbacks (because HyperPAD calls the
    extension which then calls back a routine in HyperPAD). All of the
    callbacks are described in detail later in this appendix.

    The examples presented in this appendix are written in C instead of
    assembly language for clarity.



    ________________________________________________________________________
                                                        Appendixes   298
    ________________________________________________________________________


    HOW TO CREATE AN EXTENSION

    To create an extension, follow these steps:

    1.  Use a text editor to create your source file.

    2.  Compile your source file using the following command:

    cl /c /Alfw /Gs test.c

    This command compiles a C file called TEST.C using a custom memory
    model. You must use this memory model when compiling extensions in C.
    The /Gs parameter instructs the compiler to turn off stack checking.

    In assembly language, use the following command:

    masm test.asm;

    3.  Use the LINK.EXE program to assemble an EXE file using the following
    command:

    link test,,,startup/NOE;

    This command links the TEST.OBJ file with the library STARTUP.LIB that
    is supplied with HyperPAD. This library replaces the standard C startup
    code. The /NOE switch forces the linker to use the information in
    STARTUP.LIB in place of those in the default C libraries.

    After this step, you will have a complete extension called TEST.EXE.

    4.  Use the MOVER.EXE program to add the extension to a pad. Use the
    following command:

    mover mypad.pad add test.exe

    This command copies the TEST.EXE file into the pad called MYPAD.PAD. If
    you need to replace an already existing extension called TEST with a
    fresh copy of TEST.EXE, use the command:

    mover mypad.pad replace test.exe

    You are now ready to use the pad with the newly defined handlers and
    functions.



    ________________________________________________________________________
                                                        Appendixes   299
    ________________________________________________________________________


    LIMITATIONS

    If you are programming extensions in C, some library functions will not
    work, namely the functions that assume SS equal to DS. Further,
    functions that cause the C startup code to be linked will not work. You
    can determine if the C startup code is linked if you receive the error
    message:

    unresolved external _main

    Extension are limited to 64K in size. However, in low memory situations,
    pads with extensions of this size may not load.


    EXTENSION COMPONENTS


    FUNCTION POOL

    Included with each extension is a table that you must define, called the
    function pool. The pool describes the name of each routine defined in
    the extension, its entry point (a pointer to the routine), and whether
    it is a function or a handler.

    -----------------------------------
    WHENLOADED() AND WHENUNLOADED()

    Each extension can optionally include routines that is called when the
    extension is loaded from disk and released from memory.

    -----------------------------------
    WHENLOADED()

    The WhenLoaded() performs any initialization required by your extension.
    This routine might perform memory allocation, global variable
    initialization, and interrupt redirection as required by the other
    routines in the extension. WhenLoaded() is called before the entire pad
    is loaded from disk, so it cannot send messages to the current page.

    -----------------------------------
    WHENUNLOADED()

    The WhenUnLoaded() is called when the extension is released from memory.
    This routine might free any remaining memory blocks used by the
    extension or perform any additional cleanup as required by the
    extension.



    ________________________________________________________________________
                                                        Appendixes   300
    ________________________________________________________________________


    A SAMPLE C EXTENSION

    /*
    ** The following is a skeleton C extension.
    **
    ** It defines a handler called "Sample" that does
    ** nothing. It returns the continuation value STOP to ** cause HyperPAD
    to terminate the message.
    */

    #include <stdarg.h>
    #include "extern.h"

    pascal far WhenLoaded()
    {
    }

    pascal far WhenUnLoaded()
    {
    }

    Sample(NumArgs,...)

    int NumArgs;

    {
            return(STOP);<%0>


    POOL pascal Pool[] = {
            {      "Sample",   /* name of the handler */
                   Sample,      /* pointer to the handler */
                   0,           /* reserved */
                   HANDLER},    /* this is a handler */
            {      NULL,        /* NULLs mean end table */
                   NULL,
                   0,
                   0}   };



    ________________________________________________________________________
                                                        Appendixes   301
    ________________________________________________________________________


    A SAMPLE ASSEMBLY LANGUAGE EXTENSION

    ;
    ; The following is a skeleton assembly language
    ; extension.
    ;
    ; It defines a handler called "Sample" that does
    ; nothing. It returns STOP to cause HyperPAD to
    ; terminate the message.
    ;
    DOSSEG
    .MODEL      LARGE
    include     extern.inc
    .DATA
    SampleName   db          'sample',0
    Pool         PoolStruct <SampleName,SampleProc,0,HANDLER>
                 PoolStruct <>
    CODE
    WhenLoaded   proc        far
                 ret
    WhenLoaded   endp
    WhenUnLoaded proc        far
                 ret
    WhenUnLoaded endp
    SampleProc   proc        far
                 mov         ax,STOP
                 ret
    SampleProc   endp

    end



    ________________________________________________________________________
                                                        Appendixes   302
    ________________________________________________________________________


    PASSING DATA BETWEEN HYPERPAD AND YOUR EXTENSION


    PASSING PARAMETERS

    You can pass parameters to handlers and functions in an extension using
    the normal PADtalk syntax. The extension, in turn, receives the
    arguments on the stack, each as a HANDLE to a null-terminated text
    string (a string that ends with the 0 character). The number of
    parameters is passed lowest on the stack, followed by each parameter
    that the handler or function was called with. Each parameter is in the
    form of a handle to text.

    In order to access the variable number of arguments, you must include
    the standard C header file: stdarg.h. This file contains macros that
    allow you to access the arguments passed on HyperPAD's stack. The
    following example retrieves all of the passed parameters and prints
    them.

    int sample(NumArgs,...)
    int NumArgs;
    {
        var_list args;
        HANDLE hdl;
        int i;
        va_start(args,NumArgs);
        for (i=0;i < NumArgs;i++) {
            hdl = va_arg(HANDLE);
            printf("Argument %d = %s\n",i,deref(hdl));
        }
        return(STOP);
    }



    ________________________________________________________________________
                                                        Appendixes   303
    ________________________________________________________________________


    The next example shows a function that receives two parameters (and only
    2) and returns their sum:

    int sample(NumArgs,...)
    int NumArgs;
    {
        var_list args;
        HANDLE hdl;
        int number1,number2;
        if (NumArgs != 2) return(STOP);
        va_start(args,NumArgs);
        number1 = htoi(va_arg(args,HANDLE));
        number2 = htoi(va_arg(args,HANDLE));
        ReturnValue(itoh(number1 + number2));
        return(STOP);
    }


    RETURNING VALUES

    Routines in extensions that implement HyperPAD functions can return
    values to HyperPAD scripts. These values must be in the form of a handle
    to text because that's how HyperPAD internally represents and stores all
    variables. Returning values to HyperPAD is accomplished with the
    callback function ReturnValue(). For example, the following C statement
    returns a string to HyperPAD by first converting it to a handle:

    ReturnValue(stoh("John Q. Smith"));



    ________________________________________________________________________
                                                        Appendixes   304
    ________________________________________________________________________


    Each routine can return a continuation value to HyperPAD (either using
    the return statement in C or through the AX register in assembly
    language). This value indicates to HyperPAD what  to do with the
    message. The possible continuation values are:

    Value:             Description:
    ----------------------------------------------------
    PASS               pass the message on to the next layer in the object
                       hierarchy

    STOP               stop passing the message

    PASS_TO_HYPERPAD   pass the message on directly to HyperPAD, avoiding
                       the other objects in the hierarchy

    ERROR              do not pass the message on and stop all pending
                       handlers


    HANDLING MEMORY

    HyperPAD provides two different ways to allocate memory: pointers and
    handles.


    POINTERS

    A pointer is an 8 byte (far) reference to a block of memory. Allocation
    and deallocation of pointers is accomplished using the NewPtr() and
    FreePtr() functions. The following declares a pointer and shows how to
    use it:

    PTR p;   /* declare a pointer */
    /* allocate a block of 100 bytes */
    p = NewPtr(100);
    /* copy some text into that memory */
    strcpy(p,"This is a test");
    /* free the memory */
    FreePtr(p);



    ________________________________________________________________________
                                                        Appendixes   305
    ________________________________________________________________________


    HANDLES

    A handle is a pointer to another pointer which, in turn, points to a
    block of memory. The double indirection (meaning the pointer to a
    pointer) is necessary because memory blocks in HyperPAD are movable. The
    following example shows how to allocate and use a handle:

    HANDLE h;     /* pointer to a pointer (a handle) */
    /* allocate a handle of 100 bytes */
    h = NewHandle(100);
    /* copy some text into the handle
    strcpy(deref(h),"This is a string");
    FreeHandle(h);

    Handle memory blocks can move during a memory allocation request. If
    there is insufficient memory available to satisfy the request, HyperPAD
    will attempt to shuffle the memory blocks to make room for the requested
    number of bytes. Thus, during a memory allocation, HyperPAD may
    invalidate  the pointer to your memory block, but the handle will always
    remain the same. At the end of the following example, the pointer "p" is
    no longer valid:

    HANDLE h1,h2;            /* declare some handles */
    PTR p;                   /* declare a pointer */
    h1 = NewHandle(100);     /* allocate the first handle */
    p = deref(hdl);          /* establish a local pointer */
    h2 = NewHandle(100);     /* declare another handle */
    /*
    ** the local pointer "p" no longer points to the
    ** memory block referenced by the handle, h1.
    */

    It is the responsibility of the extension to free all of the memory it
    uses (This is a good use of the  WhenUnLoaded() function). All of the
    callback functions that allocate memory are noted in their descriptions
    later in this appendix.



    ________________________________________________________________________
                                                        Appendixes   306
    ________________________________________________________________________


    REFERENCING HANDLES

    Often times, it is necessary to dereference a handle, or, in other
    words, look at the memory referenced indirectly by the handle. In C, you
    can use the dereference operator (*) as in the following example:

    HANDLE h;
    printf("the handle points to the text %s\n",*h);
    A more readable way is to use the deref (defined in extern.h) macro
    which performs the same function:
    HANDLE h;
    printf("the handle points to the text %s\n",deref(h));

    In assembly language, use the following code to dereference a handle:

    les       bx,hdl         ;ES:BX = hdl
    les       bx,es:[bx]     ;ES:BX = *hdl


    HYPERPAD CALLBACKS

    Callbacks are functions defined in HyperPAD that extensions can use to
    perform various tasks. Callbacks are useful for converting data to and
    from handles, sending messages to HyperPAD and getting and setting the
    content of a field. All of the routines are declared in a C header file
    called extern.h (or, in Assembly language, extern.inc). These files must
    be included in order to write extensions. In C this is done using the
    following statement:

    #include "extern.h"

    In assembly, use the following statement:

    include extern.inc

    When calling a callback routine from assembly language, the registers
    SI,DI,BP,SS,DS are preserved. All other registers are destroyed.

    Callbacks return values in AX for 2 byte quantities and DX:AX for 4 byte
    quantities (like handles and long integers).  Unless otherwise noted,
    the routines follow the pascal calling convention; they perform their
    own stack cleanup.  Other routines, such as printf(), sprintf(),
    SendHPMsg(), and SendPageMsg(), follow the C calling convention.



    ________________________________________________________________________
                                                        Appendixes   307
    ________________________________________________________________________


    MEMORY FUNCTIONS

    The following are the memory functions:

    Function:           Explaination:
    --------------------------------------------------------
    NewHandle           allocate a handle

    FreeHandle          free a handle

    HandleSize          get the size (in bytes) of a handle

    LockHandle          lock a handle (not movable)

    UnLockHandle        unlock a handle (movable)

    ReAllocHandle       change the size of a handle

    NewPtr              allocate a pointer

    PtrSize             get the size (in bytes) of a pointer


    CONVERSION FUNCTIONS

    The following are the conversion functions:

    Function:           Explaination:
    --------------------------------------------------------
    btoh                boolean to handle

    ftoh                float to handle

    htob                handle to boolean

    htof                handle to float

    htoi                handle to integer

    htol                handle to long

    htos                handle to string

    itoh                integer to handle

    ltoh                long to handle

    stoh                string to handle



    ________________________________________________________________________
                                                        Appendixes   308
    ________________________________________________________________________


    CONTAINER GET/SET FUNCTIONS

    The following are the functions for getting or setting values in
    containers:

    Function:           Description:
    --------------------------------------------------------
    GetFieldNum         get field content by number

    GetFieldName        get field content by name

    GetFieldID          get field content by ID

    SetFieldNum         set field content by number


    MESSAGE PASSING FUNCTIONS

    The following are the external message passing functions:

    Function:           Description:
    --------------------------------------------------------
    Do                  execute a PADtalk command

    SendPageMsg         send a message to the current page

    SendHPMsg           send a message to HyperPAD


    SCREEN HANDLING FUNCTIONS:

    The following are the screen handling functions:

    Function:           Description:
    --------------------------------------------------------
    MakeWin             make a window

    RemWin              remove the most recent window

    PutStr              put a string on the screen

    HighLine            highlight a line on the screen



    ________________________________________________________________________
                                                        Appendixes   309
    ________________________________________________________________________


    EVENT HANDLING FUNCTIONS

    The following are the event handling functions :

    Function:           Description:
    --------------------------------------------------------
    PeekEvent           get the next event without removing it

    GetEvent            get the next event

    UnGetEvent          put event on top of the event queue


    MISCELLANEOUS FUNCTIONS

    The following are miscellaneous functions:

    Function:           Description:
    --------------------------------------------------------
    ReturnValue         return a value to HyperPAD from a function

    GetSharedArea       get a pointer to the shared data area

    GetTime             get the value of a millisecond timer



    ________________________________________________________________________
                                                        Appendixes   310
    ________________________________________________________________________


    CALLBACK REFERENCE

    -----------------------------------
    BTOH

    Syntax:
    hdl = btoh(b);

    BOOLEAN b;  /* boolean to convert */
    HANDLE hdl;

    Purpose: The btoh() function converts a boolean value to a handle. The
    handle will contain the text "TRUE" if the value is non-zero, or "FALSE"
    if the value is zero.

    Note: This functions allocates memory that you must free using
    FreeHandle().

    -----------------------------------
    DO

    Syntax:
    Do(hdl);
    HANDLE hdl;     /* handle to command to execute */

    Purpose: The Do() function executes the HyperPAD command contained in
    the handle hdl (just like the built-in HyperPAD do command). You can
    execute any valid PADtalk command except the do command and commands
    having begin...end blocks.

    Examples:

    /* make the command string */
    hdl = stoh("beep 5");

    /* execute the command string */
    Do(hdl);

    /* free the command string */
    FreeHandle(hdl);



    ________________________________________________________________________
                                                        Appendixes   311
    ________________________________________________________________________


    -----------------------------------
    FREEHANDLE

    Syntax:
    FreeHandle(hdl)
    HANDLE hdl;  /* handle to free */

    Purpose: The FreeHandle() function frees a memory handle that was
    allocated using NewHandle().

    Note: You will get unpredictable results if you attempt to free a handle
    that has not been allocated. You must free all handles that you allocate
    in your extension.

    Examples:

    HANDLE hdl;

    hdl = stoh("beep;");
           :
           :
    FreeHandle(hdl);

    -----------------------------------
    FREEPTR

    Syntax:
    FreePtr(ptr);
    PTR ptr;  /* pointer to free */

    Purpose: The FreePtr() function frees a memory allocated using NewPtr().

    Note: It is the responsibility of the extension to free all of the
    pointers that it allocates. Freeing a pointer that has not been
    allocated will cause unpredictable results.



    ________________________________________________________________________
                                                        Appendixes   312
    ________________________________________________________________________


    -----------------------------------
    FTOH

    Syntax:
    hdl = ftoh(d);
    HANDLE hdl;
    double d;    /* float value to convert */

    Purpose: The ftoh() function converts a double to a handle. The returned
    value can be freed using FreeHandle().

    -----------------------------------
    GETEVENT

    Syntax:
    GetEvent(&Msg);
    MSG Msg;  /* message structure to be filled */

    Purpose: The GetEvent() function retrieves the next event from the event
    queue, placing it into the structure Msg.

    Examples:

    MSG Msg;

    GetEvent(&Msg);
    if (Msg.Event == EVENT_KEYPRESS) {
        printf("a key was pressed\n");
    }

    -----------------------------------
    GETFIELDID

    Syntax:
    hdl = GetFieldID(pageorbackground,FieldID);
    BOOLEAN pageorbackground;   /* page or background */
    WORD FieldID;               /* field ID */
    HANDLE hdl;

    Purpose: The GetFieldID() function returns the content of a page or
    background field given its ID. If pageorbackground is TRUE, then FieldID
    specifies a page field.
    Otherwise, FieldID specifies a background field.

    Note: This function returns a duplicate of the content. The returned
    value can be freed using FreeHandle().



    ________________________________________________________________________
                                                        Appendixes   313
    ________________________________________________________________________


    Examples:

    HANDLE hValue;

    /* get background field ID 3 */
    hValue = GetFieldID(FALSE,3);
              :
              :
    FreeHandle(hValue);

    -----------------------------------
    GETFIELDNAME

    Syntax:
    hdl = GetFieldName(pageorbackground,hName);
    BOOLEAN pageorbackground; /* page or bkgd field? */
    HANDLE hName;        /* handle to field name */
    HANDLE hdl;

    Purpose: The GetFieldName() function retrieves the content of a
    background or page field as referenced by its name. If pageorbackground
    is FALSE (zero), then hName specifies a field on the background.
    Otherwise, hName specifies a field on the page.

    Note: This function returns a duplicate of the content. The returned
    value can be freed using FreeHandle().

    Examples:

    HANDLE hName;
    HANDLE hValue;

    /* create a field name */
    hName = stoh("Help");

    /* get the field's value */
    hValue = GetFieldName(TRUE,hName);

    /* get rid of the name */
    FreeHandle(hName);
          :
          :
    /* get rid of the value */
    FreeHandle(hValue);



    ________________________________________________________________________
                                                        Appendixes   314
    ________________________________________________________________________


    -----------------------------------
    GETFIELDNUM

    Syntax:
    hdl = GetFieldNum(pageorbackground,fieldnum);
    BOOLEAN pageorbackground;  /* page or background field? */
    int fieldnum;              /* field number */
    HANDLE hdl;

    Purpose: The GetFieldNum() function retrieves the content of a
    background or page field as referenced by its number.

    If pageorbackground is FALSE, then fieldnum specifies a background
    field. Otherwise, fieldnum specifies the number of the page field. This
    function returns the value contained in the specified field.

    Note: This function returns a duplicate of the content. The returned
    value can be freed using FreeHandle().

    Examples:

    HANDLE hValue;

    hValue = GetFieldNum(TRUE,1); /* get page field 1 */
             :
             :
    FreeHandle(hValue);

    -----------------------------------
    GETGLOBAL

    Syntax:
    hdl = GetGlobal(hGlobalName);
    HANDLE hGlobalName;   /* name of global to get */
    HANDLE hdl;

    Purpose: The GetGlobal() function returns a duplicate of the content of
    a global variable. The returned value can be freed using FreeHandle().

    Examples:

    HANDLE hdl;
    HANDLE hGlobalName;

    /* create name of global */
    hGlobalName = stoh("savedMenuBar");



    ________________________________________________________________________
                                                        Appendixes   315
    ________________________________________________________________________


    /* get its value */
    hdl = GetGlobal(hGlobalName);

    /* free the global name */
    FreeHandle(hGlobalName);
              :
              :
    /* free the value, when done with it */
    FreeHandle(hdl);

    -----------------------------------
    GETSHAREDAREA

    Syntax:
    pShared = GetSharedArea();
    SHAREDPTR pShared;

    Purpose: The GetSharedArea() function returns the pointer to the Shared
    Data Area contained in the HPAD.EXE program. The format for the Shared
    Data Area is described later in this appendix.

    -----------------------------------
    GETTIME

    Syntax:
    sz = GetTime();
    DWORD sz;

    Purpose: The GetTime() function returns the current value of the
    millisecond timer. HyperPAD uses either the system clock or the real
    time clock that are able to tick 1000 times per second. At each tick of
    the clock, HyperPAD increments a value that this function returns. Thus,
    if you call this function twice, the second call will return a larger
    number.

    This function is useful for delays and timing screen effects.

    Examples:

    DWORD t1;

    t1 = GetTime();
          :
          :
    if (GetTime() - t1 > 1000) {
          // at least 1 second has passed
    }



    ________________________________________________________________________
                                                        Appendixes   316
    ________________________________________________________________________


    -----------------------------------
    HANDLESIZE

    Syntax:
    sz = HandleSize(hdl);
    HANDLE hdl;   /* handle to block of memory */
    int sz;

    Purpose: The HandleSize() function determines the size in bytes of a
    handle.

    Examples:

    HANDLE hdl;

    hdl = stoh("This is a handle");
    printf("%u",handlesize(hdl));
    FreeHandle(hdl);

    -----------------------------------
    HIDEMOUSE

    Syntax:
    HideMouse();

    Purpose: The HideMouse() function hides the mouse. You must hide the
    mouse before writing directly to the screen (with PutCh(), MakeWin(),
    etc.).

    Note: If there is no mouse, calling this routine will have no effect.

    -----------------------------------
    HIGHLINE

    Syntax:
    HighLine(x1,x2,y,attr,Screen);
    int x1,x2,y;       /* coordinates of line */
    int attr;          /* attribute for the line */
    PACKETPTR Screen;  /* description of screen */

    Purpose: The HighLine() function changes the attribute of the line
    defined from point (x1,y) to point (x2,y) (in other words - highlight a
    line). The attribute lies within a range of 0 to 255.  The range of the
    values for the two points is defined by the screen driver.

    Note: Attribute 7 (light grey) will appear on all video card/monitor
    combinations as white on black.  Attribute 112 will appear as reverse
    video on all video card/monitor combinations.  All other attributes
    cannot be guaranteed to appear on other hardware combinations.



    ________________________________________________________________________
                                                        Appendixes   317
    ________________________________________________________________________


    Examples:

    The following code fragment controls a highlighted bar in a region
    defined by the rectangle (x1,miny)-(x2,maxy).

    #include "extern.h"
    #include "keycodes.h"

    BOOLEAN Done = FALSE;
    int x1 = 10,x2 = 70,y = 5;
    int maxy = 5,miny = 10;
    int newy;
    MSG Msg;

    HideMouse();
    HighLine(x1,x2,y,112,Screen);      /* bar on */
    ShowMouse();
    while (!Done) {
        GetEvent(&Msg)
        switch (Msg.Event) {
        case EVENT_KEYPRESS:
            switch (Msg.KeyWord) {
            case kb_ENTER:
            case kb_ESCAPE:
                Done = TRUE;
                break;
            case kb_UP:
                if (y > miny) y--;
                else y = maxy;
                break;
            case kb_DOWN:
                if (y < maxy) y++;
                else y = miny;
                break;
            }
            break;
        }

        if (newy != y) {
            HideMouse();
            HighLine(x1,x2,y,7,Screen);   /* turn off */
            y = newy;
            HighLine(x1,x2,y,112,Screen); /* turn on */
            ShowMouse();

        }
    }



    ________________________________________________________________________
                                                        Appendixes   318
    ________________________________________________________________________


    -----------------------------------
    HTOB

    Syntax:
    bool = htob(hText);
    HANDLE hText;   /* handle to text boolean value */
    BOOLEAN bool;

    Purpose: The htob() function converts a handle passed from HPAD to a
    boolean (TRUE or FALSE). The function returns zero if the handle
    contains the word "FALSE" and a non-zero value otherwise.

    -----------------------------------
    HTOF

    Syntax:
    d = htof(hdl);
    HANDLE hdl;  /* handle to text float value */
    double d;


    Purpose: The htof() function converts a handle to a double.

    -----------------------------------
    HTOI

    Syntax:
    i = htoi(hText);
    HANDLE hText;       /* handle to some text */
    int i;

    Purpose: The htoi() function converts a handle passed from HPAD to an
    integer (an integer is a 2 byte quantity).

    -----------------------------------
    HTOL

    Syntax:
    l = htol(hText);
    HANDLE hText;  /* handle to text long value */
    long l;



    ________________________________________________________________________
                                                        Appendixes   319
    ________________________________________________________________________


    Purpose: The htol() function converts a handle passed from HPAD to a
    long integer (a long integer is a 4 byte quantity).

    -----------------------------------
    HTOS

    Syntax:
    s = htos(hText);
    HANDLE hText;  /* handle to text */
    STRING s;

    Purpose: The htos() function converts a handle passed from HPAD to a
    string. This function does nothing more than dereference the handle.
    Thus, the following statements are equivalent:

         ptr = *hText;
         ptr = htos(hText);
         ptr = deref(hText);

    -----------------------------------
    ITOH

    Syntax:
    hdl = itoh(i);
    int i;    /* integer to convert */
    HANDLE hdl;

    Purpose: The itoh() function converts an integer to a handle.

    Note: This function allocates memory that you must free using
    FreeHandle().



    ________________________________________________________________________
                                                        Appendixes   320
    ________________________________________________________________________


    -----------------------------------
    LOCKHANDLE

    Syntax:
    ptr = LockHandle(hdl);
    HANDLE hdl;  /* handle to be locked */
    PTR ptr;

    Purpose: The LockHandle() function freezes the memory block's position
    so that it will not move (until it is either freed using FreeHandle() or
    unlocked using UnLockHandle()). This is useful if you want to access the
    memory block using a pointer, instead of a handle. There may be some
    space and speed savings depending on the number of accesses to the
    memory block.

    The LockHandle() function returns a pointer to the memory.

    Example:

    HANDLE hdl;
    PTR p;

    hdl = stoh("This is a handle");
    p = LockHandle(hdl);
           :
    printf("%s",p);
           :
    FreeHandle(hdl);

    -----------------------------------
    LTOH

    Syntax:
    hdl = ltoh(l);
    long l;     /* long value to convert */
    HANDLE hdl;

    Purpose: The ltoh() function converts a long to a handle.

    Note: This function allocates memory that you must free using
    FreeHandle().



    ________________________________________________________________________
                                                        Appendixes   321
    ________________________________________________________________________


    -----------------------------------
    MAKEWIN

    Syntax:
    MakeWin(x1,y1,x2,y2,attr,Screen);
    int x1,y1,x2,y2;         /* window coordinates */
    int attr;                /* window attribute 0..255 */
    PACKETPTR Screen;        /* pointer to video packet */

    Purpose: The MakeWin() function creates a removable rectangular window
    with the upper left corner at (x1,y1) and the lower right corner at
    (x2,y2) on the screen described by Screen.
    The attribute of the window is specified in the attr parameter and has a
    valid range from 0 to 255.

    You can create many windows that overlap. The windows are remembered in
    a window stack; you can remove windows only in the order that they were
    created.

    Screen output is NOT clipped within the active window.  For example,
    PutCh() and PutStr() functions will write anywhere on the screen,
    regardless of any window that may be open.

    Examples:

    PACKETPTR Screen;
    SHAREDPTR pShared;

    /* get a screen packet */
    pShared = GetSharedArea();
    Screen = pShared -> pVideoPackets[0];

    /* make a window with color white on blue (31) */
    MakeWin(10,10,70,20,31,Screen);
              :
              :
    /* remove the window */
    RemWin()



    ________________________________________________________________________
                                                        Appendixes   322
    ________________________________________________________________________


    -----------------------------------
    NEWHANDLE

    Syntax:
    hdl = NewHandle(NumBytes);
    int NumBytes;  /* number of bytes to allocate */
    HANDLE hdl;

    Purpose: The NewHandle() function allocates a block of movable memory.
    The NumBytes parameter specifies the size of the memory block in bytes.

    -----------------------------------
    NEWPTR

    Syntax:
    p = NewPtr(NumBytes);
    int NumBytes; /* number of bytes to allocate */
    PTR p;

    Purpose: The NewPtr() function allocates a memory block accessible via a
    pointer. This function is similar to the C function malloc(). All memory
    allocated using NewPtr() must be freed using FreePtr().

    -----------------------------------
    PEEKEVENT

    Syntax:
    PeekEvent(&Msg);
    MSG Msg;  /* message structure to fill out */

    Purpose: The PeekEvent() function copies the next event from the event
    queue into the message structure. The event will not be removed from the
    event queue. PeekEvent() is equivalent to:

    GetEvent(&Msg);
    UnGetEvent(&Msg);

    /* Msg now has the next event */
    Use PeekEvent() to examine the next event without disturbing it.

    Examples:

    The following code fragment waits for a mouse button to be pressed. If a
    mouse button is already pressed, the loop is skipped.



    ________________________________________________________________________
                                                        Appendixes   323
    ________________________________________________________________________


    MSG Msg;

    PeekEvent(&Msg);    /* look at the next event */
    if (!Msg.Buttons) {
      GetEvent(&Msg);
      PeekEvent(&Msg);
    }

    -----------------------------------
    PTRSIZE

    Syntax:
    sz = PtrSize(ptr);
    PTR ptr;  /* pointer to memory block */
    WORD sz;

    Purpose: The PtrSize() function retrieves the size of a pointer. This
    function returns the exact number of bytes of the memory allocation
    requested using NewPtr().

    -----------------------------------
    PUTATTR

    Syntax:
    PutAttr(x,y,attr,Screen);
    int x,y;          /* where */
    int attr;         /* attribute to put there */
    PACKETPTR Screen; /* description of screen */

    Purpose: The PutAttr() function writes an attribute directly to the
    screen.

    Examples:

    int i;

    for (i=1;i < Width;i++) {
        PutCh(i,1,196,Screen);    /* write a '-' */
        PutAttr(i,1,112,Screen);  /* reverse video */
     }



    ________________________________________________________________________
                                                        Appendixes   324
    ________________________________________________________________________


    -----------------------------------
    PUTCH

    Syntax:
    PutCh(x,y,ch,Screen);
    int x,y;          /* where */
    int ch;           /* character to put there */
    PACKETPTR Screen; /* description of the screen */

    Purpose: The PutCh() function writes a character (ch) to the screen
    (Screen) at the location defined by (x,y).

    Examples:

    int i;

    for (i=1;i < Width;i++)
        PutCh(i,1,196,Screen);   /* write a line of '-' */

    -----------------------------------
    PUTSTR

    Syntax:
    PutStr(x,y,str,Screen);
    int x,y;            /* place to put the string */
    STRING str;         /* pointer to string to print */
    PACKETPTR Screen;   /* pointer to screen information */

    Purpose: The PutStr() function places a string at the given location on
    the screen.

    Examples:

    int i;
    PACKETPTR Screen;
           :
           :

    for (i=1;i < Height;i++) {
        PutStr(1,i,"Hello World",Screen);
    }



    ________________________________________________________________________
                                                        Appendixes   325
    ________________________________________________________________________


    -----------------------------------
    REALLOCHANDLE

    Syntax:
    ReAllocHandle(hdl,newsz);
    HANDLE hdl;  /* handle to memory block */
    WORD newsz;  /* new size (in bytes) */

    Purpose: The ReAllocHandle() function changes the size of a handle. The
    handle will remain the same, but the memory block referenced by the
    handle will change.

    Examples:

    HANDLE hdl

    hdl = NewHandle(100);     // allocate a handle
    p = deref(hdl);           // get local pointer
              :
              :
    ReAllocHandle(hdl,200);   // make handle bigger
    p = deref(hdl);           // must reassign p because
                              // it changed!

    Note: After you reallocate a handle, you must re-assign any local
    pointers you have to that handle.

    -----------------------------------
    REFRESH

    Syntax:
    Refresh();

    Purpose: The Refresh() function redraws the current page on the display.



    ________________________________________________________________________
                                                        Appendixes   326
    ________________________________________________________________________


    -----------------------------------
    RELEASEHPAD

    Syntax:
    ReleaseHpad();

    Purpose: The ReleaseHPAD() function causes HyperPAD to give up control
    of the screen, keyboard, mouse, and timer. After calling ReleaseHPAD(),
    an extension can change the video mode, read from the keyboard, or use
    the mouse.

    Note: RestoreHPAD() must be called before control is returned to
    HyperPAD. After you call ReleaseHPAD(), the following callback functions
    will not work:

    GetEvent()
    UnGetEvent()
    PeekEvent()
    ShowMouse()
    HideMouse()


    -----------------------------------
    REMWIN

    Syntax:
    RemWin();

    Purpose: The RemWin() function removes the most recently opened window
    created with MakeWin().

    See Also: MakeWin();

    -----------------------------------
    RESTOREHPAD

    Syntax:
    RestoreHpad();

    Purpose: The RestoreHPAD() function restores the keyboard, timer, mouse,
    and video mode that was previously given up by calling ReleaseHPAD().
    This function will reset the video mode back to the mode appropriate for
    the current pad.



    ________________________________________________________________________
                                                        Appendixes   327
    ________________________________________________________________________


    -----------------------------------
    RETURNVALUE

    Syntax:
    ReturnValue(hdl);
    HANDLE hdl;  /* handle to text value */

    Purpose: The ReturnValue() function returns a value to HPAD.  All values
    returned to HyperPAD must be in the form of a handle to text.  The
    conversion routines can be used to assist in converting data to a handle
    suitable for return to HyperPAD.

    Examples:

    To return an integer:

    ReturnValue(itoh(10));

    To return a string:

    ReturnValue(stoh("Hello World"));

    To return a boolean value:

    ReturnValue(btoh(FALSE));



    ________________________________________________________________________
                                                        Appendixes   328
    ________________________________________________________________________


    -----------------------------------
    SENDHPMSG

    Syntax:
    SendHPMsg(hMsgName,NumArgs,...);
    HANDLE hMsgName;    /* handle to message name */
    int NumArgs;        /* number of arguments to follow */

    Purpose: The SendHPMsg() function sends a message directly to HyperPAD.
    hMsgName is a handle to the message name, like "select" or "keypress".
    NumArgs specifies the number of arguments that follow (each argument
    must be a handle to text). You can pass any number of arguments, as long
    as NumArgs specifies the correct number.

    Note: For assembly programmers, you must clean up the stack depending on
    how many arguments you passed. If there are no arguments, pass 0 for
    NumArgs.

    Examples:

    HANDLE hMsgName;
    HANDLE hArg1,hArg2;

    /* create message to send */
    hMsgName = stoh("myhandler");

    hArg1 = itoh(10);
    hArg2 = itoh(20);

    /* send message and arguments */
    SendHPMsg(hMsgName,2,hArg1,hArg2);

    /* free up message name and arguments */
    FreeHandle(hMsgName);
    FreeHandle(hArg1);
    FreeHandle(hArg2);



    ________________________________________________________________________
                                                        Appendixes   329
    ________________________________________________________________________


    -----------------------------------
    SENDPAGEMSG

    Syntax:
    SendPageMsg(hMessage,NumArgs,...);
    HANDLE hMessage;         /* handle to message name */
    int NumArgs;             /* number of arguments */

    Purpose: The SendPageMsg() function sends a message to the current page.
    The hMessage parameter is a handle to the message name, like select or
    keypress. NumArgs specifies the number of arguments that follow (each
    argument must be a handle to text). You can pass any number of
    arguments, as long as NumArgs specifies the correct number.

    Note: For assembly programmers, you must clean up the stack depending on
    how many arguments you passed. If there are no arguments, pass 0 for
    NumArgs.

    Examples:

    HANDLE hMsgName;
    HANDLE hArg1,hArg2;

    /* what message to send */
    hMsgName = stoh("myhandler");

    hArg1 = itoh(10);
    hArg2 = itoh(20);

    /* send the message and passed parameters */
    SendPageMsg(hMsgName,2,hArg1,hArg2);

    /* free up the message and passed parameters */
    FreeHandle(hMsgName);
    FreeHandle(hArg1);
    FreeHandle(hArg2);



    ________________________________________________________________________
                                                        Appendixes   330
    ________________________________________________________________________


    -----------------------------------
    SETFIELDID

    Syntax:
    SetFieldID(pageorbackground,FieldID,hValue);
    BOOLEAN pageorbackground; /* page or bkgnd field? */
    WORD FieldID;             /* ID of field to set */
    HANDLE hValue;            /* new content for this field */

    Purpose: The SetFieldID() function sets the content of a field based on
    its ID. If pageorbackground is FALSE then FieldID specifies the ID of a
    background field. Otherwise, FieldID specifies the ID of a page field.
    The hValue parameter is a handle to the new content of this field.

    Examples:

    HANDLE hdl;

    hdl = stoh("This is new content for field 1");

    /* set the field's content */
    SetFieldID(FALSE,4,hdl);

    FreeHandle(hdl);

    -----------------------------------
    SETFIELDNAME

    Syntax:
    SetFieldName(pageorbackground,hName,hValue);
    BOOLEAN pageorbackground; /* page or bkgd field? */
    HANDLE hName;             /* handle to name of field */
    HANDLE hValue;            /* handle to value to set */

    Purpose: The SetFieldName() function sets the content of a field given
    its name. If pageorbackground is FALSE, then hName specifies the name of
    a background field. Otherwise, hName specifies the name of a page field.
    The hValue parameter is a handle to the new value of the field.



    ________________________________________________________________________
                                                        Appendixes   331
    ________________________________________________________________________


    Examples:

    HANDLE hName;
    HANDLE hValue

    /* name of the field */
    hName = stoh("Help Window");

    /* create a new content */
    hValue = stoh("press SPACE to continue");

    /* set page field hName */
    SetFieldName(TRUE,hName,hValue);

    FreeHandle(hValue);
    FreeHandle(hName);

    -----------------------------------
    SETFIELDNUM

    Syntax:
    SetFieldNum(pageorbackground,FieldNum,hValue);
    BOOLEAN pageorbackground;  /* page or background */
    int FieldNum;              /* field number */
    HANDLE hValue;             /* value to set */

    Purpose: The SetFieldNum() function sets the content of a page or
    background field given a field's number. If pageorbackground is FALSE,
    FieldNum specifies a background field. Otherwise, FieldNum specifies a
    page field. The hValue parameter is a handle to the new field's content.

    Examples:

    HANDLE hdl

    /* create a value */
    hdl = stoh("This is new field content");

    /* set page field 1 to this value */
    SetFieldNum(TRUE,1,hdl);

    /* free the value */
    FreeHandle(hdl);



    ________________________________________________________________________
                                                        Appendixes   332
    ________________________________________________________________________


    -----------------------------------
    SETGLOBAL

    Syntax:
    SetGlobal(hGlobalName,hValue);
    HANDLE hGlobalName; /* handle to name of global */
    HANDLE hValue;      /* handle to value of global */

    Purpose: The SetGlobal() function sets the value of a global variable
    referenced by the name hGlobalName to the value hValue. If the global
    variable does not exists, it will be created.

    Examples:

    HANDLE hGlobalName;
    HANDLE hValue;

    /* create name of global to set value of */
    hGlobalName = stoh("savedmenubar");

    /* create the new value */
    hValue = btoh("FALSE");

    /* set the global to the new value */
    SetGlobal(hGlobalName,hValue);

    /* free the value and global name */
    FreeHandle(hGlobalName);

    -----------------------------------
    SHOWMOUSE

    Syntax:
    ShowMouse();

    Purpose: The ShowMouse() function shows the mouse after hiding the mouse
    using HideMouse().

    Note: This routine has no effect if you don't have a mouse or the mouse
    is already displayed.



    ________________________________________________________________________
                                                        Appendixes   333
    ________________________________________________________________________


    -----------------------------------
    STOH

    Syntax:
    hdl = stoh(str);
    STRING str;  /* pointer to string to convert */
    HANDLE hdl;

    Purpose: The stoh() function converts a string to a handle. This
    function essentially allocates a block of memory and copies the string
    into it.

    Note: The returned value must be freed using FreeHandle().

    -----------------------------------
    UNGETEVENT

    Syntax:
    UnGetEvent(&Msg);
    MSG Msg;  /* filled out message structure */

    Purpose: The UnGetEvent() function places the event structure Msg at the
    beginning of the event queue such that it is the next event to be
    retrieved.

    Examples:

    The following code fragment fakes a keyboard event that never happened
    (the press of the ENTER key):

    MSG Msg;

    PeekEvent(&Msg);    // set the Msg fields
    Msg.ShiftState = 0;
    Msg.Event = EVENT_KEYPRESS;
    Msg.KeyWord = kb_ENTER;
    Msg.AsciiCode = 13;
    Msg.ScanCode = 28;



    ________________________________________________________________________
                                                        Appendixes   334
    ________________________________________________________________________


    -----------------------------------
    UNLOCKHANDLE

    Syntax:
    UnLockHandle(hdl);
    HANDLE hdl;  /* handle to memory block */

    Purpose: The UnLockHandle() function unlocks a handle that has been
    locked using Lockhandle(). This allows the memory block to move during
    subsequent memory allocations. Another way to unlock a handle is to free
    it using FreeHandle() (which will free and unlock the handle).

    Examples:

    HANDLE hdl;

    hdl = stoh("This is a handle");
    LockHandle(hdl);
         :
         :
    UnLockHandle(hdl);
    FreeHandle(hdl);



    ________________________________________________________________________
                                                        Appendixes   335
    ________________________________________________________________________


    C ROUTINES DEFINED IN HYPERPAD

    The following standard C routines are implemented as HyperPAD callback
    routines:

    printf()
    sprintf()


    USING FLOATING POINT MATH

    You can use floating point math within C extensions in HyperPAD version
    V1.00C or later. To use floating point, you must use the default
    floating point library (/FPi). Internally, the C compiler generates
    inline floating point calls using interrupts. The interrupt service
    routines are contained within HyperPAD itself, so your extensions will
    be small. Many of the floating point functions are defined as callback
    functions.

    The following math functions are defined in HyperPAD:

    Since extensions share HyperPAD's stack, functions declared pascal
    cannot return double values (because functions declared pascal return
    values local to the DS of the extension, which is different from
    HyperPAD's DS). Functions that return double values must be declared as
    C functions. For example, the following function will not work
    correctly:

    double pascal sample()
    {
    }
    The function must be rewritten as:
    double sample()
    {
    }



    ________________________________________________________________________
                                                        Appendixes   336
    ________________________________________________________________________


    DATA STRUCTURES USED BY EXTENSIONS

    HyperPAD's data structures that extensions may access are:

    DataStructure:        Description:
    --------------------------------------------------------
    Function pool         This structure declares information about the
                          handlers and functions contained in the extension.

    Video packet          This structure, located in HyperPAD, defines
                          information about the screen.

    Message               This describes the structure of a HyperPAD event
                          stored in the event queue.

    Shared Data Area      This structure, located in HyperPAD, defines
                          variables relevant to the HyperPAD environment.



    ________________________________________________________________________
                                                        Appendixes   337
    ________________________________________________________________________


    FUNCTION POOL

    The function pool is used to communicate the names, entry points, and
    type of routines that you have declared in your extension. When your
    extension is loaded, HyperPAD looks at this table and dynamically binds
    the handlers and functions that you have declared with the scripts in
    memory. It has the following definition:

    typedef struct {
         STRING Name;        /* name of this procedure */
         RTN    EntryPoint;  /* pointer to function */
         WORD   MsgNum;      /* relocated message number */
         WORD   MsgType;     /* FUNCTION or HANDLER */
    } POOL, *POOLPTR;

    The function pool is declared as follows (with a NULL entry at the end
    to signify the end of the table):

     POOL pascal Pool[] = {
         {    "Sample",      /* first entry */
              Sample,
              0,
              HANDLER   },

         {    NULL,          /* end of table */
              NULL,
              0,
              0    }    };



    The MsgType field can be one of two values:



    ________________________________________________________________________
                                                        Appendixes   338
    ________________________________________________________________________


    VDEO PACKET

    The video packet is a structure containing screen information, such as
    where the video segment is, the width, height, bytes per line, and some
    other information. A pointer to a video packet is necessary to use any
    of the callbacks that access the screen. It has the following structure:

    typedef struct PacketStruct {
         PTR  Screen;         /* screen */
         BYTE bpl;            /* bytes/line */
         BYTE Height;         /* height of screen */
         BYTE Width;          /* width of screen */
         BYTE Flag;           /* flag - booleans */
         RTN  SetMode;        /* routine to set mode */
         RTN  CursorOFF;      /* turns cursor off */
         RTN  CursorThin;     /* makes cursor thin */
         RTN  CursorFat;      /* makes cursor full height */
         RTN  ModeAvail;      /* is this mode available? */
    } PACKET, *PACKETPTR;

    A pointer to the video packets is contained in the Shared Data Area. To
    create a local copy, use the following code:

    SHAREDPTR pShared;       /* pointer to shared data */
    PACKETPTR Screen;        /* my video packet */
    pShared = GetSharedArea();

    /* get driver 0 */
    Screen = pShared -> VideoPackets[0];

    You can then use the packet for modifying the screen. For example:

    /* create a window */
    MakeWin(10,10,70,20,31,Screen);

    /* put a title on it */
    PutStr(13,10,"[ Window Title ]",Screen);

    The coordinates of the screen are within the following range:

    1  <= x  <= screen width
    1  <= y  <= screen height



    ________________________________________________________________________
                                                        Appendixes   339
    ________________________________________________________________________


    MESSAGE

    The message structure contains the description of a keyboard or mouse
    event. It has the following format:

    typedef struct {
         BYTE Event;              /* event */
         BYTE ShiftStatus;        /* shift status */
         BYTE MouseX;             /* mouse x coordinate */
         BYTE MouseY;             /* mouse y coordinate */
         BYTE Buttons;            /* mouse buttons */
         WORD KeyWord;            /* the keyword - if */
                                  /*  Event == KEYPRESS */
         BYTE AsciiCode;          /* ASCII code */
         BYTE ScanCode;           /* scan code */
    } MSG, *MSGPTR, **MSGHANDLE;

    The types of events that can occur are as follows:

    EVENT_IDLE
    EVENT_LEFTBUTTONDOWN
    EVENT_RIGHTBUTTONDOWN
    EVENT_LEFTBUTTONUP
    EVENT_RIGHTBUTTONUP
    EVENT_KEYPRESS
    EVENT_DOUBLECLICK



    ________________________________________________________________________
                                                        Appendixes   340
    ________________________________________________________________________


    THE EVENT QUEUE

    The event queue is a buffered stack of mouse and keyboard events. When
    the pad user presses a key or moves the mouse, the event and other
    pertinent data is inserted into the event queue at the end. Extensions
    have the ability to peek, get, and unget events from the event queue.

    For example, when the user presses ESC, an event is generated and the
    structure is filled out as follows:

    Event:          Returns:
    --------------------------------------------------------------------
    ShiftStatus     the status of the SHIFT, CTRL, and ALT keys at the
                    time of the event

    MouseX          the mouse x position at the time the key was pressed

    MouseY          the mouse y position at the time the key was pressed

    Buttons         the status of the mouse buttons at the time of the
                    event:
                    0=no buttons down,
                    1=left button down,
                    2=right button down,
                    3=both buttons down

    KeyWord         kb_ESC (as defined in the include file keycodes.h)

    AsciiCode       The ASCII code for this key (in this case=27)

    ScanCode        The scan code for this key (in this case=1)



    ________________________________________________________________________
                                                        Appendixes   341
    ________________________________________________________________________


    When the left mouse button is pressed, the structure is filled as
    follows: 

    Function:           Description:
    --------------------------------------------------------
    ShiftStatus         This status of the shift keys at the time the
                        button was pressed

    MouseX, MouseY      The mouse position where the left button was pressed

    KeyWord, AsciiCode, Not used for mouse events
    ScanCode

    Note: The event EVENT_IDLE is returned by GetEvent() whenever the event
    buffer is empty. The valid fields are: Buttons, ShiftStatus, MouseX,
    MouseY.

    ShiftStatus is bit defined as follows:

    Bit No.:      Returned when:
    ---------------------------------------
    bit 0         right SHIFT key pressed

    bit 1         left SHIFT key pressed

    bit 2         CTRL key pressed

    bit 3         ALT key pressed
    The following is a C routine that uses the event buffer to wait for a
    key. Notice that the keypress event remains in the event queue after
    this routine exits.

    WaitForKey()
    {
         MSG Msg;
         do {
              GetEvent(&Msg);
         } while (Msg.Event != EVENT_KEYPRESS);
         UnGetEvent(&Msg);
    }



    ________________________________________________________________________
                                                        Appendixes   342
    ________________________________________________________________________


    SHARED DATA AREA

    The Shared Data Area is a structure contained within the HPAD.EXE
    program that contains program name, video driver information, and
    command line information. The format of this area is as follows:

    typedef struct {
         BYTE flags;                      /* 0   */
         DWORD CmdLineBits;               /* 1   */
         char program_parms[128];         /* 5   */
         char program_name[80];           /* 133 */
         char spawn_name[80];             /* 213 */
         char spawn_parms[128];           /* 293 */
         char saved_pad[80];              /* 421 */
         BYTE return_code;                /* 501 */
         BYTE CardType[2];                /* 502 */
         BYTE MonitorType[2];             /* 504 */
         BYTE CardMem[2];                 /* 506 */
         char CardName[30];               /* 508 */
         PACKETPTR *pVideoModes;          /* 538 */
         int (pascal far *StartRtn)();    /* 542 */
         int (pascal far *StopRtn)();     /* 546 */
         int (pascal far *SaveKey)(WORD); /* 550 */
         char OriginalDir[64];            /* 554 */
         WORD EnvSeg;                     /* 618 */
         DWORD SerialNo;                  /* 620 */
         WORD EnvSegSz;                   /* 624 */
         RTN SetNorm;                     /* 626 */
         DWORD Reserved;                  /* 630 */
         PTR TradeNamePtr;                /* 634 */
    } SHARED,*SHAREDPTR;

    When you run HPAD from the DOS command line, the HPAD.EXE program
    determines the program parameters, video card information, and available
    video modes and remembers this information in the Shared Data Area. The
    other fields in the Shared Data Area are used when HyperPAD runs another
    application, and are useless to the extension.



    ________________________________________________________________________
                                                        Appendixes   343
    ________________________________________________________________________


    The useful fields in the Shared Data Area are described below: 

    Field:           Description:
    ---------------------------------------------------------------------
    Flags            A set of six Booleans in the bits of the Flag byte
                     (see the following table)

    CmdLineBits      Contains bits representing which command line
                     parameters the user supplied on the command line

    programParms     The original program command line

    programName      The name of the program, including the directory from
                     which it was run

    CardType         Contains the video card(s) installed in the computer.
                     CardType[0] is the primary adapter.

    MonitorType      Contains the moniter type(s) attached to the video
                     card(s)

    CardMem          Contains the amount of memory on each of the video
                     card(s)

    pVideoModes      Pointer to an array of video screen drivers.
                     pVideoPacket[0] is the default driver. This is the only
                     way to get a video packet from within an extension.

    StartRtn         Routine to start playback of keys in the recorded
                     keystroke buffer

    StopRtn          Routine to stop the playback of recorded keys from the
                     keystroke buffer

    SaveKey          Routine to save a key in the keystroke buffer of
                     HPAD.EXE

    OriginalDir      Saved directory to change to if returning to HyperPAD
                     from a launched program

    EnvSeg           Segment of HyperPAD's copy of the DOS environment

    SerialNo         The serial number of this copy of the HyperPAD Reader.

    EnvSegSz         Number of bytes for the environment. This can be larger
                     than the environment, leaving room for expansion.

    SetNorm          Routine to set the normal 80x25 text mode on exit.

    TradeNamePtr     Pointer to the title of HyperPAD. Examining this string
                     will determine if you are running in the Reader,
                     HyperPAD Easy, or HyperPAD.



    ________________________________________________________________________
                                                        Appendixes   344
    ________________________________________________________________________


    The Flags byte is set up as follows:

    Bit No.        Description:
    -----------------------------------------------------------------
    bit 0          1 = exiting to DOS,
                   0 = executing another program

    bit 1          1 = pause after launching program,
                   0 = return to HPAD immediately after launching program

    bit 2          1 = mouse installed,
                   0 = no mouse

    bit 3          1 = first time HyperPAD was loaded,
                   0 = HyperPAD has run another program at least once

    bit 4          1 = don't disturb the screen if running another program,
                   0 = clear screen before launching program, set screen
                       when returning from launching another program

    bit 5          1 = DesqView is present,
                   0 = DesqView is not present



    ________________________________________________________________________
                                                        Appendixes   345
    ________________________________________________________________________


    The CmdLineBits field contains bits representing which command line
    parameters were specified when HyperPAD was loaded from the command
    line. If a bit is set, then the corresponding command line parameter was
    used.

    Bit No.        Description:
    -----------------------------------------------
    bit 0          /NOMSG

    bit1           /25

    bit 2          /43

    bit 3          /50

    bit 4          /NOSHOW

    bit 5          /NOMOUSE

    bit 6          /NOIDLE

    bit 7          /MONO

    bit 8          /LCD

    bit 9          /B&W

    bit 10         /GREY

    bit 11         /COLOR

    bit 12         /AUTOSAVE

    bit 13         reserved

    bit 14         /NOKB

    bit 15         /NO15

    bit 16         /ENHANCEDKB

    bit 17         /NORTC

    bit 19         /NOEM



    ________________________________________________________________________
                                                        Appendixes   346
    ________________________________________________________________________

    This page left blank intentionally



    ________________________________________________________________________
                                                        Appendixes   347
    ________________________________________________________________________

    APPENDIX 4: SUPPORT FOR SHOW PARTNER F/X


    INTRODUCTION

    Brightbill-Roberts, makers of HyperPAD, also publishes a popular family
    of programs for creating screen shows for display on IBM Enhanced
    Graphics Adapter (EGA), MultiColor Graphics Array (MCGA), Video Graphics
    Array (VGA), and Hercules monochrome systems. HyperPAD 2.0 supports
    images and screen shows created by Show Partner F/X, Show Partner, and
    PC Partner. Using HyperPAD's fxshow command, you can now view graphic
    presentations, demos, and animations from within HyperPAD.


    SHOW PARTNER FILE TYPES

    HyperPAD 2.0 supports the screen show and image files listed in the
    following table. These files can be run from within HyperPAD using a
    special program called FXSHOW, which is included in your HyperPAD
    package:

    File Type:      Description:
    ----------------------------------------------------------------------
    .GX2            The .GX2 file format is a popular standard for storing
                    color images. Brightbill-Roberts' Show Partner F/X,
                    Show Partner, and PC Partner create .GX2 files. Lotus
                    Freelance Plus and Ashton-Tate Applause II also create
                    .GX2 images that HyperPAD can use.

    .PRO            The .PRO file format is used for the scripts created by
                    Show Partner F/X to control screen shows.

    .PR2            The .PR2 file format is the result of using the F/X
                    Master Maker utility to master a .PRO script file. By
                    mastering a script, a Show Partner F/X user prevents
                    anyone from changing the screen show in any way.

    .SLD            The .SLD file format is used by PC Partner, a limited
                    version of Show Partner F/X that is bundled with many
                    LCD display devices.



    ________________________________________________________________________
                                                        Appendixes   348
    ________________________________________________________________________


    USING THE FXSHOW COMMAND

    HyperPAD supports the files listed above with a special program called
    FXSHOW, which is included in your HyperPAD package. To use FXSHOW with
    HyperPAD,  youmust have already created images or screen shows with one
    of the products listed above.

    When you start HyperPAD, it looks in its home directory for a file
    called FXSHOW.EXE; when you ran SETUP, this file was copied to the
    HyperPAD home directory for you. If HyperPAD located FXSHOW, an
    additional credit will appear at the bottom of the screen:

 Ŀ
                                                                        
  **** The Printed Documentation has a picture or screen shot here **** 
                                                                        
 
    

    If HyperPAD was successful in locating this file, you can then use the
    fxshow command, which is described in Chapter 11, "Commands". When you
    use the fxshow command, HyperPAD shrinks down to 3K and runs FXSHOW.EXE,
    passing it the file to view.

    Specifying a SLD, PRO, or PRO file causes HyperPAD to view that file and
    then return to HyperPAD at the point where you left off. (If you need to
    perform some extra commands upon returning to HyperPAD, include them in
    a resume handler on that page).

    You can also specify GX2 files to view. In this case, HyperPAD assembles
    a show from the GX2 files that you specified and begins cycling them.
    When the you have viewed all of the GX2 files, control is returned to
    HyperPAD. If you press ESC during the show, FXSHOW temporarily stops the
    show and displays a list of the GX2 files in the show that it created.
    At this point, you can press ESC again and return to HyperPAD, or
    highlight a GX2 file in the list and continue the show.



    ________________________________________________________________________
                                                        Appendixes   349
    ________________________________________________________________________


    APPENDIX 5: HYPERPAD UTILITIES

    EXTENSION MOVER

    The MOVER.EXE program copies an extension into a pad, deletes an
    extension from a pad, or replaces an existing extension in a pad with
    another extension having the same name. Adding extensions to a pad
    increases the pad size by the size of the extension, plus a small amount
    of code size.

    mover <pad name> replace | add | delete <extension name>

    mover <pad name>

    Examples:

    The following example moves an extension called TEST.EXE into the Home
    pad:

    mover home add test

    To replace the extension in the phone pad called "lookup" with a new
    copy:

    mover phone replace lookup

    mover phone rep lookup

    To delete an extension from the Home pad called "rtns":

    mover delete rtns

    mover home del rtns

    To get a list of the extensions (and the handlers and function defined
    in those extensions) just supply the name of the pad. The following
    example lists the extension information in the Home pad:

    mover home

    If you don't supply an extension, HyperPAD assumes ".PAD" for pads and
    ".EXE" for extensions.

    See Appendix 3 for more information about writing extensions.



    ________________________________________________________________________
                                                        Appendixes   350
    ________________________________________________________________________


    PAD INFO

    The PADINFO.EXE program prints out information about you pad. The
    following information is listed:

    Information:                  Explanation:
    ------------------------------------------------------------------
    Pad Name                      Full DOS pathname of the pad.

    Pad access                    Either read/write (for normal pads) or
                                  read only for pads with the Can't Modify
                                  option set in the Protect dialog box.

    Can't delete pad              Indicates if the Can't Delete option is
                                  checked in the Protect dialog box.

    Home pad                      Yes if the pad is a Home pad.

    Access by password only       Yes if the By password only option is set
                                  in the Protect dialog box.

    User Level                    1 to 5 depending on the user level.

    PADINFO will also tell you if the pad is serialized. The serial number
    is used by the Reader.

    At the end of the above information, PADFINO lists the extensions, the
    extension size, the extension version number, and the handlers and
    function that are within each extension.


    STRIP

    The STRIP.EXE program removes the text portion of all of the scripts of
    a pad. This utility is useful if you want to distribute your pads
    without revealing how the pad was created.

    strip ad name

    Examples:

    strip home.pad

    strip phone.pad

    To remove the scripts from all of the pads in a directory:

    strip *.pad

    If you attempt to access a script after the text has been removed,
    HyperPAD will display the error "Cannot edit mastered script".



    ________________________________________________________________________
                                                        Appendixes   351
    ________________________________________________________________________


    If you want to remove a single script from a button or field:

    1.  Copy the button or field using the Copy command from the Edit menu.

    2.  Create a new pad by selecting New from the File menu

    3.  Paste the button of field into the new pad using the Paste command
    on the Edit menu.

    4.  Exit HyperPAD and run STRIP.EXE with the new pad you just created.

    5.  You now have a copy of the field or button without the text of the
    script which you can copy back to the original pad.


    COMPACT

    The COMPACT utility compacts a pad without having to run HyperPAD.

    compact ad name

    Examples:

    compact home.pad

    compact myphone

    To compact all of the pads in the current directory:

    compact *.pad

    After compacting each pad, the number of bytes that was saved is
    printed.



    ________________________________________________________________________
                                                        Appendixes   352
    ________________________________________________________________________



    ________________________________________________________________________
                                                        Appendixes   353
    ________________________________________________________________________


    APPENDIX 6: RUNNING HYPERPAD ON A NOVELL NETWORK


    INTRODUCTION

    If you have purchased a license to install HyperPAD on a network, you
    can give many users access to a single copy of HyperPAD program located
    on a file server.

    This appendix contains some notes intended for the network adminstrator
    who wants to install HyperPAD on a network. The description is specific
    to Novell networks, but much of the material presented here applies to
    other networks as well.


    INSTALLATION

    Follow these steps to install HyperPAD on a Novell network:

    1.  Create a directory on the file server for HyperPAD's program files.
    The files that must be included here are:

    HPAD.EXE
    HPAD.OVL
    HPAD2.OVL
    HPAD.MSG
    HPAD.PRN
    HPAD.INI (optional)

    The user's rights to this directory should be ROS (read, open, and
    search).

    2.  In order to prevent users from violating the license agreement, the
    HPAD.EXE file should be marked execute-only so that users will be unable
    to copy it. The overlay files (HPAD.OVL and HPAD2.OVL) cannot be marked
    in this manner because of HyperPAD's overlay manager.

    3.  If you have any read-only pads that you want shared by many users,
    they should be copied into this area. For example, you may have a
    HOME.PAD that is loaded by default for each user. Any help files or
    other read-only pads should also be included in this directory.

    Any pads that the users can modify should be copied into the user's
    private directory area. Do not flag pads shareable read-write as this
    will cause problems if many users update the same pad simultaneously
    (which HyperPAD doesn't support).



    ________________________________________________________________________
                                                        Appendixes   354
    ________________________________________________________________________


    4.  Grant the appropriate users access to this directory area. In the
    system login script (or login script of each user), add the statement:

    set HPADNET="."

    This causes HyperPAD to look for pads first in the user's directory
    area. Further, HyperPAD will create the HPAD.INI in this directory.


    SHARING PADS

    If a pad is marked for read-write access, only one HyperPAD user can
    open it at a time. An attempt by a second user on the network to open a
    file already in use will result in an error message to the second user.

    You can allow more than one user to open a single pad if it is marked
    read-only. You can do this within HyperPAD  by setting the Can't modify
    option in the Protect dialog box to on. In this case, HyperPAD opens the
    pad in shared, read-only mode. These pads can still be modified through
    PADtalk (by modifying field contents and object properties), but the
    pages that are modified will never be saved to disk.

    If a pad is currently being used by more than one user on a network, and
    one of these users attempts to make the pad read-only, an error will be
    displayed indicating that the pad is already in use. The pad cannot be
    changed to read-write until there is only one current user.

    The cantModify property can be changed using the PADtalk statement:

    set the cantModify of pad to true;

    set the cantModify of pad to false;

    Notes:

    HyperPAD opens the HPAD.MSG and HPAD.PRN files using a shared, read-only
    mode so that many users can access these files at the same time.

    In order for HyperPAD to share pads, you must be using MS-DOS version
    3.0 or better.



    ________________________________________________________________________
                                                        Appendixes   355
    ________________________________________________________________________


    WHERE HYPERPAD LOOKS FOR FILES

    HyperPAD looks for files in the following order:

    1.  In the current directory

    2.  In the directory specified by the HPADNET environment variable (if
    present)

    3.  In the original directory from which HyperPAD was started

    4.  The directory where HPAD.EXE resides

    5.  Each directory in the DOS path

    6.  On the B: drive (if HyperPAD was started from the A: drive on a low
    density disk)

    As an administrator, you can make HyperPAD search for pads first in the
    HPADNET directory. This is set in the DOS environment using the
    following DOS command:

    set HPADNET=S:\ACCOUNTS\JIM

    To specify the current directory:

    set HPADNET=.

    By setting this variable, you can adjust where HyperPAD looks for pads
    and the configuration file HPAD.INI.

    When you exit HyperPAD, HyperPAD writes the configuration file HPAD.INI
    into the directory specified by HPADNET. If this environment variable
    doesn't exist, HyperPAD will attempt to write the file into the same
    directory as the HyperPAD program files. If the user doesn't have writes
    to this area, the file will not be written.



    ________________________________________________________________________
                                                        Appendixes   356
    ________________________________________________________________________

    This page left blank intentionally.



    ________________________________________________________________________
                                                        Appendixes   357
    ________________________________________________________________________


    APPENDIX 7: EDGE TYPES


    The following illustration shows the available edge types in HyperPAD:

 Ŀ
                                                                        
  **** The Printed Documentation has a picture or screen shot here **** 
                                                                        
 
    



    ________________________________________________________________________
                                                        Appendixes   358
    ________________________________________________________________________

    This page left blank intentionally.



    ________________________________________________________________________
                                                        Appendixes   359
    ________________________________________________________________________


    APPENDIX  8: ASCII TABLE

 Ŀ
                                                                        
  **** The Printed Documentation has a picture or screen shot here **** 
                                                                        
 
    



    ________________________________________________________________________
                                                        Appendixes   360
    ________________________________________________________________________

    This page left blank intentionally.



    ________________________________________________________________________
                                                        Appendixes   361
    ________________________________________________________________________

    APPENDIX 9: WORKING WITH FLOPPY DISKS

    As a pad developer, keep in mind that HyperPAD is a disk-based system,
    and give thought to the issues involved when a user runs the pads you've
    developed on a system with dual floppy drives and no hard disk.

    HyperPAD  can help you ensure that your users don't lose data when
    switching disks. To keep users from losing data, do everything possible
    to  make sure that the current pad has been properly closed before
    another pad is opened.


    USING THE GO STATEMENT FOR CHANGING DISKS

    HyperPAD allows the user to remove disks from the drive after a
    go statement fails to find a specified pad. HyperPAD
    displays a Where Is dialog box for the user to complete after changing
    disks.

    The go statement has an optional parameter that allows you to display
    your own message in place of HyperPAD's Where Is dialog box.

    go to pad "A:SAMPLE.PAD"

       with diskchange "Insert Disk 2";

    This example closes the current pad and displays the message "Insert
    Disk 2" in a dialog box. If the user selects <<Ok>>, then HyperPAD
    attempts to load the pad "A:SAMPLE.PAD". The message will continue to be
    displayed until the disk with the pad has been inserted into the A:
    drive. If the user selects <Cancel>  or presses ESC, then the original
    pad will be loaded. (If the original disk is not in the drive, then the
    user will be instructed to insert the original disk.)

    The user can also remove the disk containing HPAD2.OVL (Program Disk 2).
    When the overlay is requested (when HyperPAD is compiling a script, for
    example), the user will be prompted for the disk containing the overlay
    (using the Where Is dialog box). Once the overlay has been loaded, the
    user  will be prompted to insert the disk containing the pad. Changes to
    the pad will be lost if the user does not reinsert the disk with the
    current pad.

    Note:

    If you run HyperPAD on a low density disk from the A: drive, HyperPAD
    will search for pads on the B: drive (if there is one).
