=========================================================================
                       VDSug.dll (VDS 'U'p'G'rade)
=========================================================================
 Many thanks to Dr. Dread, SnarlingSheep, Moke, and Codescript for their
 help with this project. 

Summary

  A free license* DLL designed for VDS3 and later. Some commands and
  functions may also work with earlier versions of Visual DialogScript
  ("Visual DialogScript" copyright  Commercial Research Ltd).

  free license* - see "*Free License Agreement" below.

  Features include:
  - SMALL DLL size (under 30k).
  - SAVEFILE command for visible lists (NO memory leak!).
  - MOUSEDOWN function that's missing in VDS3 and earlier.
  - GETPIXEL function that returns the RRGGBB hex color value of any
    pixel on your screen.
  - FILE IO commands and functions that use the Windows API to access
    files, pipes, mailslots, communications resources, etc. The file
    read buffer size can be adjusted by the user.
  - USE NON-VDS DLLs, including (but not limited to) Windows system
    DLLs such as kernel32.dll, user32.dll, etc. Non-VDS DLL functions
    can have up to 20 parameters. You may load up to 10 DLLs and have
    a total of up to 100 functions.
  - !CLIPBOARD! option to replace any command/function parameter with
    "!CLIPBOARD!" to work around the 4k data buffer limit (see below).
  - DRAW lines, rectangles, rounded rectangles, ellipses, and pie
    charts. A demo (ug_draw.dsc) is in ug_sample.zip.
  - Create up to 100 menus and submenus.
  - RAWDATA mode to manipulate data "as is" from binary files. Check
    the file IO commands/functions.
  - MENU commands/functions to create, check, uncheck, enable, disable,
    and remove up to 100 menus/items.

  IMPORTANT!
    - Be aware that when you test programs in the VDS IDE (editor), DLLs
      are actually loaded into the IDE memory space - so if an uncompiled
      program crashes, you MUST close and re-open VDS or the DLL may not
      unload properly. This causes errors that would not normally happen.
      It's a good idea to test programs with DLLs AFTER compiling.

    - You must use your window handle in the EXTERNAL command when loading
      VDSug.dll (where registration keys usually are) to use the DRAW and
      MENU features.

        Example:
          %%hwnd = @winexists("Your program window name")
          EXTERNAL VDSug.dll, %%hwnd

    - You can also add "test" (or use "test" alone), and a "DLL  Unloading"
      window will pop up when the DLL exits cleanly.
        Example:
          if using draw features:
            EXTERNAL VDSug.dll, %%hwnd test
          if not using draw features:
            EXTERNAL VDSug.dll, test

    - Due to VDS3 and VDS4 design, the buffer size to send commands and
      functions to an external DLL (such as VDSUG.DLL) must be limited
      to approximately 4k bytes to avoid memory leaks. This limit does
      NOT apply to VDSUG's SAVEFILE command, because it reads directly
      from the VDS list. However, all other commands/functions in VDSUG
      are limited to 4024 TOTAL bytes - including the command/function
      name, variable contents and parameters. Data returned to VDS from
      the DLL does not have this restriction. See the clipboard option
      below.

  CLIPBOARD OPTION - SEND MORE THAN 4K DATA!
    You may replace any command/function parameter with "!CLIPBOARD!"
    and VDSUG will use the clipboard contents as that parameter. Data
    is placed in allocated memory each time to insure it remains
    available to VDSUG until the command/function has completed.
    Use the vds command CLIPBOARD SET just before using "!CLIPBOARD!"
    as a command/function parameter. The "!CLIPBOARD!" parameter is
    not case-sensitive, and the quotes are not necessary. Test your
    program thoroughly when using clipboard contents of more than a
    few megabytes.

      Example:
        CLIPBOARD SET, %%data
        UG FILEWRITE, 1, TEXT, !CLIPBOARD!

  BUFFER OPTION FOR FILEWRITE COMMAND:
    There is now a !BUFFER! option to use with the FILEWRITE command.
    With this you can write raw data directly from the internal buffer
    if you wish to cut/slice/splice files.

  YOU CAN ALSO READ FILES WITHOUT RETURNING DATA TO VDS:
    There is now a FILEREAD command (not to be confused with the FILEREAD
    function) that ONLY reads to the internal buffer for faster reading
    and writing (that does not require data to be manipulated in VDS).

=========================================================================
*Free License Agreement
=========================================================================

  "The software" in the context of this agreement shall refer to "free
  license" DLLs, "free license" executables, or other "free license"
  software from McLain Software.

  You are hereby granted a free limited license to use and/or distribute
  the software, subject to the terms and conditions stated below. This
  is a legal agreement between you and McLain Software.

  While the limited license is free, the software is not "free software".
  The software is the copyright of McLain Software and is protected under
  international law. Any reverse engineering, decompiling, or use of the
  software to create competitive products is expressly forbidden.

  You may not sell, rent or lease the software. The software may be freely
  distributed with your software products, but shall not be valued as any
  part of the purchase price of your software products.

  The software is provided "as is" and all responsibility for determining
  fitness of purpose rests solely with you. You agree not to hold McLain
  Software or its agents liable for any loss, damage, or consequential
  loss or damage, arising directly or indirectly from use of the software
  or for any other reason. You accept sole responsibility for taking all
  necessary precautions to safeguard against any such loss, damage, or
  consequential loss or damage, howsoever it may be caused.

  The software is copyright  McLain Software. All rights are reserved. 

=========================================================================
Using the DLL in your program 
=========================================================================

  You must use the VDS EXTERNAL command somewhere near the beginning
  of your code so the functions and commands are accessible to your
  program. You should use the full path to the DLL.

  NOTE: for using the DRAW and CREATEMENU commands, you should load
  the DLL after the program window is created, and use the window
  handle as a parameter to the EXTERNAL command.

   1. Create a program with a window.

   2. Get the program's window handle using @winexists():
      Example:  %%hwnd = @winexists("Your program window name")

   3. Load the dll using your window handle (specifiy the correct
      path to VDSug.dll):

      Example:  EXTERNAL VDSug.dll, %%hwnd

  If you are not using these commands, you can load the DLL before
  window creation:
  
  Syntax: EXTERNAL [path]VDSUG.DLL (no key is required) 

  Example (checks local, windows\system, and windows\system32 dirs):
    if @file(@path(%0)VDSUG.DLL)
       EXTERNAL @path(%0)VDSUG.DLL
    else
       if @file(@windir()\system\VDSUG.DLL)
          EXTERNAL @windir()\system\VDSUG.DLL
       else
          if @file(@windir()\system32\VDSUG.DLL)
             EXTERNAL @windir()\system32\VDSUG.DLL
          else
             TITLE PROGRAM ERROR
             WARN Cannot find a necessary file:@tab()@cr()@cr()VDSUG.DLL
             EXIT
          end
       end
    end

  Tip: Note that @path() (VDS4 and earlier) includes a backslash, but
       @windir() does not. 

=========================================================================
Commands 
=========================================================================

  - Commands must be preceeded by "UG" (case-insensitive) and a space,
    NOT enclosed in parenthesis, and separated by commas. Command names
    are NOT case sensitive.
  - VDS vars may be used as actual command names and/or parameters.
  - Strings with leading/trailing spaces should be enclosed in quotes
    or in a var. 

-------------------------------------------------------------------------
Command (Listbox) - SAVEFILE 

  This command was designed to avoid the memory leak in the VDS
  "LIST SAVEFILE" commands as needed. It is NOT related to FILE IO
  commands/functions in VDSUG.DLL.

  NOTE: SAVEFILE works ONLY with standard Windows list boxes. It does
        NOT work with VDS "created" lists (LIST CREATE) because it
        requires a list "handle" - the identifier for controls that is
        obtained with @winexists().

  Syntax: UG SAVEFILE, [list handle], [filename]

  Example: UG SAVEFILE, @winexists(~List1), %%filename 

  OK: Set to FALSE if SAVEFILE fails.

  Tip: You can hide a standard list box with DIALOG HIDE if you wish to
       use UG SAVEFILE and require a non - visible list. 

-------------------------------------------------------------------------
Command (File IO) - FILECLOSE 

  Closes a file/device/etc. that has been opened with FILEOPEN.

  Syntax: UG FILECLOSE, [1-10]

  Example: UG FILECLOSE, 1

  OK: Set to FALSE if the file/device/etc. cannot be closed. 

-------------------------------------------------------------------------
Command (File IO) - FILEOPEN 

  Uses the Windows API function "CreateFile" to open files, pipes,
  mailslots, communications resources, disk devices (Windows NT only),
  consoles, and directories (open only).

  NOTE: You must use FILEOPEN before using other FILE IO commands or
        functions.

  Syntax (query, read, write, read|write):
    UG FILEOPEN, [1-10], [file/device/etc. name], QUERY
    UG FILEOPEN, [1-10], [file/device/etc. name], READ
    UG FILEOPEN, [1-10], [file/device/etc. name], WRITE
    UG FILEOPEN, [1-10], [file/device/etc. name], READ|WRITE

  Example:UG FILEOPEN, 1, c:\myfile.txt, READ|WRITE

  OK: Set to FALSE if the file/device/etc. cannot be opened.

  More Info:
    - Up to 10 files/devices/etc. may be opened at once (numbered 1
      thru 10). 

-------------------------------------------------------------------------
Command (File IO) - FILEREAD 

  A COMMAND to read user-defined number of bytes from a file to the
  internal buffer only (it does NOT return the data to VDS!). You
  can then write from the internal buffer using FILEWRITE with the
  "!BUFFER!" parameter when copying all or portions of a file.

  Do not confuse this fileread COMMAND with the fileread FUNCTION
  that returns data to your VDS program.

  NOTE: Read size is limited by size of internal file "read" buffer
        which is set by the FILEREADBUFSIZE function (4024 bytes is
        the default size).

  Syntax (RAWDATA MODE ONLY): 
    UG FILEREAD, [1-10], RAWDATA, [bytes to read]

  Example (RAWDATA MODE ONLY):
    UG FILEREAD, 1, RAWDATA, 1024

  OK: Set to FALSE if FILEREAD fails.

-------------------------------------------------------------------------
Command (File IO) - FILEWRITE 

  Write to a file/device/etc. that has been opened with the FILEOPEN
  command using the WRITE or READ|WRITE parameter.

  Syntax (TEXT, HEX, RAWDATA):
    UG FILEWRITE, [1-10], TEXT, [string to write, !CLIPBOARD! or !BUFFER!]
    UG FILEWRITE, [1-10], HEX, [string to write, or !CLIPBOARD!]
    UG FILEWRITE, [1-10], RAWDATA, [string to write, !CLIPBOARD! or
                  !BUFFER!], [null replace char so we can put nulls back]
  Examples:
    UG FILEWRITE, 1, TEXT, "this is a test"
    UG FILEWRITE, 1, TEXT, !CLIPBOARD!
    UG FILEWRITE, 1, TEXT, !BUFFER!

    UG FILEWRITE, 1, HEX, "4D 61 63"
    UG FILEWRITE, 1, HEX, !CLIPBOARD!

    UG FILEWRITE, 1, RAWDATA, "this is a test", @chr(20)
    UG FILEWRITE, 1, RAWDATA, !CLIPBOARD!
    UG FILEWRITE, 1, RAWDATA, !BUFFER!

  OK: Set to FALSE if FILEWRITE fails.

  Tip:Since FILEWRITE does NOT move the pointer ahead, you must increment
      the file position.
      On new (empty) files you can use FILESETPOS with FILEGETSIZE:
        %%setpos = @ug(FILESETPOS,1, @ug(FILEGETSIZE, 1))
      On existing files, you can increment the pointer by the length of
      the string written:
        %%pos = @ug(FILEGETPOS, 1)
        UG FILEWRITE, 1, TEXT, %%string
        %%pos = @ug(FILESETPOS,1, @fadd(%%pos, @len(%%string)))

  More Info:
    - Up to 4024 bytes (chars) of TEXT data may be sent from VDS at
      once, or approx 1.3k of HEX data (HEX requires two hex digits
      and a space per char). You can also send clipboard contents
      with "!CLIPBOARD!" as a parameter. You can write directly from
      the internal read buffer with the "!BUFFER!" parameter in TEXT
      and RAWDATA modes only.
    - TEXT is standard ASCII strings. TEXT chars are case sensitive.
    - HEX data is standard 2 digit hex chars separated by spaces
      ("4D 61 63" or "4d 61 63" etc.). HEX char digits are not case
      sensitive.
    - HEX mode is extremely slow, and for this reason HEX data is
      limited to 32k bytes read/write to/from the file - that's 96k
      of text in hex format "4D 61 63", etc.
    - The file pointer is NOT automatically moved ahead, so to write in
      a loop you must reset the file position after each FILEWRITE.
    - FILEWRITE does NOT stop at EOF (end of file) so you can extend or
      append a file if desired. Functions FILEGETSIZE and FILEGETPOS may
      be used if needed to determine max chars (bytes) to write from
      current position (filesize minus currentpos). 

-------------------------------------------------------------------------
Command (GUI) - MENU

  Create up to 100 total menus/submenus and items. Menu ITEM clicks
  generate "item nameMENU" events ("MENU" is added to event). Has
  parameters to CREATE, CHECK, UNCHECK, ENABLE, DISABLE and REMOVE.

  You cannot insert menus or items, but you can remove all items
  and recreate the menu with different items - and re-use the same
  menu/item ID numbers. Top level menus (always visible - usually
  "File", "Edit", etc.) cannot be checked, disabled, or removed.

  Use the function @ug(MENU, GETSTATE, parent number, item number) to
  retrieve the current state of a menu item.

  Initial steps for using MENU commands:

    1. Create a program with a window.

    2. Get the program's window handle using @winexists():
       Example:  %%hwnd = @winexists("Your program window name")

    3. Load the dll using your window handle (specifiy the correct
       path to VDSug.dll):

       Example:  EXTERNAL VDSug.dll, %%hwnd


  CREATE parameter - creates a MENU or menu ITEM.

    Syntax:
      UG MENU, CREATE, control number (1-100), control type (menu,item,bar),
                       menu name (returns this as event on submenus),
                       parent menu number (0-100)

      Note: The "BAR" parameter ignores parameters other than the parent
            menu number (parent is the menu number it's added to).
            Menu bars are NOT included in the 100 menus/submenus limit,
            but MUST be counted when using the zero based item position.

    Example (File -> Open menu, 2 submenus on Open with a bar between):
      UG MENU, CREATE, 1, MENU, &File, 0
      UG MENU, CREATE, 2, MENU, &Open, 1
      UG MENU, CREATE, 3, ITEM, &MyFile, 2
      UG MENU, CREATE, NULL, BAR, NULL, 2
      UG MENU, CREATE, 4, ITEM, &YourFile, 2

  NOTE: You must count menu bars (separators) when determining the
        zero based menu item number for the following parameters.

  CHECK parameter - puts a checkmark by a menu ITEM.

      Syntax:
        UG MENU, CHECK, parent ID number, zero based menu item number

      Example - check first menu item (0) of parent menu (1):
        UG MENU, CHECK, 1, 0

  UNCHECK parameter - removes a checkmark by a menu ITEM.

      Syntax:
        UG MENU, UNCHECK, parent ID number, zero based menu item number

      Example - check first menu item (0) of parent menu (1):
        UG MENU, UNCHECK, 1, 0


  ENABLE parameter - enables a child MENU (and items) or a menu ITEM.

      Syntax:
        UG MENU, ENABLE, parent ID number, zero based menu item number

      Example - enable first menu item (0) of parent menu (1):
        UG MENU, ENABLE, 1, 0

  DISABLE parameter - disables a child MENU (and items) or a menu ITEM.

      Syntax:
        UG MENU, DISABLE, parent ID number, zero based menu item number

      Example - disable first menu item (0) of parent menu (1):
        UG MENU, DISABLE, 1, 0

  REMOVE parameter - removes a child MENU (and items) or a menu ITEM.

      Syntax:
        UG MENU, REMOVE, parent ID number, zero based menu item number

      Example - disable first menu item (0) of parent menu (1):
        UG MENU, REMOVE, 1, 0

      NOTE: When a MENU or ITEM is removed, items below are moved up
            in the zero-based position count (WYSIWYG). You can also
            re-use ID numbers of removed items.

  IMPORTANT:
    - All MENU commands/functions work ONLY on menus created with
      VDSug.dll commands.
    - Menu names can now be up to 58 characters in length.
    - Menu items created with the same name generate the same event.
    - You MUST count menu bars (separators) when determining the
      zero based menu item number. However, they are NOT included in
      the 100 menu/item limit.
    - You may use ampersands (&) in menu/item names, but they are
      removed from the returned VDS event. When making labels for
      item events, you must use the name WITHOUT the "&" chars.
    - The base parent number is zero - only use this as a parent number
      when creating top level menus such as "File", "Edit", etc. All
      other parent numbers (1-100) are the previous menus you created.
      Top level menus cannot be removed, checked, or disabled.
    - Internal control ID numbers start at 10001 (default) when you use
      the element number 1 (you must use 1-100). If there is a conflict
      with VDS or other DLL control ID numbers, you can change the
      default with "UG SETIDFACTOR, number" - where number is 64500 or
      less (and preferably above 1000 to avoid system ID numbers).
      This allows a different range of internal ID numbers without
      changing your VDS code.

=========================================================================
Functions 
=========================================================================

  - Functions must be preceeded by "@UG" (case-insensitive), enclosed in
    parenthesis, and separated by commas. Function names are NOT case
    sensitive.
  - VDS vars may be used as actual function names and/or parameters.
  - Strings with leading/trailing spaces should be enclosed in quotes or
    in a var. 

-------------------------------------------------------------------------
Function (GIU) - MENU

  All MENU commands/functions work ONLY on menus created with
  VDSug.dll commands.

  GETSTATE parameter - retrieve the current state of a menu item.

    Returns check/disabled state of menu item in a "x.x" format:
      "1.0" if checked only.
      "0.1" if disabled only.
      "1.1" if both.
      "0.0" if neither.

    Syntax:
      @ug(MENU, GETSTATE, parent ID number, zero based menu item number)
      Note: You must count menu bars (separators) when determining
            menu item number.

    Example - get state of first menu item (0) of parent menu (1):
      %%menustate = @ug(MENU, GETSTATE, 1, 0)

-------------------------------------------------------------------------
Function (Mouse) - MOUSEDOWN 

  Gets current status of left, middle, or right mouse buttons.

  NOTE: MOUSEDOWN has been updated to work only in the client area
        of the parent and child windows in Win9x and later. It is
        no longer global in Windows XP.

  Syntax:@ug(MOUSEDOWN, any combination of LMR)
    Note: Buttons must be LMR order (LMR, LM, LR, L, MR, M, or R).
          Defaults to L if no button parameter is used.

  Example:
    OPTION DECIMALSEP, "."
    REPEAT
       PARSE "%l;%m;%r", @ug(MOUSEDOWN, LMR)
       DIALOG SET, Status, Left= %l Middle= %m Right= %r
       WAIT ".01"
    UNTIL @event()

  Returns: 1 if chosen mouse button is down, NULL (nothing) if not.

  Tip: Use a WAIT in VDS loops whenever practical, otherwise CPU usage
       may reach 100% (a behavioral condition of VDS). 

-------------------------------------------------------------------------
Function (Graphics) - GETPIXEL 

  This function returns the RRGGBB hex color value of any pixel on your
  screen.

  Syntax: @ug(GETPIXEL, [window handle], [pixel X], [pixel Y])

  Example (captures pixel at mousepos) vars are used for clarity, VDS
  functions may be used directly in GETPIXEL:
    %%hwnd = @winatpoint(@mousepos(X),@mousepos(Y))
    %x = @mousepos(X)
    %y = @mousepos(Y)
    %%pixel = @ug(GETPIXEL, %%hwnd, %x, %y)

  Returns: RRGGBB (6 digit hex) color.

  Tip: VDS uses RGB (red green blue) colors in reverse order, so reverse
       the values to BBGGRR (blue green red) and prefix a "$" for VDS
       ($0000FF = VDS red). HTML uses the normal RRGGBB format prefixed
       with a "#" (#FF0000 = HTML red). 

-------------------------------------------------------------------------
Function (System) - GETLASTERROR 

  This function returns the Windows last-error code. Especially useful
  to find the cause of FILE IO errors.

  Syntax: @ug(GETLASTERROR)

  Example: %%errmsg = @ug(GETLASTERROR)

  Returns: Windows last-error code message as text.

  Tip: You should use GETLASTERROR immediately after a failure, because
       some functions clear previous error codes.

  More Info:
    - The last-error is maintained on a per-thread basis. Multiple
      threads do not overwrite each other's last-error codes. 

-------------------------------------------------------------------------
Function (File IO) - FILEGETSIZE

  Gets size of selected file.

  Syntax: @ug(FILEGETSIZE, [1-10])

  Example: %%size = @ug(FILEGETSIZE, 1)

  Returns: Size of selected file in decimal bytes.

-------------------------------------------------------------------------
Function (File IO) - FILEGETPOS 

  Gets position of the current file pointer.

  Syntax: @ug(FILEGETPOS, [1-10])

  Example: %%pos = @ug(FILEGETPOS, 1)

  Returns: Decimal byte position of the current file pointer. 

-------------------------------------------------------------------------
Function (File IO) - FILESETPOS 

  Sets position of the current file pointer.

  Syntax: @ug(FILESETPOS, [1-10], [file position number])

  Example: %%newpos = @ug(FILESETPOS, 1, 25)

  Returns: New decimal position of the current file pointer. 

-------------------------------------------------------------------------
Function (File IO) - FILEREAD

  Reads user-defined number of bytes from a file into a var.

  NOTE: Read size is limited by size of internal file "read" buffer
        which is set by the FILEREADBUFSIZE function (4024 bytes is
        the default size).

  Syntax (TEXT, HEX, RAWDATA):
    %%data = @ug(FILEREAD, [1-10], TEXT, [bytes to read])
    %%data = @ug(FILEREAD, [1-10], HEX, [bytes to read])
    %%data = @ug(FILEREAD, [1-10], RAWDATA, [bytes to read],
                                            [null replacement char])

    Note: For null replacement to work properly, you must choose a char
          that is NOT in the file. Otherwise, all instances of the char
          will be replaced with nulls when you specify the replacement
          char in the FILEWRITE command.

  Example (TEXT, HEX, RAWDATA):
     %%data = @ug(FILEREAD, 1, TEXT, 4096)
     %%data = @ug(FILEREAD, 1, HEX, 1024)
     %%data = @ug(FILEREAD, 1, RAWDATA, 1024, @chr(255))

  Returns: Data read from the file if successful, NULL (nothing) if not.

  More Info:
    - RAWDATA is data exactly as read from a file. Null chararacters
      designate the end of a string, so you can add an optional null
      replacement character in order to return all the data to VDS.
    - HEX data is returned as two digit hex numbers separated by a
      space, TEXT is returned as normal text. When EOF is reached,
      pointer resets to zero, so you can read in a loop until:

        @equal(@ug(FILEGETPOS, [1-10]), "0")

    - HEX mode is extremely slow, and for this reason HEX data is
      limited to 32k bytes read/write to/from the file - that's 96k
      chars in text format "4D 61 63".
    - HEX mode requires the fileread buffer to be 3 times the actual
      size of bytes read from the file - it must have room for the
      bytes to be converted to hex chars (2 digits and a space). To
      read 8k bytes in hex requires a 24k fileread buffer.
    - To read the whole file (up to file "read" buffer size, which is
      set with the FILEREADBUFSIZE function) use "0" (a zero) for the
      [bytes to read] parameter.
    - File pointer is re-set to zero (start of file) when end of file
      is reached.

-------------------------------------------------------------------------
Function (File IO) - FILESEARCHTEXT, FILESEARCHHEX

  Searches for a string (case sensitive or not) in a file. Default
  search is NOT case sensitive, use "EXACT" parameter for case
  sensitive search.

  Syntax (text and hex) 
    Case insensitive:
      @ug(FILESEARCHTEXT, [1 - 10], [search string])
      @ug(FILESEARCHHEX, [1 - 10], [search string])
    Case sensitive:
      @ug(FILESEARCHTEXT, [1 - 10], [search string], EXACT)
      @ug(FILESEARCHHEX, [1 - 10], [search string], EXACT)

  Example (text and hex) - vars may be used
    Case insensitive:
      %%foundpos = @ug(FILESEARCHTEXT, 1, "Fred the customer")
      %%foundpos = @ug(FILESEARCHHEX, 1, "4D 61 63")
    Case sensitive:
      %%foundpos = @ug(FILESEARCHTEXT, 1, "Fred the customer", EXACT)
      %%foundpos = @ug(FILESEARCHHEX, 1, "4D 61 63", EXACT)

  Returns: File position if string found, NULL (nothing) if not found,
           and "ERROR" if there was a failure.

  More Info:
    - Search string is limited to 4024 bytes (chars).
    - File pointer is re-set to zero (start of file) if search string
      was not found.

-------------------------------------------------------------------------
Function (File IO) - FILEREADBUFSIZE

  Check size, or set size of internal DLL buffer that file is read into.

  Syntax (check size and set size): 
    @ug(FILEREADBUFSIZE)
    @ug(FILEREADBUFSIZE, [new size of buffer])

  Example (check size and set size): 
    %%bufsize = @ug(FILEREADBUFSIZE)
    %%bufsize = @ug(FILEREADBUFSIZE, 1024000)

  Returns: Current buffer size, whether a change was successful or not.

  Tip: You can use the return value to check if the function was
       successful.
       Example:
         %%bufsize = @ug(FILEREADBUFSIZE, 20480000)
         if @not(@equal(%%bufsize, 20480000))
            INFO ERROR - buffer size is still %%bufsize
         end

  More Info:
    - Limited to maximum available free RAM, or 2 gigabytes (whichever
      comes first).
    - Probably not a good idea to max out available RAM with this.

=========================================================================
USING NON-VDS DLLs (DLL functions accept up to 20 parameters)
=========================================================================

  You may use non-VDS DLL functions with VDSUG. However, these steps
  MUST be taken (a complete simple program is shown below):

  1. You MUST catch VDS error trapping for each non-VDS DLL function
     call. Calling a non-VDS DLL function generates a false "error 27"
     from VDSUG - the VDS status procedure (StatProc) function for DLLs
     does not work when calling another DLL from VDSUG. Catching the
     false error is simple, just use OPTION ERRORTRAP:

     OPTION ERRORTRAP, trap1

     And then add a label named ":trap1" below your @ug(DLLFUNC) call
     (more on this in the "NON-VDS DLL NOTES" section below). You must
     add one for each function call (trap1, trap2, etc.), and turn it
     back off afterwards.

  2. Load a DLL. You can load up to 10 DLLs, numbered 1-10. When you
     unload a DLL, that number is free to use again. NOTE: System DLLs
     already in memory will remain accessible even after unloading, but
     their number can still be reassigned if needed.

       Syntax (path is not necessary with system DLLs): 
         UG DLLLOAD, DLL number, DLL path\name

       Example (as the first DLL to load):
         UG DLLLOAD, 1, kernel32.dll

  3. Initialize a DLL function (up to 100 functions, numbered 1-100).
     Function numbers are NOT related to DLL numbers. If you have 3
     DLLs loaded and use 2 functions from each, the DLLs will number
     1-3, and the functions will number 1-6. A function only has to
     be initialized once, then you can call it anytime after that.

       Syntax:
         UG DLLINITFUNC, DLL number, function number, function name

       Example:
         UG DLLINITFUNC, 1, 1, GetComputerNameA

  4. Call the DLL function with up to 20 function parameters (the label
     ":trap1" is added here to catch false errors).

       Syntax:
         @ug(DLLFUNC, function name, return type, params, params, etc.)

       Example:
         OPTION ERRORTRAP, trap1
         %%result = @ug(DLLFUNC, GetComputerNameA, int, strbuf:, bufsize:)
         :trap1
         PARSE "%%return; %%buffer", %%result
         INFO Return value: %%return@cr()@cr()Buffer value: %%buffer

  5. Unloading a DLL. DLLs are automatically released when your program
     exits, but you can unload a DLL when you no longer need it with the
     "UG DLLUNLOAD: command:

       Syntax:
         UG DLLUNLOAD, DLL number

       Example:
         UG DLLUNLOAD, 1

-------------------------------------------------------------------------
  NON-VDS DLL NOTES:

    - Return types are INT and STR only, although internal struct and
      buffer values may also be set and retrieved (see "DLL Commands,
      Functions, and Structures" section).

    - If you are unsure of a return value type, try INT. This is
      the most common return type.

    - Function return and string buffer values are returned as a single
      field separated string, separated by pipes "|". The return value
      is always first.

    - Handle, integer, and string params must be qualified. Do not
      leave blanks after the colon unless you intend to use them.
        Example: INT:234 or STR:This is a string test!

    - Parameter qualifiers - must include a colon, leave no unwanted
      spaces between the colon and the value.

        HANDLE:   Window handles may be obtained with @winexists().
                  Leading percent char "%" will be ignored.
                  Example:
                    handle:@winexists(myVDSprogram)

        INT:      Number range from -2,147,483,648 to 2,147,483,647
                  (no decimal numbers). Most handles (WindowDC, etc.)
                  can be retrieved and used as INT.
                  Example:
                    int:1024

        STR:      String or single character values.
                  Example:
                    str:This is a test.

        STRBUF    For functions that require an input or return string
                  buffer.  Takes no other values.  See the "DLL Commands,
                  Functions, and Structures" section below.
                  Example:
                    strbuf

        STRADDR   Address of STRBUF. Takes no other values.
                  Example:
                    straddr

        STRSIZE   Pointer to size of STRBUF. Takes no other values.
                  Example:
                    strsize

        INTBUF    For functions that require an input or return number
                  buffer. Takes no other values.  See the "DLL Commands,
                  Functions, and Structures" section below.
                  Example:
                    intbuf

        INTADDR   Address of INTBUF. Takes no other values.
                  Example:
                    intaddr

        Structure parameters - There are a limited number of structures
        in the VDSug.dll. See "DLL Commands, Functions, and Structures"
        section below. Use @ug(STRUCTLIST) to return available structs.

    - The "STRBUF" and "STRSIZE" params take no other values. The
      current STRBUF size is 4024 bytes. This may be increased later
      since there is no problem returning large strings from the DLL.

    - Window handles may be obtained with @winexists(). If there is
      a leading percent char (%), it will be ignored.

    - Non-VDS DLL functions names ARE case sensitive.

    - Qualifiers and return types (HANDLE:, INT:, STR:, etc.) are
      NOT case sensitive.

    - ERROR TRAPPING: If you wish to use a your own errortrapping
      procedure, use "OPTION ERRORTRAP, trap1" (etc.) just above
      the @ug(DLLFUNC) function, then below the ":trap1" (etc.)
      label, you can reset your previous error trapping routine or
      turn it back off. Do NOT leave errortrapping set to "trap1"
      (etc.), or any other error will cause your program to go to
      that label.

    - Many system DLL functions have an "A" added to the end of the
      function name. For example, the API "MessageBox" function is
      named "MessageBoxA" when called straight from user32.dll.

    - You can use MS QuickView to read the exported function names
      in a DLL, however you must obtain the correct parameters. The
      Windows system DLL parameters can be found in the MS SDK help
      files. Other DLL parameters should be obtained from the DLL's
      author.

=========================================================================
DLL Commands, Functions, and Structures
=========================================================================
  IMPORTANT - Set the number that corresponds to which parameter you'll
  use these in. Parameters are numbered 0-19 and start AFTER the external
  DLL return type. For example - if you use STRBUF, STRADDR, STRSIZE,
  INTBUF or INTADDR as the first parameter after the return type, set
  that value using number zero.

  There are two generic structs now: INTSTRUCT and STRSTRUCT. INTSTRUCT
  can be used when the struct must be all numbers (such as RECT and POINT)
  and have up to 16 elements. STRSTRUCT can be used when the elements are
  all strings, and have up to 4 elements.

  Command - SETSTR
    Sets one of the 20 internal DLL string buffers (numbered 0-19).

    Syntax:
      UG SETSTR, number (0-19), "string"

    Example:
      UG SETSTR, 1, "string"

  Command - SETINT
    Sets one of the 20 internal DLL non-float number buffers (numbered
    0-19). Acceptable values are from -2,147,483,648 to 2,147,483,647.

    Syntax:
      UG SETINT, number (0-19), number

    Example:
      UG SETINT, 1, 654321

  Command - SETSTRUCT
    Sets data in one of the 20 internal DLL structures (numbered 0-19)
    of the named struct, one value per parameter.

    Syntax:
      UG SETSTRUCT, struct number (0-19), structure name, element1,
         element2, element3, etc. //

    Example:
      UG SETSTRUCT, 1, INTSTRUCT, 100, 200, 300, 400
      UG SETSTRUCT, 1, STRSTRUCT, Test1, Test2, Test3

    Note: Using SETSTRUCT without values clears the struct elements.
          Number structs are all set to zero, string structs are all
          set to null.


  Function - GETSTRATADDR
    Returns a string from the specified int address. Use this to
    retrieve data from external DLL functions that only return a
    pointer to the data you need.

    Syntax:
      @ug(GETSTRATADDR, [address])

    Example (for a function that returned an address (pointer) as
    param 3, and you used INTBUF or INTADDR as param 3):
      %%pointer = @ug(GetInt, 3)
      %%result = @ug(GetStrAtAddr, %%pointer)

  Function - GETSTR
    Returns data from one of the 20 internal DLL string buffers (numbered
    0-19).

    Syntax:
      @ug(GETSTR, number (0-19))

    Example:
      %%result = @ug(GETSTR, 1)

  Function - GETINT
    Returns data from one of the 20 internal DLL number buffers (numbered
    0-19).

    Syntax:
      @ug(GETINT, number (0-19))

    Example:
      %%result = @ug(GETINT, 1)

  Function - GETSTRUCT
    Returns data from one of the 20 internal DLL structures (numbered
    0-19) of the named struct. Each element of the structure is field
    separated by "|" in the return value.

    Syntax:
      @ug(GETSTRUCT, struct number (0-19), struct name)

    Example:
      %%result = @ug(GETSTRUCT, 1, INTSTRUCT)


  Function - STRUCTLIST
    Returns available internal structs, field separated by "|" in the
    return value.

    Syntax:
      @ug(STRUCTLIST)

    Example:
      %%result = @ug(STRUCTLIST)

-------------------------------------------------------------------------
rem -- Sample program with functions from user32.dll.
rem -- Change the EXTERNAL command path to VDSUG.DLL as necessary.
rem -- This isn't a practical example, but it's interesting.

EXTERNAL @path(%0)vdsug.dll
UG DLLLOAD, 1, user32.dll
UG DLLINITFUNC, 1, 1, GetWindowDC
UG DLLINITFUNC, 1, 2, PaintDesktop
UG DLLINITFUNC, 1, 3, ReleaseDC

OPTION SCALE, 96
OPTION DECIMALSEP, "."
TITLE By SnarlingSheep
DIALOG CREATE,"Test Program",-1,0,343,193
  %%hwnd = @winexists("Test Program")
  DIALOG ADD,BUTTON,Test,5,5,60,22
  DIALOG ADD,BUTTON,Clear,5,70,60,22
DIALOG SHOW

:EVLOOP
  OPTION ERRORTRAP
  WAIT EVENT
  goto @event()

:TestBUTTON
  OPTION ERRORTRAP,trap1
  %%winDC = @ug(DLLFUNC, GetWindowDC, int, handle:%%hwnd)
  :trap1

  OPTION ERRORTRAP,trap2
  %%result = @ug(DLLFUNC, PaintDesktop, int, int:%%winDC)
  :trap2

  DIALOG FOCUS, Clear
  INFO Function return: %%result

  OPTION ERRORTRAP,trap3
  %%result = @ug(DLLFUNC, ReleaseDC, int, handle:%%hwnd, int:%%winDC)
  :trap3
  goto EVLOOP

:ClearBUTTON
  DIALOG HIDE
  DIALOG SHOW
  goto EVLOOP

:CLOSE
  exit

=========================================================================
USING THE DRAW COMMANDS  (syntax is different from draw3.dll)
=========================================================================

 Initial steps for using the draw features of VDSug.dll:

 1. Create a program with a window, using the PAINT style.

 2. Get the program's window handle using @winexists():
    Example:  %%hwnd = @winexists("Your program window name")

 3. Load the dll using your window handle (specifiy the correct
    path to VDSug.dll):

    Example:  EXTERNAL VDSug.dll, %%hwnd

  *******************************************************************
  DRAW COMMANDS: (most require additional parameters, vars may be used)

    PEN        Sets pen color, style, width if desired.
               Style: SOLID DASH DOT DASHDOT DASHDOTDOT
               Colors: VDS3 color names (no BACKGRND,FOREGRND),
                       or Hex format 0x00FFFFFF (any color).
               Width starts at 1 (SOLID is only style above 1).
               Retains settings unless changed.
               Example: UG DRAW,PEN,RED,SOLID,2

    FILL       Sets fill (brush) color to fill ellipses, etc.
               Colors: VDS3 color names (no BACKGRND,FOREGRND),
                       or Hex format 0x00FFFFFF (any color).
               Retains settings unless changed.
               Example: UG DRAW,FILL,YELLOW

    FONT       Sets font color, style, size, font type (background
               is always transparent).
               Colors: VDS3 color names (no BACKGRND,FOREGRND),
                       or Hex format 0x00FFFFFF (any color).
               Styles: N = normal, B = bold,
                       NI = normal italics, BI = bold italics. 
               Size: Desired size of font.
               Retains settings unless changed.
               Either use color only, or include ALL parameters.
               Example1: UG DRAW,FONT,RED
               Example2: UG DRAW,FONT,RED,N,24,"Times New Roman"

    TEXT       Draws text (240 chars max) in current font at x1 y1.
               Parenthesis, commas, etc. must be enclosed in quotes.
               Example: UG DRAW,TEXT,10,40,"This is, (a test!)"

    FLOOD      Floods the current area starting at x1,y1 with the
               current FILL (brush) color. You may optionally name
               the color that is being replaced, otherwise the
               pixel color at x1, y1 determines replacement. The
               area is flooded in all directions until a different
               colored boundary (line, etc.) is reached.
                 Replace pixel color at x1, y1:
                   Example: UG DRAW,FLOOD,10,30
                 Name white pixels as ones to be replaced:
                   Example: UG DRAW,FLOOD,10,30,WHITE

    LINE       Draws line from x1 y1 to x2 y2.
               Example: UG DRAW,LINE,10,30,280,180

    ARC        Draws Arc within rectangle upper left x1 y1
               lower right x2 y2, with first radial endpoint xy
               at r1,r2 and second radial endpoint xy at r3,r4.
               Sum of coordinates should not exceed 32,767.
               Example:
                    UG DRAW,ARC,120,120,200,200,120,120,200,200
               Tip: To see how ARC works, also draw a rectangle
                    using the first 4 parameters of your arc.

    PIE        Draws Pie within rectangle upper left x1 y1
               lower right x2 y2, with first radial endpoint xy
               at r1,r2 and second radial endpoint xy at r3,r4.
               Sum of coordinates should not exceed 32,767.
               Example:
                    UG DRAW,PIE,120,120,200,200,120,120,200,200
               Tip: To see how PIE works, also draw a rectangle
                    using the first 4 parameters of your pie.

    RECTANGLE  Draws rectangle from x1 y1 upper left
               to x2 y2 lower right.
               Example: UG DRAW,RECTANGLE,10,30,280,180

    ROUNDRECT  Draws rounded rectangle from x1 y1 upper left to
               x2 y2 lower right. Corner ellipse width and height
               are optional (if using height, width is required),
               defaults are 30.
                 Example1: UG DRAW,ROUNDRECT,10,30,280,180
               Set corner ellipse width only:
                 Example2: UG DRAW,ROUNDRECT,10,30,280,180,30
               Set corner ellipse width and height:
                 Example3: UG DRAW,ROUNDRECT,10,30,280,180,30,10

    ELLIPSE    Draws ellipse from x1 y1 upper left to to x2 y2
               lower right. If x1 y1 x2 y2 is square, draws a
               circle, otherwise draws an ellipse.
               Example: UG DRAW,ELLIPSE,60,80,280,185

    OFFSCREEN  For fast flicker free erase/redraw animations.
               Allows drawings to be done offscreen before showing
               them. You must then call ONSCREEN to show the
               accumulated drawings (a PAINT event will also
               show all accumulated drawings).
               Example: UG DRAW,OFFSCREEN

    ONSCREEN   Deactivates the OFFSCREEN command and shows all
               drawings created during OFFSCREEN.
               Example: UG DRAW,ONSCREEN

    SAVESCREEN updates the copy of your screen in memory. Use
               this after normal VDS routines that change text,
               images, etc. Otherwise the REFRESH command can
               not perform a true update of your program window.

    REFRESH    Refreshes (updates) your drawings automatically
               when the window is moved or minimized (use under
               the ":PAINT" label). Eliminates the need to have
               draw routines under the paint label.
               Example: UG DRAW,REFRESH

  ******************************************************************
  !!! IMPORTANT NOTES !!!
  - Be aware that when you run programs in the VDS IDE (editor),
    DLLs are actually loaded into the IDE memory space - so if an
    uncompiled program crashes, you MUST close and re-open VDS
    or the DLL may not unload properly, and this may cause errors.
    SOLUTION: Test programs with DLLs AFTER compiling.
  - If you show a continued memory loss (or your program is slow)
    when testing, close and re-open the VDS IDE. There should be
    normal memory usage (especially when drawing offscreen), but
    memory use should stabilize after peaking. The exception is
    resizable windows, which may lose a few bytes on resizing (the
    offscreen buffer must be re-initialized to the correct size).
  - You should always use the PAINT style for your program, and
    use "UG DRAW,REFRESH" under the ":PAINT" label.

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