                                JFTerm scripts
                                --------------

Note: This is not completely correct for this version of JFTerm...

Introduction
-------------
This document explains how to use the scripting system for writing new
styles. You do not need to understand it to use JFTerm as it stands.


Scripting system
----------------
I've not finished this yet. I'm still developing the libraries, so as I
need more features I'll no doubt add them to the system. Please note that the
IRC library /does not/ work 100% correctly - lines > 256 bytes *may* be
poorly processed (if you're reading this as an update, I've changed the
wording - support is a little better now :-) ). It may (or may not) be
improved. A better solution would be to improve BASIC to handle longer
strings; but this is non-trivial.


How to write style scripts
--------------------------
Style scripts are essentially very easy. There are a few routines you must
provide to be recognised correctly by JFTerm (error handling is somewhat
non-existant atm :-( ). Each of the routines is a function call with the
generic name 'FNlib_<libname>_<routine>' where <libname> is the name of the
library with dot's in it's path changed to _'s - look at the examples and
you'll get the idea. The routines which need to be written are :

* FNlib_<x>_flags  : Return the capabilities of this style
    Currently only a few are defined :
       f_HasMenus   - set if you will be supplying menu items
       f_Keys       - set if you will be handling unknown keypresses
       f_SupURL     - set if you will be supporting URL requests
       f_HasDaemons - set if you will be providing daemons
       f_HasLibMenu - set if you will be providing a menu on the 'Info' window
       f_PartialDisplay - set if you want lines which have not yet been fully
                          received to be displayed
       f_HasUserMsg - undocumented
       f_HasColsMenu- undocumented
    Simple styles will want to return 0 or f_PartialDisplay.

* FNlib_<x>_desc(disp) : Describe yourself in the info window
    You should describe yourself using PROCdisplay_add(disp%,"<something>")
    and return the amount of 'global workspace'you require. You are allowed
    to add as many lines as you like :-)

* FNlib_<x>_type : Return the style name
    You should return a style name with a trailing : (followed by a patch name
    for extension patches).

* FNlib_<x>_space : Return the amount of workspace you need per connection
    If you don't need any workspace for your sessions you should return 0.
    If you request some space you will be passed this in each subsequent
    call.


* FNlib_<x>_init(g%) : Initialise module
    You should start any daemons you need using :
      d%=FNdaemon_start(port)
    Any other things you want to set up can be done here.
    You may set up any global variables you want to use here, but it would
    be preferable to use your global workspace for this.
    Return TRUE to mean 'ok'

In the following routines c% is the connection handle and should be returned
in routines which talk to JFTerm, p% is a pointer to your private workspace
for this session, d% is the daemon handle, and g% is a pointer to you global
workspace (or 0 if none). You can store things you want to hold on to in your
private space, but only up to the limit defined in FNlib_<x>_space. You
should return TRUE if you don't want any more processing (should always be
done for the base style).


* FNlib_<x>_connect(g%,c%,p%,host$) : We've got a connection
    Anything you want to do on connection should be done now.

* FNlib_<x>_disconnect(g%,c%,p%,RETURN msg$) : We've lost our connection
    You should free any space you are using in your private space (the space
    itself will be automatically released), close any files and generally
    tidy up. If you want to modify the parting message you can.

* FNlib_<x>_lineentered(g%,c%,p%,line$) : The user has entered something
    You should process this into something to send to the connection. The
    simplest thing you can do is simply call PROCsendline(c%,line$). If you
    wish to modify the line before returning FALSE you may (all patches).

* FNlib_<x>_incoming(g%,c%,p%,f%,RETURN a$) : The connection received something
    You should process the line as if it were the start of a line if f% is
    TRUE, and as if it is a continuation of a prior line if f% is FALSE.
    If you wish to modify the line before it is displayed you may (patches).
    To show the line yourself you should use PROCshow(c%,f%,line$), where
    f% is TRUE if you want to start a new line and FALSE otherwise (as
    above).
    Returning FALSE will just show the line in the display.

If f_Keys is set you should provide :

* FNlib_<x>_keypress(g%,c%,p%,key%,line$,idx%) : A key has been pressed
    You should process the line and modify the input string using
    PROCsetinput(c%,line$,[idx% | -1]). idx% contains the index into the
    string of the caret. Return TRUE if you handled the keypress.

If f_HasMenu is set you should provide :

* FNlib_<x>_buildmenu(g%,c%,p%) : We need a menu for this display
    You should build a menu using the dynamic menu library calls. Quickly,
    these are :
      PROCdynmenu_add(item$,sprite$,%smwlt)
        (Shaded, Message, Writable, Line, Ticked)
        (Message not supported yet)
      PROCdynmenu_submenu(name$)
      PROCdynmenu_attach(FNdynmenu_end)
    You should return TRUE if you don't wish any extra items to be added.

* FNlib_<x>_menuchoice(g%,c%,p%,m$) : Something has been chosen
    You should perform some action based on the string chosen (FNdecodemenu
    string).
    Return TRUE if the menu structure has been modified by your action (N/A).

If f_HasDaemons is set you should provide :

* FNlib_<x>_daemon_die(g%,d%) : Daemon should die at user request
    This is called when the entry on the 'Close' menu is selected. You
    should remove all your references to it, or deny it's closedown.
    Return TRUE if you have deleted your references to the daemon and it
    can die. Return FALSE if you don't want the daemon to closedown.

* FNlib_<x>_daemon_connect(g%,d%,host$) : Requested connection of daemon
    This is called to ask if you want to handle the connection. If you wish
    to close the connection you should do so as a callback.
    Return TRUE to accept the connection, FALSE to deny it.

If f_HasLibMenu is set you should provide :

* FNlib_<x>_buildlibmenu(g%) : Build a library menu
    You should build a menu using :
      PROCdynmenu_add(item$,sprite$,flags%)
        (message /is/ valid and will be passed to libmenumsg
      PROCdynmenu_attach(menu%)
    You may attach colour menus using colsmenu%, but you'll probably need to
    set the 'message' flag.
    Return TRUE.
    
* FNlib_<x>_libmenuchoice(g%,m$) : Something has been picked from your libmenu
    You should process the menu string, possibly using the block at b%
    to determine the selection. You may use :
      col=FNcolfrommenu(blk%)  : to decode a colour menu
      PROCtickcolour(col%)     : to tick a colour item
    Return TRUE if your menu has changed (it will be regenerated), FALSE if
    not. libmenumsg calls will /not/ be made in the recreation.
    
* FNlib_<x>_libmenumsg(g%,m$,menu%) : Submenu about to open
    You should process the menu string and produce tick any menu items
    relevant. Most likely you'll want to call :
      PROCtickcolour(col%)   : To tick a colour menu entry
    You should return the menu handle, or another handle.

If f_SupURL is set you, should provide :

* FNlib_<x>_url(g%,type$,url$) : URL request has been received
    You should check the type of the url and if you like it return TRUE.
    Opening connections can be performed here with :
      c%=FNconnection(host$,port%,style$)
    which returns the handle of the connection, or 0 if it couldn't connect.

* FNlib_<x>_urlboot : The !Boot file is being run; set up variables
    You should set up any system variables you want to support.
    The most common setting is likely to be :
      *Set Alias$URLOpen_<type> Run <JFTerm$Dir>.!Run -url %*0

If f_UsePane is set, you should provide :

* FNlib_<x>_paneclick(g%,c%,p%,pane%,button,icon)
    You should check the button flags and icon, and possibly the pane as
    well. No means is available at present to generate menus.

Within your code you may use :

PROCsendline(c%,line$) : Sends something to the connection
PROCshow(c%,f%,line$)  : Shows something in the display (will also be spoken if
                         speak text is configured)
PROCspeak(voice%,line$): Speaks a line of text explicitly.
PROCsetinput(c%,line$) : Sets the users input line
FNclaim(size%)         : Claims some memory
FNstrdup(str$)         : Claims some memory and store a string in it
PROCrelease(mem%)      : Releases some memory
FNfg(x)                : Sets foreground colour
FNbg(x)                : Sets background colour
FNbold                 : Toggles bold
FNunderline            : Toggles underline
FNinverse              : Toggles inverse
FNreset                : Resets all colour and style changes
FNnormal               : Resets bold, inverse, underline and flashing
PROCdisconnect(c%,msg$): Disconnects a connection
FNupper(a$)            : Capitalises a string
FNtidy(a$)             : Capitalises words
PROCtickcolour(num%)   : Tick a colour on colsmenu%
FNcolfrommenu(blk%)    : Read colour from the menu (blk-> start of colsmenu%)
colsmenu%              : Menu structure for a menu of colours
FNgethost(c%)          : Read the hostname of a connection
FNdaemon_start(port)   : Start a daemon on a port (returns daemon handle) if
                         port is 0 a port will be allocated dynamicly
PROCdaemon_stop(d%)    : Stop a daemon
FNdaemon_getport(d%)   : Read the port number of a daemon
PROCcallback(m$,c$,p$) : Call a user routine of the form FNuser_m$_c$(g%,<p$>)
                         when we're not threaded.
FNconnection(h$,p%,s$) : Create a new connection to a host, port in a style.
FNaddpane(c%,file$,name$,sprites%,where) :
                         Attach a pane to a connection window. where is
                         documented in PaneLib.


Proxying
--------
Proxying is currently a program selected option. This will be changed soon.
The proxy library is named 'ProxyLib' and contains three functions :

* FNproxy_init : Initialise the proxy and find the amount of workspace required
    Initialises any variables/connections required for the proxy.
    Returns the amount of workspace required for each proxied connection

* FNproxy_connect(p%,host$,port%)
    Attempts a connection to a host on a port. Sockets should be set up and
    the correct connection established.
    Return the socket handle, or 0 if failed

* FNproxy_incoming(p%,c%,line$)
    Data is coming in through the proxy. You should parse this to check that
    it's valid and return the correct string depending on the state.
    Return "" if the proxy is still being accessed,
           CHR$0 if the connection has been made and subsequent data is from
                 the host requested
           other if there was an error (string is the message)

p% is your private workspace, c% is the connection handle - you can do the
normal connection type things with it.


