#GemZ Api: Accurate to Version 3.10beta %9.15#1

If you are writing an addon script to GemZ, this document is for you.  If 
you are seeking general GemZ/OpenChat help, you should use the /help
command from within the IRC client.

(Note: this is unfinished... preliminary release)

The GemZ 3rd Party MANUAL

	(C) Copyright 1997-1998 by gemini (gemini@silcom.com)

#############
## PURPOSE ##
#############

  GemZ is a fully functional script, but it has hooks and functions
  to enable other folks to add on to it.  (I will refer to these scripts
  and the use of these extra features as "3rd Party").  This 
  Manual will describe these features and document the GemZ "api".

  This document assumes you know basic and intermediate IRCII scripting
  and have a general knowledge of some of the extra features of 
  OpenChat/2 such as scripting menus.

###################################################################

##########################################
## HINTS and 3RD Party Scripting Basics ##
##########################################

When adding on to GemZ (or any other script for that matter, some basic 
rules should apply. 

1. Event Hooks:

  When adding on to any script that is a fully functional script, you
  should realize that the main script will handle the basic On hooks.  
  You should NOT overwrite these.  For example your script should 
  never hook "^on ^msg "*" {#code here}

  The reason is simple.  The main script DEPENDS on these hooks being there.
  To add your functionality to the msg function, you should use what is known
  as serialized on hooks.  I won't go into great detail here, as you will be
  able to find this information in most IRC manuals (including the one I
  plan on writing after this document is finished).

  The basics of serialized on hooks:

  You can hook the same event a number of times by adding a serial number
  to the hook.  IE ^on #^msg 5 "*" {#your code here}  Keep in mind that the
  number is also the order in which each hook is processed, 0 being the 
  original "^on ^msg "*" {} hook.  In other words... on ^msg  will be hooked
  first, then on #^msg 1 (if it exists)... and so on.  You don't have to
  go in order.

  Keep in mind that GemZ uses *SOME* serialized hooks as well.  A good 
  practice would be to pick ONE obscure number, and use that for ALL of your
  addons.  IE.  on #^msg 712... on #^notice 712 etc etc...
  
2. Freeing assigns.

  Good practice in any script is to free an assign when you are done with it.
  If it is a single assign: "^assign -variablename" 
  If it is an array: purge arraystem

3. Variable stomping.

  As with on hooks, you should not stomp on top of any variable that gemz
  may use, you should also not assume that because you changed a value, or
  setting the associated menu or status bar portion will change with it.  
  GemZ handles those things internally based on events.  In these cases you
  should contact me to find out how to notify gemz of the change in values.

4. Make your script reloadable if possible.

  This is often easily done by adding a line such as:
 		  if (!myscriptloaded) {}
  to your script to set values which much be initialized on first load, 
  but shouldn't be messed with on a reload.  At the end of the script
  setting "@ myscriptloaded = 1" will assure this.  (change the variable
  name of course).

5. Key bindings.  

  I reserve any key bindings for my own use later.  Don't count on any 
  binds that are currently unused to stay unused every GemZ release.

  Exception:  I have left all the contol-fkey bindings free so that addon
  scripts can use them.  I will NOT use these binding in any subsequent 
  GemZ release.

###################################
## Version Advertising and reply ##
###################################

GemZ has a built in function to return all versions including 3rd party
scripts, as long as you follow this simple format.  For each 3rd party
script you should set one assign using the gzver.yourscirpt format.

For example, if my addon script for GemZ was called momoware... i might
set the following:

@ gzver.momo = [MoMoWaRe 1.0 (Private release)]

gz.versions() would return:

 GemZ/2 v3.0 (%11.30#1) + MoMoWaRe 1.0 (Private release)

Note: for those of you who have already hacked your version into gemz with
the /set client_information.  You should take that code out... GemZ will 
automatically do it for you.  It will sync the version information 
dynamically when any version information is requested by you or another user.

##################################
## Customizing the GemZ MenuBar ##
##################################

3rd Party Scripts may add on to the bottom of each of the Submenus
available from the main menu bar by filling in the stub functions.  These
stub functions (when fully written) are called from gemz on a reload or
when gz.menubarreset is called.  You should addont to the gemz existing
menus by using menuitem, or submenu. 

Example:

#inside of 3rd party script
 alias gz.addonmain {
  menuitem main "3rdParty Status" {myfunction}
  submenu main mysubmain "My setup"
   menuitem mysubmain "Setup 3rd party stuff" {mysetupfunction}
 }
 #...
 gz.menubarreset
#End of example

You should call gz.menubarreset from your 3rd party script at the end.  
This will recreate the gemz menus using your 3rd party add ons.


 Stub Lists:
  alias gz.addonmain {}
    #add on to menu main
  alias gz.addonjoin {}
    #add on to menu join
  alias gz.addonuser {}
    #add on to menu user
  alias gz.addonsrv {}
    #add on to menu srv
  alias gz.addonxdcc {}
    #add on to menu xdcc
  alias gz.addonmsgs {}
    #add on to menu msgs
  alias gz.addongemz {}
    #add on to menu gemz
  alias gz.addonhelp {}
    #add on to menu help


#######################
##  GemZ Event Hooks ##
#######################
 These are internal hooks that are activated on certain GemZ events.
 You can access them externally with an ^on hook.  This was primarily 
 added so that I could write a Speech Synthesis addon to GemZ.
 These are provided to you so you do not have to rewrite the code in 
 GemZ to add extra functionality... Hooks will be added to GemZ on request.

 Hooks:

  gzaway
    (hooked when you set /away)
  gzback <tdiff time string>
    (hooked when you set /back)
  gzcycle channel
    (hooked when you /cycle)
  gzcmd   <nick> <ok|failed>
    (hooked when someone issues a /gzcmd to you)
  gzsave
    (hooked when your settings are saved)
  gzlog <on|off>
    (hooked when your log is turned on/off)
  gznetsplit
    (hooked when a netsplit is detected)
  gznetjoin
    (hooked when a netjoin is detected)
  gzuptime <tdiff style string>
    (hooked when you type /uptime)

 example Usage: 
  ^on hook "gzaway" {speechsay You have set away}

#########################################
## HOW TO RELOAD YOUR 3RD PARTY SCRIPT ##
#########################################

(unfinished)

###############
## FUNCTIONS ##
###############
There are many features which I have written for internal GemZ reasons that
you may find usefull in your 3rd party script as well.  For this reason I 
document them so you will not have to rewrite what is available to you.  I am
not going to document every GemZ function, just the ones I think would be 
usefull to you.

Coding examples are provided, and are a basic hybrid of my coding style
but made to be a bit easier to read.  They are meant to be used by 
experienced coders.  If you don't understand the code, please take time
to review an irc scripting manual.

(unfinished)


Function: $gz.bytestomegs()
Input   : <number of bytes>
Returns : Nearest Number (with decimals to two places) of Megs
Example :
      echo *** File is $gz.bytestomegs(12346321) Megs
      The output would look like:

              *** File is 11.77 Megs

Function: $gz.chanops()
Input   : <#channel>
Returns : List of channel ops in specified channel

Function: $gz.chatstat()
Input   : <nick>
Returns : 0 if no chat, 1 if chat is waiting, 2 if chat is active, 3 if chat is offered

Function: $gz.cols()
Input   : <refnum | window_name | channel | query> <r | n | c | q>
Returns : Number of columns available to specified window.
Note    : use gz.cols(<refnum> r) for refnums, gz.cols(#channel c)
        : for channels, etc. Returns 80 if the window is minimized, and
        : 0 if window is not found

Function: $gz.drivetype()
Input   : <path to valid dir>
Returns : "hpfs", "fat", "bad_dir", or "error" 
Note    : It is preferable to send this a path with the drive letter
          In it, as the function will cache this information, thus 
          creating less overhead next time the function is called.
Example :
   @ _drivetype = gz.drivetype($exedir/script)
   switch ($_drivetype) {
    (fat) {echo *** drive is fat}
    (hpfs) {echo *** drive is hpfs}
    (bad_dir) {echo *** Directory does not exist}
    (error) {echo *** Unknown error occured}
    (*) {echo *** Got unexpected return code}
   }

Function: $gz.fixbytes()
Input   : <number of bytes>
Returns : A Formatted number with appropriate unit, guaranteed to 
          be 4 characters or less
Note    : Currently only accurate to 999M, if needed I will expand this.
Example : $gz.fixbytes(1234) gives "1.2k"
          $gz.fixbytes(1234567) gives "1.1M"


Function: $gz.fixnum()
Input   : <number>
Returns : Comma formated number.  Negative numbers work as well.
Example :

       echo *** Swapper.dat size is $gz.fixnum($fsize(c:\os2\system\swapper.dat)) bytes

       The output would look like:
       *** Swapper.dat size is 12,582,912 bytes


Function: $gz.fixpath()
Input   : <somepath>
Returns : Path with all backslashes converted to irc compatible forward slashes
Note    : any path that is saved, should be saved in forward slash format

Function: $gz.lamers()
Input   : <#channel>
Returns : List of all non-ops and non-voices in specified channel

Function: $gz.lastw()
Input   : <word list>
Returns : The last word in a list of words.

Function: $gz.minimizedlist()
Input   : <server number>
Returns : list of all channels, on given server, that are in minimized windows.

Function: $gz.nuh_nick()
Input   : <nick!user@host.com>
Returns : Only the nick (ie nick)

Function: $gz.nuh_user()
Input   : <nick!user@host.com>
Returns : Only the usernick (ie user)

Function: $gz.nuh_host()
Input   : <nick!user@host.com>
Returns : Only the host (ie host.com)

Function: $gz.rows()
Input   : <refnum | window_name | channel | query> <r | n | c | q>
Returns : Number of rows available to specified window.
Note    : use gz.rows(<refnum> r) for refnums, gz.rows(#channel c)
        : for channels, etc. Returns 25 if the window is minimized, and
        : 0 if window is not found

Function: $gz.striplastslash()
Input   : <somepath>
Returns : Same String with trailing slash removed if it exists
Note    : this is usefull if you can't have a trailing slash, and you've 
          queried the user for a path where he may have added the final slash.
          Please note that this does not use an implied gz.fixpath(), you should
          convert any user entered strings to irc format with gz.fixpath() first,
          then apply gz.striplastslash()

Function: $gz.servergroups()
Input   : None
Returns : List of all of your servergroups.

Function: $gz.strlen()
Input   : <any string>
Returns : the number of characters in the string.
Note    : Irc can use the "@" preceding a variable name to get the length of a string
          (ie $@varname) so where possible use that, but in the case of $0 or $* 
          you cannot use $@0 or $@*, thus gz.strlen() is a nice way around that 
          limitation.

Function: $gz.srv_serv()
Input   : <server:port> (ie irc.server.com:6666)
Returns : Only the server portion (ie irc.server.com)

Function: $gz.srv_port()
Input   : <server:port> (ie irc.server.com:6666)
Returns : Only the port portion (ie 6666)

Function: $gz.versions()
Input   : <none>
Returns : Formatted Version list of GemZ and all 3rd party scripts that
          adhere to the Api format set forth above.


Function: $gz.voices()
Input   : <#channel>
Returns : List of voices (not counted if nick has both +v and +o)
Note    : If user is +o user, user is not considered +v

#sorry, these api calls aren't in gz.<api> format, but they are part of the api.
  
Function: $uh()
Input   : <nick> [-s]
Returns : The hostname (user@host) of the nick that it is passed if it is 
          available in the OpenChat cache. (In other words, if the nick 
          is in one of your channels).  It will return nothing if it is not.  
Note    : This function can save you the time of querying the server for 
          a user@host.  If my nick is gemini, and my host is 
          gemini@silcom.com... then the code: 
             if (uh(gemini)==[gemini@silcom.com]) {}
          would evaluate to true (1).
          If -s is specified, then uh will strip the first ~ if one exists.
          (Idea by Poohbear)

Example :
  alias quickban {
    if (onchannel($0 $C) && ischanop($N $C)) {
      //mode $C +b *!$uh($0)
    } 
  }

Function: $_bool()
Input   : (<something that means true usually>)
Returns : 0 or 1 (False or True)
Note    : this is an optimization function mostly.  It is meant to get
          a 0 or 1 return from something like YES, ON, TRUE, etc...
Example :

  Old code:  if ([$somevar] == [ON] || [$somevar] == [YES]) {echo it's on}
  New code:  if (_bool($somevar)) {echo it's on}

######################
# XDCC Api Functions #
######################

Function: $gx.getcount()
Input   : None
Returns : The number of DCC Gets currently in progress

Function: $gx.nheader1()
Input   : None
Returns : Default Notice Header (Line 1)

Function: $gx.nheader2()
Input   : None
Returns : Default Notice Header (Line 2)

Function: $gx.maxqueue()
Input   : None
Returns : The currently set maximum number of queued nicks allowed.

Function: $gx.maxsends()
Input   : None
Returns : The currently set maximum number of sends allowed.

Function: $gx.numpacks()
Input   : None
Returns : The number of packs you currently have offered.

Function: $gx.oheader1()
Input   : None
Returns : Default Offer Header (line 1)

Function: $gx.oheader2()
Input   : None
Returns : Default Offer Header (line 2)

Function: $gx.packbytes()
Input   : <packnum>
Returns : Number of bytes (all files) in specified pack.

Function: $gx.packcount()
Input   : <packnum>
Returns : Number of time specified pack has been requested. 

Function: $gx.packdesc()
Input   : <packnum>
Returns : The description, if it exists, of specified pack.

Function: $gx.packfiles()
Input   : <packnum>
Returns : List of files in specified pack.

Function: $gx.packnote()
Input   : <packnum>
Returns : The extended note of the specified pack.

Function: $gx.packpass()
Input   : <packnum>
Returns : The password, if it exists, of specified pack.

Function: $gx.qcount()
Input   : None
Returns : The number of Queue entries present

Function: $gx.record()
Input   : None
Returns : Current xdcc send transfer record in k/s (Units are NOT appended)

Function: $gx.sendcount()
Input   : None
Returns : The number of DCC Sends currently in progress

Function: $gx.sendcount()
Input   : None
Returns : The number of DCC Sends and Gets currently in progress, does
          not include Chats or Raws.

Function: $gx.totaloffered()
Input   : None
Returns : Total number, in bytes, you have currently offered (All packs)

Function: $gx.totalsent()
Input   : None
Returns : Total number, in bytes, you have sent from current packlist
