


PINFO_TI(3)                   Contributed Software                  PINFO_TI(3)


NAME
       pinfo_ti  -  Description  of  the terminal interface to the portable
       Infocom datafile interpreter.

SYNOPSIS
       #include <stdio.h>
       #include "infocom.h"

       extern gflags_t gflags;
       extern char     *ti_location;
       extern char     *ti_status;


       const char *scr_usage;
       const char *scr_long_usage;
       const char *scr_opt_list;

       int scr_cmdarg( int argc, char ***argv_p );

       int scr_getopt( int c, const char *arg );

       void scr_setup( int margin,
                       int indent,
                       int lines,
                       int context );

       void scr_begin();

       void scr_putline( const char *buffer );

       void scr_putscore();

       void scr_putsound( int number,
                          int action,
                          int volume,
                          int argc );

       void scr_putmesg( const char *buffer, Bool is_error );

       int scr_getline( const char *prompt,
                        int length,
                        char *buffer );

       void scr_window( int size );

       void scr_set_win( int win );

       FILE *scr_open_sf( int length, char *buffer, int type );

       void scr_close_sf( const char *buffer, FILE *fp, int is_save );

       void scr_end();

       void scr_shutdown();



Revision 3.0                    21 October 1992                               1





PINFO_TI(3)                   Contributed Software                  PINFO_TI(3)


DESCRIPTION
       These routines form  the  interface  between  the  portable  Infocom
       datafile  interpreter  (pinfocom) and a particular type of terminal.
       The pinfocom package comes with interfaces to the following terminal
       types:

       termcap
              This terminal type supports all(?) UNIX systems via an inter-
              face to either termcap or terminfo  terminal  capability  and
              either  termio,  termios,  or  sgtty line discipline control.
              Optional support for the GNU readline line editing  and  his-
              tory library is also available.

       amiga  This  terminal  type  supports  an Amiga interface, including
              sound  and  command  line  editing.   See  amiga.c  for  full
              details.

       msdos  This  terminal  type  supports  MS-DOS  based  systems.   See
              msdos.c for full details.

       stream This terminal type should support any system with  a  C  com-
              piler;  it  uses simple C stdio routines that all C libraries
              will have.  Nothing fancy, but it works.

       Also in the works is an X11-based interface.

       This man page describes the interface between the pinfo  interpreter
       and  the  terminal  support  packages so that programmers can create
       their own interfaces to new systems.   Terminal  interface  will  be
       abbreviated to TI below.

   Environment
       The  interpreter  operates in two modes: game-playing mode (default)
       and information mode (if any of the command-line options -h, -o, -O,
       -v  and/or  -V are given), where the game is not played but informa-
       tion about it is instead displayed on the screen.

       All input and output in game-playing mode is done  via  the  scr_*()
       functions  described  below.   Output during information mode is via
       simple C stdio library functions.

       The only interface between the interpreter and the terminal handling
       code  is through the functions and global variables described below;
       no other symbols in the TI code should be externally visible and any
       other  external  symbols  in  the  interpreter  code  are subject to
       change.

GENERAL
       Some general issues to be considered:

   Asynchronous Events
       The interpreter registers a signal handler for the SIGINT signal and
       sets to ignore the SIGQUIT signal (if defined).




Revision 3.0                    21 October 1992                               2





PINFO_TI(3)                   Contributed Software                  PINFO_TI(3)


       Any  other  signals or other asynchronous events are free to be han-
       dled by the TI as it sees fit.  Note, however, that  none  of  these
       handler  routines  may  modify  or access any interpreter variables:
       interpreter variables listed below are only guaranteed to  be  valid
       when  one  of  the  scr_*() functions below has been properly called
       from within the interpreter code.

   Proportional Fonts
       If the TI supports multiple fonts it is perfectly reasonable to  use
       proportional-width fonts for printing general game text if you wish.

       However, at  certain  points  in  the  game  fixed-width  fonts  are
       required,  such  as  when  printing  maps, etc.  To accomodate this,
       before printing to  the  screen  scr_putline()  (see  below)  should
       invoke  the  macro  F2_IS_SET(B_FIXED_FONT).   If this macro returns
       non-0 then the current buffer should be  printed  in  a  fixed-width
       font;  if it returns 0 then a proportional-width font may be used if
       desired.

   Scripting
       All Infocom games support the script command, which is  supposed  to
       begin  a transcript of the user's adventure.  Normally this initial-
       ized the printer and all subsequent text and commands  were  printed
       to the printer as well as to the screen.

       The  TI  may support this feature as well.  There's no Z-Code primi-
       tive for turning on and off scripting, however: instead  a  flag  is
       set  or  reset.   In  scr_putline() and scr_getline() the macro call
       F2_IS_SET(B_SCRIPTING) should be used; if it returns non-0 then  the
       output  line  or  prompt and command should be printed to the script
       file as well as the display.

       The interface will call scr_open_sf() with a file type of  SF_SCRIPT
       when  a script file is to be opened and scr_close_sf() when a script
       file is to be closed.

   Fixed Window
       Only Seastalker makes use of the fixed window  feature  in  Standard
       Series games, but it's nice to have nevertheless.

       If  the  TI  can  support  a  fixed window in addition to the normal
       scrolling text window then scr_begin() should notify the interpreter
       by calling F1_SETB(B_STATUS_WIN).  In this case the scr_window() and
       scr_set_win()  functions  described  below  will  be  used  to  cre-
       ate/manage/delete the fixed window.

       If  the TI cannot support a fixed window then the above macro should
       not be called and scr_window() and scr_set_win() may be dummy  func-
       tions.

GLOBAL VARIABLES
       These  global  variables are defined in the interpreter code and may
       be used by the TI:




Revision 3.0                    21 October 1992                               3





PINFO_TI(3)                   Contributed Software                  PINFO_TI(3)


   gflags
       Contains global flags and other general variables of interest.   The
       only  field  which may be modified is the pr_status field, if the TI
       doesn't support status line printing.

   ti_location
       This nul-terminated string is a short  description  of  the  current
       location of the player, for printing on the status line.  It is usu-
       ally displayed on the left-hand side of the status line.

   ti_status
       This nul-terminated  string  contains  the  status  of  the  player.
       Depending  on  the game this may be score, score and turn number, or
       the current time in a 12-hour clock.  This string is usually printed
       on the right-hand side of the status line.

       These  global  variables  should  be defined in the TI .c file; they
       will be declared external where used in the interpreter code.

   scr_usage
       The scr_usage variable should be initialized to a string  containing
       info  about  any extra command-line options that the TI makes avail-
       able.  Here's an example from the termcap TI:

           const char *scr_usage = "[-H file] [-C file]";

       If there are no extra command-line options the  variable  should  be
       set to the empty string (""), not NULL.

   scr_long_usage
       The  scr_long_usage  variable  should  be initialized to be a string
       containing a one-line per option description of any  extra  command-
       line  options  that  the TI makes available.  Here's an example from
       the termcap TI:

           const char *scr_long_usage = "\
           \t-H file\tread/store command history in file\n\
           \t-C file\tread/store user command completions in file\n";

       If there are no extra command-line options the  variable  should  be
       set to NULL.

   scr_opt_list
       The  scr_opt_list variable should be initialized to be a string con-
       taining  getopt(3)-style  descriptions  of  any  extra  command-line
       options that the TI makes available.  Briefly, each option character
       is placed in the string; if the option has an argument (no  optional
       arguments allowed) then it should be immediately followed by a colon
       (:).  Here's an example from the termcap TI:

           const char *scr_opt_list = "C:H:";

       If there are no extra command-line options the  variable  should  be
       set to the nul string ("").



Revision 3.0                    21 October 1992                               4





PINFO_TI(3)                   Contributed Software                  PINFO_TI(3)


Interpreter Macros
       The  following  macros are defined in infocom.h and available to the
       TI writer for access to certain data structures.

       The flags available with F1_*() macros are:

       B_USE_TIME
              If set them time is displayed on the status  line,  otherwise
              score/moves  is  displayed.  This is a readonly value; the TI
              cannot change it.

       B_TANDY
              The Tandy license flag; if set then Tandy licensing  mode  is
              turned on, otherwise it's turned off.

       B_ALT_PROMPT
              The alternate prompt flag; if set then alternate prompting is
              enabled, otherwise it's disabled.

       B_STATUS_WIN
              If set the TI supports fixed windows (for Seastalker), if not
              set it doesn't.

       The flags available with F2_*() macros are:

       B_SCRIPTING
              If  set  then  scripting mode is currently enabled, otherwise
              it's disabled.

       B_FIXED_FONT
              If set then the current buffer must be printed  in  a  fixed-
              width font if possible; otherwise it may be printed in a pro-
              portional font.

       B_SOUND
              If set the interpreter  may  issue  scr_putsound()  requests;
              otherwise  it  won't.  Note this flag is readonly and may not
              be set by the TI.

   F?_IS_SET()
       This macro returns a 0 if the specified game header flag is not set,
       and a non-0 (note not necessarily 1!)  if it is not set.

   F?_SETB()
       This macro sets the specified game header flag.

   F?_RESETB()
       This  macro  resets  (un-sets)  the specified game header flag.  The
       following functions are defined in the interpreter and available  to
       the  TI writer for use (no other functions in the interpreter should
       be called).

   xmalloc()
       This function calls malloc() and exits with an error if there is  no



Revision 3.0                    21 October 1992                               5





PINFO_TI(3)                   Contributed Software                  PINFO_TI(3)


       heap left.

   xrealloc()
       This function calls realloc() and exits with an error if there is no
       heap left.

   chop_buf()
       buf    Buffer to be chopped.

       max    Max number of chars wanted

       This function locates the longest section of buf less than or  equal
       to  max  characters  containing at least one complete word.  It does
       not modify the buffer.  It returns a pointer to the space where  the
       line should be broken, or to the nul character ('\0') if buf is less
       than or equal to max chars long.

       This function is useful with fixed-width font TIs  for  chopping  up
       the  buffer  passed  to scr_putline() into sections which fit on the
       screen.  See examples of its use in stream.c.

TI Functions
       The following functions need to be provided by the TI code.

   scr_cmdarg()
       argc   Number of command-line args.

       argv_p Pointer to an array of strings; each one  is  a  command-line
              argument.

       This  function will be called before any other scr_*() function, and
       before the command-line arguments are examined by  the  interpreter.
       It  allows the TI to add (and possibly remove) arguments to the com-
       mand line.

       If the interface has the ability to determine  command-line  options
       from  an alternate source, such as a configuration file, an environ-
       ment variable, windowing resources, or saved game resources, then it
       should  add  these  options to argv_p so they will be noticed by the
       interpreter.

       Note that when  adding  options  they  should  be  inserted  between
       (*argv_p)[0]  and  (*argv_p)[1], shifting the existing options over,
       so that they will be properly overridden by any options given on the
       command line.

       This  function  should return the number of elements in argv_p after
       modification (the new argument count).  It is  expected  that  after
       this function is called, (*argv_p)[0] remains the name of the inter-
       preter program, (*argv_p)[1] to (*argv_p)[argc-1]  are  command-line
       arguments, and (*argv_p)[argc] is 0 (NULL).

       Although  it  is  perfectly legal to remove arguments from argv_p as
       well, this is trickier because you must follow  all  UNIX  getopt(1)



Revision 3.0                    21 October 1992                               6





PINFO_TI(3)                   Contributed Software                  PINFO_TI(3)


       conventions.   It  is suggested that scr_getopt() is used to process
       arguments on the command line, and scr_cmdarg()  used  only  to  add
       extra arguments if needed.

   scr_getopt()
       c      The command-line option character.

       arg    The command-line option argument (if used).

       This  function  will  be  called  each  time  an option specified in
       scr_opt_list is found on the command line.  It  is  guaranteed  that
       only  options  contained  in  scr_opt_list  will be passed, and each
       option which requires a command-line argument will have one.   Error
       messages  for  poorly  formed  options will be printed by the inter-
       preter and this function will not be called.

   scr_setup()
       margin The number of spaces in the right margin.

       indent The number of spaces in the left margin.  Note that  normally
              only the output text is indented, not the command prompts.

       lines  The  number  of  lines per screenful.  If this value is non-0
              then the TI must make every effort to use this value  as  the
              number of lines per screenful.  If it is 0 then the interface
              must infer the screen size as best it can.

       context
              The number of lines that should be kept at  the  top  of  the
              screen  when scrolling; this many lines should be left at the
              top of each page of output if  a  paged  output  mode  is  in
              effect.

       This  function is called after the game has initialized and examined
       its command-line arguments but before anything else is done.  It  is
       called  for  both  game-playing  and information modes, so it should
       perform any setup necessary for general stdio printing.

       This function should return the number of  characters  that  may  be
       printed  on one line in informational mode.  If game-playing mode is
       to be used then this value is ignored.

   scr_shutdown()
       This function should perform any general end processing  appropriate
       for both game-playing and informational modes.

   scr_begin()
       This  function  will be called just before the interpreter goes into
       game-playing mode.  If the interpreter  is  running  in  information
       mode this function will never be called.

       Any  game-playing mode specific processing should be done here, such
       as opening a new window, clearing the screen, setting terminal char-
       acteristics,  etc.  After this function returns the screen should be



Revision 3.0                    21 October 1992                               7





PINFO_TI(3)                   Contributed Software                  PINFO_TI(3)


       set up and the cursor should be positioned at  the  lower-left  hand
       corner of the screen.

       Additionally, if the TI supports the creation of a fixed status win-
       dow (in addition to the normal status line) it should call the macro
       F1_SETB(B_STATUS_WIN);  here  to  notify  the game Z-Code so that it
       will properly call the scr_window() and scr_set_win() functions (see
       below).

   scr_end()
       This  function  should  perform  any  end processing appropriate for
       game-playing mode only, such as deleting windows, resetting terminal
       characteristics, etc.

   scr_putline()
       buffer A  nul-terminated string containing any number of characters.
              The string may be empty, but the pointer will  not  be  NULL.
              There  will  be no newline character ('\n') at the end of the
              string.

       This function should print buffer to the screen, performing whatever
       line wrapping, paging, etc. is necessary.  Processing should proceed
       as follows:

       For each lineful of characters in buffer:

       *   print whatever indent was specified.

       *   print a lineful along with a newline and whatever  scrolling  is
           necessary.

       *   if  the  interface  supports  paging, and it's enabled, and it's
           been (screenful - context)  lines  since  the  last  prompt  was
           printed, then perform whatever paging is necessary.

       If  the  TI  supports  proportional-  and fixed-width fonts then the
       macro call F2_IS_SET(B_FIXED_FONT) should be  used  before  printing
       each line; if the macro returns non-0 then that line must be printed
       in a fixed-width font  if  possible  (maps,  etc.).   If  the  macro
       returns 0 then a proportional font may be used if desired.

       If    the    TI    supports    scripting   then   the   macro   call
       F2_IS_SET(B_SCRIPTING) should be checked; if the macro returns non-0
       then buffer should be printed to the script file as well.

   scr_putscore()
       This  function  is called whenever the values on the status line are
       to be displayed.  If the interface supports status-line printing and
       it  is  enabled,  then  this  function  should  use  the  values  of
       ti_location and ti_status to display the status line on  the  screen
       in  whatever  manner  it chooses (these variables always contain the
       proper values; they may be used by any TI function).

       This function should be also be called whenever the  TI  code  might



Revision 3.0                    21 October 1992                               8





PINFO_TI(3)                   Contributed Software                  PINFO_TI(3)


       have disturbed the status line.

   scr_putsound()
       number The sound number to be played.

       action The action to be taken.

       volume The volume at which to play the sound (between 1 and 8).

       argc   The number of arguments (1 to 3) passed to the function.

       This  function  will  be called by the interpreter if the game being
       played contains sound support.  If  the  interface  doesn't  support
       sound  then  a  simple  output  line may be printed by this function
       stating that fact.

       Unfortunately different versions of Infocom games require  different
       methods  of  sound  support, but generally a separate sounds file is
       supplied with the datafile and the  sounds  must  be  retrieved  and
       played from there.

   scr_putmesg()
       buffer A  nul-terminated string containing a message from the inter-
              preter.

       is_error
              Set to 1 if the message is an error message, or 0 if it's  an
              informational message only.

       This  function  is  called whenever the interpreter needs to print a
       message for some reason.  Messages from the game will be printed via
       scr_putline().   The  TI  should  not attempt to exit the program or
       anything else; the interpreter will decide what to do about the mes-
       sage.

   scr_getline()
       prompt A  nul-terminated  string  which  is the prompt to be printed
              when requesting a command.

       length The maximum number of characters (including the  nul  charac-
              ter) which can be placed in buffer.

       buffer A string of length characters, in which the command should be
              returned.

       This function is called when the  interpreter  needs  command  input
       from the user.  The function should accept up to length-1 characters
       of input and place them, along with  a  terminating  nul  character,
       into  buffer.   All  command  history, editing, shell escaping, etc.
       etc. must be done internal to this function.  Also if the user types
       more  than length-1 characters the function should flush the rest of
       the input and notify the user that it is doing so.

       If this function causes the status line to be  messed  up  (i.e.,  a



Revision 3.0                    21 October 1992                               9





PINFO_TI(3)                   Contributed Software                  PINFO_TI(3)


       shell  escape causes extra lines to be printed, etc.) care should be
       taken to rewrite the status line correctly.

       The interpreter supports an "interpreter escape mode", where  inter-
       preter  flags  and options may be modified.  This mode is invoked by
       the user typing the escape character (by default ``@'') as the first
       character  on  the  command line.  If this function sees that as the
       first character, it should call ti_escape() with  the  remainder  of
       the  command  line  ( not the escape character).  Once that function
       returns the prompt should be reprinted  and  more  input  should  be
       obtained  without  returning.   If  the TI wishes to provide its own
       escape  commands  it  should  process  them  itself  and  not   call
       ti_escape() for those commands.

       The  escape  char by itself will list the available options.  If the
       TI wishes to supply options in addition to the interpreter  options,
       it should call ti_escape() first, then print its own options.

       Note  that the TI may provide alternative ways of manipulating these
       options, such as pull-down or pop-up  menus  on  windowing  systems;
       ti_escape() can be called whenever control is properly passed to the
       TI; not from a signal handler, etc.

       If the TI supports scripting, then it should check  the  command  to
       see  if  it  was  "script".   If it was and scripting is not already
       enabled then it should be enabled here.  If the enabling fails  then
       an error should be printed and the TI should ask for another command
       without returning to the interpreter.

       The function should return the  number  of  characters  placed  into
       buffer, not counting the terminating nul character.

   scr_window()
       size   Create  a fixed status window size lines high.  If size is 0,
              then delete the current fixed status window (if any).

       This function is called if the game supports a fixed  status  window
       (currently  Seastalker  is  the only such Standard Series game), and
       the TI has registered that it supports such functionality by calling
       F1_SETB(B_STATUS_WIN) in scr_begin() (see above).

       The  function will be passed the number of vertical lines needed for
       the fixed status window.  When the window is to be deleted  it  will
       be  passed  an argument of 0.  Note it may be passed a 0 even if the
       window currently doesn't exist; in this  case  the  function  should
       just silently return.

       If  the TI doesn't support a fixed status window then just provide a
       dummy function which does nothing.

   scr_set_win()
       win    Determines which window to start printing in.

       This function is called if the game supports a fixed  status  window



Revision 3.0                    21 October 1992                              10





PINFO_TI(3)                   Contributed Software                  PINFO_TI(3)


       (currently  Seastalker  is  the only such Standard Series game), and
       the TI has registered that it supports such functionality by calling
       F1_SETB(B_STATUS_WIN) in scr_begin() (see above).

       After  the  scr_window()  function has been called (see above), this
       function will be used to switch back and forth between the two  win-
       dows.   If  called  with  win set to 0, then the TI should set up to
       start printing in the regular text window.  If called with  win  set
       to 1, then set up to start printing in the fixed status window.  All
       actual printing is done with the normal scr_putline() function.

   scr_open_sf()
       length The maximum number of characters (including the  nul  charac-
              ter) which can be placed in buffer.

       buffer A  string  of length characters, in which the filename should
              be returned.

       type   The type of save file to be opened: SF_SAVE,  SF_RESTORE,  or
              SF_SCRIPT.

       This  function  is  called when the interpreter needs to open a save
       game file for either saving or restoring, or to open a script  file.

       When scr_open_sf() is called, buffer will contain a default filename
       (initially it will be a static name, after the first  call  it  will
       contain  the  last filename entered).  If length is 0, then the file
       should just be opened and the file pointer returned.  If  length  is
       greater  than  0,  the  function should print an appropriate prompt,
       then accept up to length-1 characters of input and place them, along
       with  a  terminating  nul character, into buffer then open that file
       and return the file pointer.

       If type is SF_SAVE or SF_SCRIPT, then the file is  being  opened  to
       save the game or write script to and so should be opened for writing
       (binary mode for SF_SAVE and plain text mode  for  SF_SCRIPT).   The
       function  should  test if the file already exists and if so, ask the
       user to confirm overwriting it.

       If type is SF_RESTORE, then the file is being opened  to  restore  a
       game and so should be opened for reading in binary mode.

       Any  command  history, editing, filename completion, shell escaping,
       etc. etc. must be done internal to this function.  Also if the  user
       types  more  than  length-1 characters the function should flush the
       rest of the input and notify the user that it is doing so.

       If this function causes the status line to be  messed  up  (i.e.,  a
       shell  escape causes extra lines to be printed, etc.) care should be
       taken to rewrite the status line correctly.

       If the TI wishes to use this function for other purposes,  the  type
       argument  can  be used: the interpreter will only call this function
       with values >=0 for type so the TI is free to call it  with  special



Revision 3.0                    21 October 1992                              11





PINFO_TI(3)                   Contributed Software                  PINFO_TI(3)


       values <0 if it wishes.

       The  function should return a FILE pointer to the open file.  If the
       user cancels the operation somehow or the open fails, then the func-
       tion  should  return 0 (NULL).  If the return value is NULL then the
       interpreter will examine errno: if errno is 0 then  the  interpreter
       will  assume  the  operation  was  canceled;  if it's non-0 then the
       interpreter will assume there was an error  during  opening  of  the
       file and print an appropriate error message.

       If  the  function  returns non-NULL, the interpreter will attempt to
       read/write data from  the  current  position  in  the  file  without
       rewinding  or other manipulation.  This means that you may store TI-
       specific information at the beginning of saved game files  and  read
       them back in when restoring if you like.

   scr_close_sf()
       filenm The name of the game file just saved/restored

       fp     FILE pointer of the game just saved/restored

       type   The  type  of save file to be opened: SF_SAVE, SF_RESTORE, or
              SF_SCRIPT.

       This function is called immediately after a game save file is  saved
       or  restored  or  a  script file is to be closed.  At the very least
       this function should perform an fclose(fp) to close the file.  Addi-
       tionally it may add more terminal-specific data, create special con-
       figuration files, change file privileges, etc.

       If the TI wishes to use this function for other purposes,  the  type
       argument  can  be used: the interpreter will only call this function
       with values >=0 for type so the TI is free to call it  with  special
       values <0 if it wishes.

Writing a New Interface
       If  you  wish  to  create  a  new  TI, I suggest that you start with
       stream.c as the simplest current interface.  Be sure you examine all
       of  this  code  so you understand in detail what each function does.
       You should then create your own .c file and add functionality as you
       like.

MAKEFILE
       After  you  create your new TI you should name the .c file something
       relevant, such as pcdos.c for an interface to an  IBM  PC-compatible
       in DOS, or pcwindows.c for an interface to an IBM PC-compatible run-
       ning MS-Windows,  or  something.   Then  you  should  create  a  new
       TERMTYPE  section  in  the Makefile.  Decide what, if any, flags you
       need to give to the compiler and fill in TERMFLAGS; likewise for any
       extra libraries you need and TERMLIB.

       If you'd like your interface distributed with the pinfocom distribu-
       tion, and an interface doesn't already exist, then send  it  to  the
       pinfocom  maintainer and he/she'll incorporate it in.  Note you must



Revision 3.0                    21 October 1992                              12





PINFO_TI(3)                   Contributed Software                  PINFO_TI(3)


       place your interface code under the GNU Public License for it to  be
       distributed (see the copyright notices in the other files), and pro-
       vide an address for people to contact you about bugs,  enhancements,
       etc. in a comment in the .c file.

       If  an  interface  already  exists  then  you'll have to contact the
       author and the two of you can hash it out between you :-).


















































Revision 3.0                    21 October 1992                              13


