home *** CD-ROM | disk | FTP | other *** search
/ Frozen Fish 1: Amiga / FrozenFish-Apr94.iso / bbs / alib / d8xx / d834 / pinfocom.lha / PInfoCom / pinfocom-3.0.lha / amiga.c < prev    next >
Text File  |  1993-02-21  |  64KB  |  2,754 lines

  1. /* amiga.c
  2.  *
  3.  *  ``pinfocom'' -- a portable Infocom Inc. data file interpreter.
  4.  *  Copyright (C) 1987-1992  InfoTaskForce
  5.  *
  6.  *  This program is free software; you can redistribute it and/or modify
  7.  *  it under the terms of the GNU General Public License as published by
  8.  *  the Free Software Foundation; either version 2 of the License, or
  9.  *  (at your option) any later version.
  10.  *
  11.  *  This program is distributed in the hope that it will be useful,
  12.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14.  *  GNU General Public License for more details.
  15.  *
  16.  *  You should have received a copy of the GNU General Public License
  17.  *  along with this program; see the file COPYING.  If not, write to the
  18.  *  Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  19.  */
  20.  
  21. /*
  22.  * $Header$
  23.  */
  24.  
  25. /*
  26.  *  Amiga    terminal  interface  created  by  Olaf  `Olsen' Barthel, send
  27.  *  complaints and bug reports to:
  28.  *
  29.  *  Until mid-July 1993:
  30.  *
  31.  *         Olaf `Olsen' Barthel
  32.  *         Brabeckstrasse 35
  33.  *         D-3000 Hannover 71
  34.  *
  35.  *         Federal Republic of Germany
  36.  *
  37.  *  After mid-July 1993 (German national ZIP code change):
  38.  *
  39.  *         Olaf `Olsen' Barthel
  40.  *         Brabeckstrasse 35
  41.  *         D-30559 Hannover
  42.  *
  43.  *         Federal Republic of Germany
  44.  *
  45.  *  EMail: olsen@sourcery.mxm.sub.org
  46.  *
  47.  *  This  interface has been designed to work on any Amiga machine running
  48.  *  Kickstart  1.2   or  higher.   Unlike the original Infocom interpreter
  49.  *  interfaces,  it  supports command-line history (20 lines are standard,
  50.  *  the  number can  be changed at compile-time) and command-line editing.
  51.  *  Editing functions are as follows:
  52.  *
  53.  *  - Backspace
  54.  *
  55.  *    Deletes the character to the left of the cursor.
  56.  *
  57.  *  - Shift + Backspace
  58.  *
  59.  *    Deletes everything from the cursor backward to the start of the line.
  60.  *
  61.  *  - Delete
  62.  *
  63.  *    Deletes the character under the cursor.
  64.  *
  65.  *  - Shift + Delete
  66.  *
  67.  *    Deletes everything from the cursor forward to the end of the line.
  68.  *
  69.  *  - Control + X
  70.  *
  71.  *    Deletes the entire line contents.
  72.  *
  73.  *  - Control + \
  74.  *
  75.  *    Closes the window.
  76.  *
  77.  *  - Control + A
  78.  *
  79.  *    Moves the cursor to the start of the line.
  80.  *
  81.  *  - Control + Z
  82.  *
  83.  *    Moves the cursor to the end of the line.
  84.  *
  85.  *  - Control + W
  86.  *
  87.  *    Deletes the word to the left of the cursor.
  88.  *
  89.  *  - Control + K
  90.  *
  91.  *    Deletes everything from the cursor forward to the end of the line.
  92.  *
  93.  *  - Control + U
  94.  *
  95.  *    Deletes everything from the cursor backward to the start of the line.
  96.  *
  97.  *  - Control + C
  98.  *
  99.  *    Remembers current input line contents.
  100.  *
  101.  *  - Control + Y
  102.  *
  103.  *    Undoes previous editing operation.
  104.  *
  105.  *  - Cursor up
  106.  *
  107.  *    Recalls previous history line.
  108.  *
  109.  *  - Shift + Cursor up
  110.  *
  111.  *    Recalls first history line.
  112.  *
  113.  *  - Cursor down
  114.  *
  115.  *    Moves to next history line.
  116.  *
  117.  *  - Shift + Cursor down
  118.  *
  119.  *    Moves to last history line.
  120.  *
  121.  *  - Cursor right
  122.  *
  123.  *    Moves the cursor to the right.
  124.  *
  125.  *  - Shift + Cursor right
  126.  *
  127.  *    Moves the cursor to the beginning of the next word to the right.
  128.  *
  129.  *  - Cursor left
  130.  *
  131.  *    Moves the cursor to the left.
  132.  *
  133.  *  - Shift + Cursor left
  134.  *
  135.  *    Moves the cursor to the beginning of the previous word to the left.
  136.  *
  137.  *  - Help
  138.  *
  139.  *    Starts  function key assignment.  Press the function key you wish to
  140.  *    assign  text  to, then enter the text you wish to use.  The vertical
  141.  *    bar  (|) and exclamation mark (!) serve as line terminators and will
  142.  *    produce a carriage-return when the key assigment is recalled.  Note:
  143.  *    any  text following the vertical bar or the exclamation mark will be
  144.  *    quietly discarded!
  145.  *
  146.  *  - F1-F10, Shift + F1-F10
  147.  *
  148.  *    Recalls function key assignment.
  149.  *
  150.  *  - Numeric keypad
  151.  *
  152.  *    Produces movement commands.
  153.  *
  154.  *  As  for  tool  and  project  icons the following tool type entries are
  155.  *  supported.   Note  that due to a bug in icon.library v1.2 and v1.3 the
  156.  *  single line tool types such as "CUSTOMSCREEN" will have to be followed
  157.  *  by  a  `='  character (e.g.  "CUSTOMSCREEN="  with  no   corresponding
  158.  *  argument).
  159.  *
  160.  *  - FILETYPE
  161.  *
  162.  *    This  is  where  you  or  the  interpreter  places  the  type of the
  163.  *    corresponding   file.    For   saved   game   files   this  will  be
  164.  *    "FILETYPE=BOOKMARK|ITF",  for  story  files "FILETYPE=STORY" and for
  165.  *    transcript files "FILETYPE=TEXT|ASCII".
  166.  *
  167.  *  - CUSTOMSCREEN
  168.  *
  169.  *    Corresponds to the "-C" command-line option, i.e.  the output window
  170.  *    will  be  opened  on  a  custom  screen rather than on the Workbench
  171.  *    screen.   The screen will inherit attributes such as depth, colours,
  172.  *    size   and  display  mode  from  the  Workbench  screen.   The  only
  173.  *    difference  is  the handling of A2024 screen modes, which will cause
  174.  *    the screen to open in hires-interlaced display mode.
  175.  *       If  running  under operating system revisions previous to v2.04 a
  176.  *    monochrome display with the background and text colours set to black
  177.  *    and white will be opened.
  178.  *
  179.  *  - FILL
  180.  *
  181.  *    Corresponds  to  the  "-D"  option, i.e.  text printed in the window
  182.  *    will be flush-filled to fill the entire line.  This text for example
  183.  *    has  been flush-filled.  As formatting takes time, you should enable
  184.  *    this switch only if your machine runs fast enough to handle it.
  185.  *
  186.  *  - TEXTFONT
  187.  *
  188.  *    Corresponds  to the "-F" option, i.e.  determines the text rendering
  189.  *    font  to be used.  This will be a proportional-spaced font.  If this
  190.  *    option is specified "LISTFONT" and "FONTSIZE" have to be included as
  191.  *    well.  To use the Adobe Times font, use "TEXTFONT=Times".
  192.  *
  193.  *  - LISTFONT
  194.  *
  195.  *    Corresponds  to the "-L" option, i.e.  determines the list and table
  196.  *    rendering  font  to  be  used.  This will be a fixed-width font.  If
  197.  *    this  option  is  specified  "TEXTFONT"  and  "FONTSIZE"  have to be
  198.  *    included   as   well.    To   use   the   Adobe  Courier  font,  use
  199.  *    "LISTFONT=Courier".
  200.  *
  201.  *  - FONTSIZE
  202.  *
  203.  *    Corresponds to the "-S" option, i.e.  the point size of the text and
  204.  *    list fonts specified using the "TEXTFONT" and "LISTFONT" tool types.
  205.  *    To use point size 11, use "FONTSIZE=11".
  206.  *
  207.  *  - STORY
  208.  *
  209.  *    This  tool  type  entry  determines  the  story  file  to  be  used.
  210.  *    Typically, it is saved in the project icon of a saved game file.  In
  211.  *    order  to  use  "Work:Infocom/ZorkIII/Story.Data"  as  a story file,
  212.  *    enter the following text:  "STORY=Work:Infocom/ZorkIII/Story.Data".
  213.  *
  214.  *  - ATTRIBUTEASSIGNMENTS
  215.  *
  216.  *    Corresponds to the "-a" command-line option.
  217.  *
  218.  *  - ATTRIBUTETESTS
  219.  *
  220.  *    Corresponds to the "-A" command-line option.
  221.  *
  222.  *  - CONTEXT
  223.  *
  224.  *    Corresponds  to  the  "-c" command-line option.  In order to use two
  225.  *    lines of inter-page context, use "CONTEXT=2".
  226.  *
  227.  *  - ECHO
  228.  *
  229.  *    Corresponds to the "-e" command-line option.
  230.  *
  231.  *  - INDENT
  232.  *
  233.  *    Corresponds  to  the  "-i" command-line option.  In order to use two
  234.  *    characters of line indent, use "INDENT=2".
  235.  *
  236.  *  - MARGIN
  237.  *
  238.  *    Corresponds  to  the  "-m" command-line option.  In order to use two
  239.  *    characters as a line margin, use "MARGIN=2".
  240.  *
  241.  *  - NOPAGER
  242.  *
  243.  *    Corresponds to the "-p" command-line option.
  244.  *
  245.  *  - PROMPT
  246.  *
  247.  *    Corresponds to the "-P" command-line option.
  248.  *
  249.  *  - NOSTATUS
  250.  *
  251.  *    Corresponds to the "-s" command-line option.
  252.  *
  253.  *  - TRANSFERS
  254.  *
  255.  *    Corresponds to the "-t" command-line option.
  256.  *
  257.  *  - TANDY
  258.  *
  259.  *    Corresponds to the "-T" command-line option.
  260.  *
  261.  *  This   interpreter   supports  proportional  fonts:   by  default  the
  262.  *  Workbench  screen  font  will  be  used  for text display (this can be
  263.  *  overridden  using  the  "TEXTFONT",  "LISTFONT"  and  "FONTSIZE"  tool
  264.  *  types).  If the Workbench screen font and the system font do not match
  265.  *  in  height the system font will be used for text display.  This is due
  266.  *  to  the  fact  that  the  interpreter  contains conditional code which
  267.  *  changes  the type of the font during the game if tables or maps are to
  268.  *  be displayed.
  269.  *
  270.  *  If  you  want the interpreter to save icons with saved game files make
  271.  *  sure  that  the icon file "Icon.Data" is present in the directory from
  272.  *  which  the  interpreter was loaded or saved game files will be created
  273.  *  without getting icons attached.
  274.  *     The  interpreter  recognizes  saved  game  files  by their filetype
  275.  *  entries,  i.e.   the  tooltype  "FILETYPE=BOOKMARK" has to be present.
  276.  *  Function  key  assignments,  the name of the story file being used and
  277.  *  game  options  are  saved along with the game file icon.  Function key
  278.  *  assignments  are  restored  automatically  when  a  saved game file is
  279.  *  loaded.   Story  file  name  and  options  are  considered only if the
  280.  *  interpreter is invoked by double-clicking on a project icon.
  281.  *
  282.  *
  283.  *  The  following  list  of  features is valid only for Kickstart 2.04 or
  284.  *  higher.   Users  whose  machines run Kickstart 1.2 or 1.3 will have to
  285.  *  get along with a slightly simplified interface.
  286.  *
  287.  *  - Several  options  can be changed and commands recalled via pull-down
  288.  *    menus.   Game  files  can be restored by dropping their icons on the
  289.  *    interpreter window.
  290.  *
  291.  *  - If  run  from  Workbench  with no story file available the interface
  292.  *    will  check  the  "Infocom:" assignment or volume if present.  If it
  293.  *    cannot  be  found a file requester will allow you to select the game
  294.  *    file to use.  If present the "Infocom:" volume or assignment will be
  295.  *    scanned for valid type 3 Infocom game files.  If more than one valid
  296.  *    game file is found a list will be displayed to choose from.
  297.  *
  298.  *  - The  interface  also  supports  multi-volume assignments, so you can
  299.  *    assign  "Infocom:" to multiple directories the interface is to scan.
  300.  *    One  example  how  to use it would be to copy the "Lost Treasures of
  301.  *    Infocom"  to your hard disk and then use the "Assign Infocom:  <Game
  302.  *    directory> Add" command for each game file directory.
  303.  *
  304.  *
  305.  *  Some things which you might want to know about:
  306.  *
  307.  *  - Clipboard  support  has been implemented in so far as it is possible
  308.  *    to  paste  the  contents of the clipboard, but there is no option to
  309.  *    copy  the screen text to the clipboard.  This may follow in a future
  310.  *    release  version  since  it  requires  a  good  lot  of work.  Paste
  311.  *    operations  are  limited  to  a single line of input, any additional
  312.  *    text  is  discarded.   Line  feeds  are automatically converted into
  313.  *    carriage  returns.   Any  non-printable  characters are filtered out
  314.  *    while reading.
  315.  *
  316.  *  - As of this writing, the interface ignores any page length settings.
  317.  *
  318.  *  - If  a  fixed  text window is displayed (such as by `Seastalker') the
  319.  *    status line will be enabled by default.  If the fixed text window is
  320.  *    disabled  again the interface will pay attention to the user-defined
  321.  *    settings.
  322.  *
  323.  *  - Due   to  the  current  implementation  of  pull-down-menu  support,
  324.  *    drag-selection and multiple-selection are not supported.
  325.  *
  326.  *  Please  refer to the `COPYING' file for distribution conditions and to
  327.  *  the `pinfo.txt' file for a general list of  features and  command-line
  328.  *  options.
  329.  *
  330.  *
  331.  *  In  order  to  compile  this program an ANSI compliant `C' compiler is
  332.  *  required.   Except for the old v5.x/v4.x Lattice/SAS `C' compilers any
  333.  *  other Amiga compiler should do.
  334.  *
  335.  *  May the source be with you,
  336.  *                              -olsen
  337.  */
  338.  
  339. #ifndef _AMIGA_GLOBAL_H
  340. #include "amiga_global.h"
  341. #endif    /* !_AMIGA_GLOBAL_H */
  342.  
  343.     /* Disable ^C trapping for several Amiga `C' compilers. */
  344.  
  345. #ifdef LATTICE
  346.  
  347.     /* The old Lattice/SAS `C' compiler runtime library does not
  348.      * contain the strerror() routine (it's in the ANSI specs,
  349.      * but not in the library...), so we'll have to fake it.
  350.      */
  351.  
  352. #ifndef __SASC_60
  353.  
  354. char *strerror(int code) { return("Unknown error code"); }
  355.  
  356. ULONG CXBRK(VOID) { return(0); }
  357.  
  358. #else
  359.  
  360. VOID Chk_Abort(VOID) {}
  361. VOID _CXBRK(VOID) {}
  362.  
  363. #endif    /* !__SASC_60 */
  364.  
  365. #endif    /* LATTICE */
  366.  
  367. #ifdef AZTEC_C
  368.  
  369. LONG Chk_Abort(VOID) { return(0); }
  370. VOID _wb_parse(VOID) {}
  371.  
  372. #endif    /* AZTEC_C */
  373.  
  374. /*
  375.  * Global Variables
  376.  */
  377.  
  378. /*
  379.  * Variable:    scr_usage
  380.  *
  381.  * Description:
  382.  *      This variable should contain a usage string for any extra
  383.  *      command-line options available through this terminal
  384.  *      interface.
  385.  */
  386.  
  387. const char *scr_usage       = "[-C] [-D] [-L list font name] [-F text font name] [-S font point size]";
  388.  
  389. /*
  390.  * Variable:    scr_long_usage
  391.  *
  392.  * Description:
  393.  *      This variable should contain a more verbose usage string
  394.  *      detailing the command-line options available through this
  395.  *      terminal interface, one option per line.
  396.  */
  397.  
  398. const char *scr_long_usage  = "\t-C\topen custom screen\n\t-D\tflush-fill text lines\n\t-L name\tset name of list font\n\t-F name\tset name of text font\n\t-S #\tset font point size\n";
  399.  
  400. /*
  401.  * Variable:    scr_opt_list
  402.  *
  403.  * Description:
  404.  *      This variable should contain a getopt(3)-style option list for
  405.  *      any command-line options available through this terminal
  406.  *      interface.
  407.  */
  408.  
  409. const char *scr_opt_list    = "CDF:L:S:";
  410.  
  411. /*
  412.  * Function:    scr_cmdarg()
  413.  *
  414.  * Arguments:
  415.  *      argc        number of original arguments
  416.  *      argvp       pointer to array of strings containing args
  417.  *
  418.  * Returns:
  419.  *      Number of new arguments.
  420.  *
  421.  * Description:
  422.  *      This function is called before any command line parsing is
  423.  *      done.  Any terminal interface-specific arguments should be
  424.  *      pulled out of the argv list and any extra arguments obtained
  425.  *      from resource files or wherever should be added.  Note that
  426.  *      (*argvp)[0] must be the command name and (*argvp)[argc] must
  427.  *      be a null pointer.
  428.  *
  429.  * Notes:
  430.  */
  431.  
  432. int
  433. scr_cmdarg(int argc, char ***argvp)
  434. {
  435.         /* Obtain current process pointer. */
  436.  
  437.     ThisProcess = (struct Process *)FindTask(NULL);
  438.  
  439.         /* Are we running as a child of Workbench? */
  440.  
  441.     if(!argc)
  442.     {
  443.         STATIC char    *DummyInput[19];
  444.  
  445.         char         ProjectName[MAX_FILENAME_LENGTH],
  446.                  StoryName[MAX_FILENAME_LENGTH];
  447.         int         Count = 0;
  448.  
  449.             /* Clear the names. */
  450.  
  451.         ProjectName[0] = StoryName[0] = 0;
  452.  
  453.             /* Obtain Workbench startup message. */
  454.  
  455.         WBenchMsg = (struct WBStartup *)*argvp;
  456.  
  457.             /* Install new input data. */
  458.  
  459.         *argvp = (char **)DummyInput;
  460.  
  461.             /* Fill in the program name. */
  462.  
  463.         DummyInput[Count++] = WBenchMsg -> sm_ArgList[0] . wa_Name;
  464.  
  465.             /* Open system libraries, we will
  466.              * need the icon.library routines.
  467.              */
  468.  
  469.         if(ConOpenLibs())
  470.         {
  471.                 /* Did we succeed in opening icon.library? */
  472.  
  473.             if(IconBase)
  474.             {
  475.                 LONG i;
  476.  
  477.                     /* Run down the list of arguments... */
  478.  
  479.                 for(i = 0 ; Count < 16 && i < WBenchMsg -> sm_NumArgs ; i++)
  480.                 {
  481.                         /* A correct project icon always has a
  482.                          * directory lock associated, let's check it.
  483.                          */
  484.  
  485.                     if(WBenchMsg -> sm_ArgList[i] . wa_Lock && WBenchMsg -> sm_ArgList[i] . wa_Name)
  486.                     {
  487.                         struct DiskObject *Icon;
  488.  
  489.                             /* Skip to the icon location. */
  490.  
  491.                         CurrentDir(WBenchMsg -> sm_ArgList[i] . wa_Lock);
  492.  
  493.                             /* Try to read the project icon. */
  494.  
  495.                         if(Icon = GetDiskObject(WBenchMsg -> sm_ArgList[i] . wa_Name))
  496.                         {
  497.                                 /* Is it a project icon or even the
  498.                                  * program icon itself?
  499.                                  */
  500.  
  501.                             if(Icon -> do_Type == WBPROJECT || (!i && Icon -> do_Type == WBTOOL))
  502.                             {
  503.                                 STRPTR Type;
  504.  
  505.                                     /* Find the file type if any. */
  506.  
  507.                                 if(Type = FindToolType((STRPTR *)Icon -> do_ToolTypes,"FILETYPE"))
  508.                                 {
  509.                                         /* Is it a bookmark file? */
  510.  
  511.                                     if(MatchToolValue(Type,"BOOKMARK") && MatchToolValue(Type,"ITF"))
  512.                                         strcpy(ProjectName,WBenchMsg -> sm_ArgList[i] . wa_Name);
  513.  
  514.                                         /* Is it a story file? */
  515.  
  516.                                     if(MatchToolValue(Type,"STORY"))
  517.                                         strcpy(StoryName,WBenchMsg -> sm_ArgList[i] . wa_Name);
  518.                                 }
  519.  
  520.                                     /* Are we to use a special text rendering font? */
  521.  
  522.                                 if(Type = FindToolType((STRPTR *)Icon -> do_ToolTypes,"TEXTFONT"))
  523.                                     strcpy(TextFontName,Type);
  524.  
  525.                                     /* Are we to use a special list text rendering font? */
  526.  
  527.                                 if(Type = FindToolType((STRPTR *)Icon -> do_ToolTypes,"LISTFONT"))
  528.                                     strcpy(ListFontName,Type);
  529.  
  530.                                     /* Which font size are we to use? */
  531.  
  532.                                 if(Type = FindToolType((STRPTR *)Icon -> do_ToolTypes,"FONTSIZE"))
  533.                                     FontSize = atoi(Type);
  534.  
  535.                                     /* Are we to use a special story file? */
  536.  
  537.                                 if(Type = FindToolType((STRPTR *)Icon -> do_ToolTypes,"STORY"))
  538.                                     strcpy(StoryName,Type);
  539.  
  540.                                     /* Are we to open a custom screen? */
  541.  
  542.                                 if(FindToolType((STRPTR *)Icon -> do_ToolTypes,"CUSTOMSCREEN"))
  543.                                     UseCustomScreen = TRUE;
  544.  
  545.                                     /* Are we to flush-fill text lines? */
  546.  
  547.                                 if(FindToolType((STRPTR *)Icon -> do_ToolTypes,"FILL"))
  548.                                     FillLines = TRUE;
  549.  
  550.                                     /* Are we to print object attribute assignments while playing? */
  551.  
  552.                                 if(FindToolType((STRPTR *)Icon -> do_ToolTypes,"ATTRIBUTEASSIGNMENTS"))
  553.                                     DummyInput[Count++] = "-a";
  554.  
  555.                                     /* Are we to print object attribute tests while playing? */
  556.  
  557.                                 if(FindToolType((STRPTR *)Icon -> do_ToolTypes,"ATTRIBUTETESTS"))
  558.                                     DummyInput[Count++] = "-A";
  559.  
  560.                                     /* Are we to set the page context? */
  561.  
  562.                                 if(Type = FindToolType((STRPTR *)Icon -> do_ToolTypes,"CONTEXT"))
  563.                                 {
  564.                                     DummyInput[Count++] = "-c";
  565.  
  566.                                     if(DummyInput[Count] = (STRPTR)malloc(strlen(Type) + 1))
  567.                                         strcpy(DummyInput[Count++],Type);
  568.                                     else
  569.                                         Count--;
  570.                                 }
  571.  
  572.                                     /* Are we to set the line indent? */
  573.  
  574.                                 if(Type = FindToolType((STRPTR *)Icon -> do_ToolTypes,"INDENT"))
  575.                                 {
  576.                                     DummyInput[Count++] = "-i";
  577.  
  578.                                     if(DummyInput[Count] = (STRPTR)malloc(strlen(Type) + 1))
  579.                                         strcpy(DummyInput[Count++],Type);
  580.                                     else
  581.                                         Count--;
  582.                                 }
  583.  
  584.                                     /* Are we to set the line margin? */
  585.  
  586.                                 if(Type = FindToolType((STRPTR *)Icon -> do_ToolTypes,"MARGIN"))
  587.                                 {
  588.                                     DummyInput[Count++] = "-m";
  589.  
  590.                                     if(DummyInput[Count] = (STRPTR)malloc(strlen(Type) + 1))
  591.                                         strcpy(DummyInput[Count++],Type);
  592.                                     else
  593.                                         Count--;
  594.                                 }
  595.  
  596.                                     /* Are we to echo line input? */
  597.  
  598.                                 if(FindToolType((STRPTR *)Icon -> do_ToolTypes,"ECHO"))
  599.                                     DummyInput[Count++] = "-e";
  600.  
  601.                                     /* Are we to disable text paging? */
  602.  
  603.                                 if(FindToolType((STRPTR *)Icon -> do_ToolTypes,"NOPAGER"))
  604.                                     DummyInput[Count++] = "-p";
  605.  
  606.                                     /* Are we to display the alternate prompt, if any? */
  607.  
  608.                                 if(FindToolType((STRPTR *)Icon -> do_ToolTypes,"PROMPT"))
  609.                                     DummyInput[Count++] = "-P";
  610.  
  611.                                     /* Are we to disable the status line? */
  612.  
  613.                                 if(FindToolType((STRPTR *)Icon -> do_ToolTypes,"NOSTATUS"))
  614.                                     DummyInput[Count++] = "-s";
  615.  
  616.                                     /* Are we to display object transfers? */
  617.  
  618.                                 if(FindToolType((STRPTR *)Icon -> do_ToolTypes,"TRANSFERS"))
  619.                                     DummyInput[Count++] = "-t";
  620.  
  621.                                     /* Are we to enable the Tandy mode? */
  622.  
  623.                                 if(FindToolType((STRPTR *)Icon -> do_ToolTypes,"TANDY"))
  624.                                     DummyInput[Count++] = "-T";
  625.                             }
  626.  
  627.                                 /* Free the icon data. */
  628.  
  629.                             FreeDiskObject(Icon);
  630.                         }
  631.                     }
  632.                 }
  633.             }
  634.         }
  635.  
  636.             /* Did we get a project file name? */
  637.  
  638.         if(ProjectName[0])
  639.         {
  640.                 /* Supply restore command. */
  641.  
  642.             DummyInput[Count++] = "-r";
  643.  
  644.                 /* Add the name of the file to
  645.                  * be restored.
  646.                  */
  647.  
  648.             if(DummyInput[Count] = (STRPTR)malloc(strlen(ProjectName) + 1))
  649.                 strcpy(DummyInput[Count++],ProjectName);
  650.             else
  651.                 Count--;
  652.         }
  653.  
  654.             /* Have another try opening the system libraries. */
  655.  
  656.         if(ConOpenLibs())
  657.         {
  658.                 /* No custom story file support. */
  659.  
  660.             if(NewOS)
  661.             {
  662.                 char *Buffer;
  663.  
  664.                     /* Did we get a story file name? */
  665.  
  666.                 if(StoryName[0])
  667.                 {
  668.                         /* Is it a valid story file? */
  669.  
  670.                     if(!ConCheckStory(StoryName))
  671.                     {
  672.                             /* Can we locate any story file? */
  673.  
  674.                         if(Buffer = ConLocateStory("",StoryName))
  675.                             strcpy(StoryName,Buffer);
  676.                         else
  677.                         {
  678.                                 /* Prompt the user to select a new one. */
  679.  
  680.                             if(!GameSelect(StoryName))
  681.                                 StoryName[0] = 0;
  682.                         }
  683.                     }
  684.                 }
  685.                 else
  686.                 {
  687.                         /* Can we locate any story file? */
  688.  
  689.                     if(Buffer = ConLocateStory("",""))
  690.                         strcpy(StoryName,Buffer);
  691.                     else
  692.                     {
  693.                             /* Obviously not, so prompt
  694.                              * the user to select a new one.
  695.                              */
  696.  
  697.                         if(!GameSelect(StoryName))
  698.                             StoryName[0] = 0;
  699.                     }
  700.                 }
  701.             }
  702.         }
  703.  
  704.             /* Did we get a story file name? */
  705.  
  706.         if(StoryName[0])
  707.         {
  708.                 /* Add the name of the story
  709.                  * file to be used.
  710.                  */
  711.  
  712.             if(DummyInput[Count] = (STRPTR)malloc(strlen(StoryName) + 1))
  713.                 strcpy(DummyInput[Count++],StoryName);
  714.         }
  715.  
  716.             /* Return new number of arguments. */
  717.  
  718.         return(Count);
  719.     }
  720.     else
  721.         return(argc);
  722. }
  723.  
  724. /*
  725.  * Function:    scr_getopt()
  726.  *
  727.  * Arguments:
  728.  *      c           option found
  729.  *      arg         option argument (if requested)
  730.  *
  731.  * Description:
  732.  *      This function is called whenever a command-line option
  733.  *      specified in scr_opt_list (above) is found on the command
  734.  *      line.
  735.  */
  736.  
  737. void
  738. scr_getopt(int c,const char *arg)
  739. {
  740.         /* Are we to open a custom screen? */
  741.  
  742.     if(c == 'C')
  743.         UseCustomScreen = TRUE;
  744.  
  745.         /* Are we to flush-fill text lines? */
  746.  
  747.     if(c == 'D')
  748.         FillLines = TRUE;
  749.  
  750.         /* Are we to use a special list font? */
  751.  
  752.     if(c == 'L')
  753.         strcpy(ListFontName,arg);
  754.  
  755.         /* Are we to use a special text font? */
  756.  
  757.     if(c == 'F')
  758.         strcpy(TextFontName,arg);
  759.  
  760.         /* Are we to use a special font size? */
  761.  
  762.     if(c == 'S')
  763.         FontSize = atoi(arg);
  764. }
  765.  
  766. /*
  767.  * Function:    scr_setup()
  768.  *
  769.  * Arguments:
  770.  *      margin      # of spaces in the right margin.
  771.  *      indent      # of spaces in the left margin.
  772.  *      scr_sz      # of lines on the screen.
  773.  *      context     # of lines of context to keep when scrolling
  774.  *
  775.  * Description:
  776.  *      This function should set up generic items in the screen
  777.  *      interface that may need to be done before *any* output is
  778.  *      done.
  779.  *
  780.  *      If SCR_SZ is not 0, then this function must use SCR_SZ as the
  781.  *      number of lines the screen can hold at once, no matter what it
  782.  *      may infer otherwise.  If SCR_SZ is 0, then the function must
  783.  *      figure the size of the screen as best it can.
  784.  *
  785.  * Notes:
  786.  *      Any terminal initialization needed only for actually playing
  787.  *      the game should go in scr_begin(), not here.
  788.  */
  789.  
  790. int
  791. scr_setup(int margin,int indent,int scr_sz,int context)
  792. {
  793.     int Columns = 75;
  794.  
  795.         /* Remember the config data. */
  796.  
  797.     ConLineMargin    = margin;
  798.     ConLineIndent    = indent;
  799.     ConLineContext    = context;
  800.  
  801.         /* Return number of on-screen columns. */
  802.  
  803.     if(!WBenchMsg && SysBase -> LibNode . lib_Version >= 37)
  804.     {
  805.         struct InfoData *InfoData;
  806.  
  807.         if(InfoData = (struct InfoData *)AllocVec(sizeof(struct InfoData),MEMF_ANY))
  808.         {
  809.             if(DoPkt1(ThisProcess -> pr_ConsoleTask,ACTION_DISK_INFO,MKBADDR(InfoData)))
  810.             {
  811.                 struct ConUnit *ConUnit = (struct ConUnit *)((struct IOStdReq *)InfoData -> id_InUse) -> io_Unit;
  812.  
  813.                 Columns = ConUnit -> cu_XMax;
  814.             }
  815.  
  816.             FreeVec(InfoData);
  817.         }
  818.     }
  819.  
  820.         /* Return the number of columns. */
  821.  
  822.     return(Columns);
  823. }
  824.  
  825. /*
  826.  * Function:    scr_shutdown()
  827.  *
  828.  * Description:
  829.  *      This function will be called just before we exit.
  830.  */
  831.  
  832. void
  833. scr_shutdown()
  834. {
  835.     /* Nothing happens here. */
  836. }
  837.  
  838. /*
  839.  * Function:    scr_begin()
  840.  *
  841.  * Arguments:
  842.  *      game    The game datafile we're about to execute.
  843.  *
  844.  * Description:
  845.  *      This function should perform terminal initializations we need
  846.  *      to actually play the game.
  847.  */
  848.  
  849. void
  850. scr_begin()
  851. {
  852.         /* Set up the console or fail. */
  853.  
  854.     if(ConSetup())
  855.     {
  856.         char    *Buffer;
  857.         int     Len = strlen(gflags . filenm);
  858.  
  859.             /* Block GCC signal handling. */
  860.  
  861. #ifdef __GNUC__
  862.  
  863.         const sigset_t trapped = TRAPPED_SIGNALS;
  864.  
  865.         if(sigprocmask(SIG_BLOCK,&trapped,NULL))
  866.             exit(RETURN_FAIL);
  867.  
  868. #endif    /* __GNUC__ */
  869.  
  870.             /* Determine number of lines on the screen. */
  871.  
  872.         ConNumLines = (Window -> Height - (WindowBorderTop + WindowBorderBottom)) / TextFontHeight;
  873.  
  874.             /* Jump to the end of the screen. */
  875.  
  876.         ConSet(0,(ConNumLines - 1) * TextFontHeight,-1);
  877.  
  878.             /* Clear the status line if any. */
  879.  
  880.         if(gflags . pr_status)
  881.             ConPrintStatus("","");
  882.  
  883.             /* Try to get the story name in case we
  884.              * might need it later.
  885.              */
  886.  
  887.         if(NewOS)
  888.         {
  889.                 /* Is this just the bare game file name
  890.                  * without any path part attached?
  891.                  */
  892.  
  893.             if(FilePart((STRPTR)gflags . filenm) == (STRPTR)gflags . filenm)
  894.             {
  895.                     /* Allocate space for full path. */
  896.  
  897.                 if(StoryName = malloc(Len + MAX_FILENAME_LENGTH))
  898.                 {
  899.                         /* Obtain the current directory name. */
  900.  
  901.                     if(GetCurrentDirName(StoryName,Len + MAX_FILENAME_LENGTH))
  902.                     {
  903.                             /* Build the full path name. */
  904.  
  905.                         if(!AddPart(StoryName,(STRPTR)gflags . filenm,Len + MAX_FILENAME_LENGTH))
  906.                             StoryName = "Story.Data";
  907.                     }
  908.                     else
  909.                         StoryName = "Story.Data";
  910.                 }
  911.                 else
  912.                     StoryName = "Story.Data";
  913.             }
  914.             else
  915.             {
  916.                     /* Remember the name. */
  917.  
  918.                 if(StoryName = malloc(Len + 1))
  919.                     strcpy(StoryName,gflags . filenm);
  920.                 else
  921.                     StoryName = "Story.Data";
  922.             }
  923.         }
  924.         else
  925.         {
  926.                 /* Remember the name. */
  927.  
  928.             if(StoryName = malloc(Len + 1))
  929.                 strcpy(StoryName,gflags . filenm);
  930.             else
  931.                 StoryName = "Story.Data";
  932.         }
  933.  
  934.             /* Determine story file serial number and release. */
  935.  
  936.         if(NewOS)
  937.         {
  938.             if(Buffer = ConLocateStory("",StoryName))
  939.                 ConQueryStoryInformation(Buffer);
  940.         }
  941.  
  942.             /* Make a copy of the game name. */
  943.  
  944.         if(SoundName = malloc(Len + AMIGADOS_NAME_LIMIT))
  945.         {
  946.             strcpy(SoundName,gflags . filenm);
  947.  
  948.                 /* Does the sound file name have any
  949.                  * length, i.e. is it a real name?
  950.                  */
  951.  
  952.             if(Len)
  953.             {
  954.                 int i;
  955.  
  956.                     /* Starting from the end of the
  957.                      * file name look for the first
  958.                      * path character.
  959.                      */
  960.  
  961.                 for(i = Len - 1 ; i >= 0 ; i--)
  962.                 {
  963.                         /* Is it a path name seperation
  964.                          * character?
  965.                          */
  966.  
  967.                     if(SoundName[i] == '/' || SoundName[i] == ':')
  968.                     {
  969.                             /* Append the sound directory
  970.                              * name to the string.
  971.                              */
  972.  
  973.                         SoundPath = &SoundName[i + 1];
  974.  
  975.                             /* We're finished. */
  976.  
  977.                         break;
  978.                     }
  979.                 }
  980.             }
  981.  
  982.                 /* If no proper subdirectory name was
  983.                  * to be found, override the entire
  984.                  * string.
  985.                  */
  986.  
  987.             if(!SoundPath)
  988.                 SoundPath = SoundName;
  989.         }
  990.  
  991.             /* Update the menus. */
  992.  
  993.         if(NewOS)
  994.             ConUpdateMenus();
  995.  
  996.             /* Activate the window and bring the screen to the front. */
  997.  
  998.         if(Window)
  999.         {
  1000.             ActivateWindow(Window);
  1001.  
  1002.             ScreenToFront(Window -> WScreen);
  1003.         }
  1004.  
  1005.             /* This interface supports a multiline status window. */
  1006.  
  1007.         F1_SETB(B_STATUS_WIN);
  1008.     }
  1009.     else
  1010.         exit(RETURN_FAIL);
  1011. }
  1012.  
  1013. /*
  1014.  * Function:    scr_end()
  1015.  *
  1016.  * Description:
  1017.  *      This function will be called after the last line is printed
  1018.  *      but before we exit, *only* if scr_begin() was called (*not* if
  1019.  *      just scr_startup() was called!)
  1020.  */
  1021.  
  1022. void
  1023. scr_end()
  1024. {
  1025.         /* Is the console available? */
  1026.  
  1027.     if(Window)
  1028.     {
  1029.             /* Scroll the screen contents up. */
  1030.  
  1031.         ConScrollUp();
  1032.  
  1033.             /* Set special colour. */
  1034.  
  1035.         ConSetColour(COLOUR_SPECIAL);
  1036.  
  1037.             /* Set the proportional font. */
  1038.  
  1039.         ConSetFont(FONT_PROP);
  1040.  
  1041.             /* Block the menu strip. */
  1042.  
  1043.         Window -> Flags |= WFLG_RMBTRAP;
  1044.  
  1045.             /* Say goodbye... */
  1046.  
  1047.         ConPrintf("Press any key to exit.");
  1048.  
  1049.             /* Turn on the cursor. */
  1050.  
  1051.         ConCursorOn(CURSOR_AVERAGE);
  1052.  
  1053.             /* Wait for key to be pressed. */
  1054.  
  1055.         ConGetChar(TRUE);
  1056.     }
  1057.  
  1058.         /* If the script file is still open (although it shouldn't)
  1059.          * close it.
  1060.          */
  1061.  
  1062.     if(ScriptFile)
  1063.         scr_close_sf(ScriptFileName,ScriptFile,SF_SCRIPT);
  1064.  
  1065.         /* Enable GCC signal handling again. */
  1066.  
  1067. #ifdef __GNUC__
  1068.  
  1069.     {
  1070.         const sigset_t trapped = TRAPPED_SIGNALS;
  1071.  
  1072.         sigprocmask(SIG_UNBLOCK,&trapped,NULL);
  1073.     }
  1074.  
  1075. #endif    /* __GNUC__ */
  1076. }
  1077.  
  1078. /*
  1079.  * Function:    scr_putline()
  1080.  *
  1081.  * Arguments:
  1082.  *      buffer          Line to be printed.
  1083.  *
  1084.  * Description:
  1085.  *      This function is passed a nul-terminated string and it should
  1086.  *      display the string on the terminal.  It will *not* contain a
  1087.  *      newline character.
  1088.  *
  1089.  *      This function should perform whatever wrapping, paging, etc.
  1090.  *      is necessary, print the string, and generate a final linefeed.
  1091.  *
  1092.  *      If the TI supports proportional-width fonts,
  1093.  *      F2_IS_SET(B_FIXED_FONT) should be checked as appropriate.
  1094.  *
  1095.  *      If the TI supports scripting, F2_IS_SET(B_SCRIPTING) should be
  1096.  *      checked as appropriate.
  1097.  */
  1098.  
  1099. void
  1100. scr_putline(const char *buffer)
  1101. {
  1102.     int MaxLen;
  1103.  
  1104.         /* Determine length of text line. */
  1105.  
  1106.     MaxLen = strlen(buffer);
  1107.  
  1108.         /* Check for scripting. */
  1109.  
  1110.     if(F2_IS_SET(B_SCRIPTING))
  1111.     {
  1112.             /* Is this just a blank line? */
  1113.  
  1114.         if(MaxLen)
  1115.             ScriptSplitLine((char *)buffer,MaxLen,FALSE);
  1116.         else
  1117.             ScriptWrite("",0);
  1118.     }
  1119.  
  1120.         /* Is this just a blank line? */
  1121.  
  1122.     if(MaxLen)
  1123.     {
  1124.             /* Are we to change the text rendering font?
  1125.              * The interpreter may want to change between
  1126.              * a fixed and a proportional-spaced font.
  1127.              */
  1128.  
  1129.         if(F2_IS_SET(B_FIXED_FONT))
  1130.             ConSetFont(FONT_FIXED);
  1131.         else
  1132.             ConSetFont(FONT_PROP);
  1133.  
  1134.             /* Chop the line into pieces and
  1135.              * print it.
  1136.              */
  1137.  
  1138.         ConSplitLine((char *)buffer,MaxLen,FALSE);
  1139.     }
  1140.     else
  1141.         ConPrintLine("",0,0,FALSE);
  1142. }
  1143.  
  1144. /*
  1145.  * Function:    scr_putscore()
  1146.  *
  1147.  * Description:
  1148.  *      This function prints the ti_location and ti_status strings
  1149.  *      if it can and if status line printing is enabled.
  1150.  */
  1151.  
  1152. void
  1153. scr_putscore()
  1154. {
  1155.         /* Are we to print the status line? */
  1156.  
  1157.     if(gflags . pr_status)
  1158.     {
  1159.         IMPORT char    *ti_location,
  1160.                 *ti_status;
  1161.  
  1162.             /* Print it. */
  1163.  
  1164.         if(ti_location && ti_status)
  1165.             ConPrintStatus(ti_location,ti_status);
  1166.     }
  1167. }
  1168.  
  1169. /*
  1170.  * Function:    scr_putsound()
  1171.  *
  1172.  * Arguments:
  1173.  *      number      sound number to play
  1174.  *      action      action to perform
  1175.  *      volume      volume to play sound at
  1176.  *      argc        number of valid arguments
  1177.  *
  1178.  * Description:
  1179.  *      This function plays the sound specified if it can; if not it
  1180.  *      prints a line to that effect.
  1181.  *
  1182.  *      If the `argc' value is 1, then the we play `number' of beeps
  1183.  *      (usually the ^G character).
  1184.  *
  1185.  *      If `argc' >1, the `action' argument is used as follows:
  1186.  *
  1187.  *          2:  play sound file
  1188.  *          3:  stop playing sound file
  1189.  *          4:  free sound resources
  1190.  *
  1191.  *      If `argc' >2, the `volume' argument is between 1 and 8 and is
  1192.  *      a volume to play the sound at.
  1193.  */
  1194.  
  1195. void
  1196. scr_putsound(int number,int action,int volume,int argc)
  1197. {
  1198.         /* Single argument? Just beep. */
  1199.  
  1200.     if(argc == 1)
  1201.     {
  1202.             /* Run down the number of beeps to produce. */
  1203.  
  1204.         while(number--)
  1205.         {
  1206.                 /* Beep! */
  1207.  
  1208.             DisplayBeep(Window -> WScreen);
  1209.  
  1210.                 /* Wait a bit. */
  1211.  
  1212.             if(number)
  1213.                 Delay(TICKS_PER_SECOND / 2);
  1214.         }
  1215.     }
  1216.     else
  1217.     {
  1218.             /* Is the sound name buffer available? */
  1219.  
  1220.         if(SoundName)
  1221.         {
  1222.             Bool GotSound;
  1223.  
  1224.                 /* What are we to do next? */
  1225.  
  1226.             switch(action)
  1227.             {
  1228.                     /* If a new sound is to be replayed, stop
  1229.                      * the current sound.
  1230.                      */
  1231.  
  1232.                 case 2:    if(number != SoundNumber && SoundNumber != -1 && SoundControlRequest)
  1233.                     {
  1234.                         SoundAbort();
  1235.  
  1236.                             /* Free previously allocated sound data. */
  1237.  
  1238.                         if(SoundData && SoundLength)
  1239.                         {
  1240.                                 /* Free it. */
  1241.  
  1242.                             FreeMem(SoundData,SoundLength);
  1243.  
  1244.                                 /* Leave no traces. */
  1245.  
  1246.                             SoundData    = NULL;
  1247.                             SoundLength    = 0;
  1248.                         }
  1249.  
  1250.                         SoundNumber = -1;
  1251.                     }
  1252.  
  1253.                         /* Make sure that we have the resources we need,
  1254.                          * either allocate them or rely on the fact that
  1255.                          * the previous call to this routine had already
  1256.                          * triggered the allocation.
  1257.                          */
  1258.  
  1259.                     if(!SoundControlRequest)
  1260.                         GotSound = SoundInit();
  1261.                     else
  1262.                         GotSound = TRUE;
  1263.  
  1264.                         /* Do we have the resources or not? */
  1265.  
  1266.                     if(GotSound)
  1267.                     {
  1268.                             /* If we are to replay the same sound as we
  1269.                              * did before, we are probably to change the
  1270.                              * replay volume.
  1271.                              */
  1272.  
  1273.                         if(SoundNumber == number && SoundNumber != -1)
  1274.                         {
  1275.                                 /* Is the sound still playing? If so,
  1276.                                  * change the volume, else restart
  1277.                                  * it with the new volume.
  1278.                                  */
  1279.  
  1280.                             if(!CheckIO((struct IORequest *)SoundRequestLeft))
  1281.                             {
  1282.                                     /* Set up new volume. */
  1283.  
  1284.                                 SoundControlRequest -> ioa_Request . io_Command    = ADCMD_PERVOL;
  1285.                                 SoundControlRequest -> ioa_Request . io_Flags    = ADIOF_PERVOL;
  1286.                                 SoundControlRequest -> ioa_Volume        = volume * 8;
  1287.  
  1288.                                     /* Tell the device to make the change. */
  1289.  
  1290.                                 SendIO((struct IORequest *)SoundControlRequest);
  1291.                                 WaitIO((struct IORequest *)SoundControlRequest);
  1292.                             }
  1293.                             else
  1294.                             {
  1295.                                     /* Wait for requests to return. */
  1296.  
  1297.                                 SoundAbort();
  1298.  
  1299.                                     /* Set up new volume. */
  1300.  
  1301.                                 SoundRequestLeft  -> ioa_Volume = volume * 8;
  1302.                                 SoundRequestRight -> ioa_Volume = volume * 8;
  1303.  
  1304.                                     /* Stop the sound. */
  1305.  
  1306.                                 SoundStop();
  1307.  
  1308.                                     /* Queue the sound. */
  1309.  
  1310.                                 BeginIO((struct IORequest *)SoundRequestLeft);
  1311.                                 BeginIO((struct IORequest *)SoundRequestRight);
  1312.  
  1313.                                     /* Start the sound. */
  1314.  
  1315.                                 SoundStart();
  1316.                             }
  1317.                         }
  1318.                         else
  1319.                         {
  1320.                                 /* The sound file header. */
  1321.  
  1322.                             struct
  1323.                             {
  1324.                                 UBYTE    Reserved1[2];
  1325.                                 BYTE    Times;        /* How many times to play (0 = continuously). */
  1326.                                 UBYTE    Rate[2];    /* Replay rate (note: little endian). */
  1327.                                 UBYTE    Reserved2[3];
  1328.                                 UWORD    PlayLength;    /* Length of sound to replay. */
  1329.                             } SoundHeader;
  1330.  
  1331.                                 /* Sound file handle and name buffer. */
  1332.  
  1333.                             FILE *SoundFile;
  1334.  
  1335.                                 /* Cancel the number of the previously loaded
  1336.                                  * sound in case the load fails.
  1337.                                  */
  1338.  
  1339.                             SoundNumber = -1;
  1340.  
  1341.                                 /* Set up the sound file name. */
  1342.  
  1343.                             sprintf(SoundPath,"sound/s%d.nam",number);
  1344.  
  1345.                                 /* Open the file for reading. */
  1346.  
  1347.                             if(SoundFile = fopen(SoundName,"rb"))
  1348.                             {
  1349.                                     /* The name of the sound file, as
  1350.                                      * given in the header.
  1351.                                      */
  1352.  
  1353.                                 char SoundFileName[34 + 1];
  1354.  
  1355.                                     /* Read the header. */
  1356.  
  1357.                                 if(fread(SoundFileName,1,34,SoundFile) < 1)
  1358.                                     SoundPath[0] = 0;
  1359.                                 else
  1360.                                     sprintf(SoundPath,"sound/%s",SoundFileName + 2);
  1361.  
  1362.                                     /* Close the file. */
  1363.  
  1364.                                 fclose(SoundFile);
  1365.                             }
  1366.                             else
  1367.                                 SoundPath[0] = 0;
  1368.  
  1369.                                 /* Did we get a name? */
  1370.  
  1371.                             if(SoundPath[0])
  1372.                             {
  1373.                                     /* Open the file for reading. */
  1374.  
  1375.                                 if(SoundFile = fopen(SoundName,"rb"))
  1376.                                 {
  1377.                                         /* Read the file header. */
  1378.  
  1379.                                     if(fread(&SoundHeader,sizeof(SoundHeader),1,SoundFile) == 1)
  1380.                                     {
  1381.                                             /* Remember the sound file length. */
  1382.  
  1383.                                         SoundLength = SoundHeader . PlayLength;
  1384.  
  1385.                                             /* Allocate chip ram for the sound data. */
  1386.  
  1387.                                         if(SoundData = (APTR)AllocMem(SoundLength,MEMF_CHIP))
  1388.                                         {
  1389.                                                 /* Read the sound data. */
  1390.  
  1391.                                             if(fread(SoundData,SoundLength,1,SoundFile) == 1)
  1392.                                             {
  1393.                                                     /* Turn the replay rate into a
  1394.                                                      * sensible number.
  1395.                                                      */
  1396.  
  1397.                                                 ULONG Rate = (GfxBase -> DisplayFlags & PAL ? 3546895 : 3579545) / ((((UWORD)SoundHeader . Rate[1]) << 8) | SoundHeader . Rate[0]);
  1398.  
  1399.                                                     /* Set up the left channel. */
  1400.  
  1401.                                                 SoundRequestLeft -> ioa_Request . io_Command    = CMD_WRITE;
  1402.                                                 SoundRequestLeft -> ioa_Request . io_Flags    = ADIOF_PERVOL;
  1403.                                                 SoundRequestLeft -> ioa_Period            = Rate;
  1404.                                                 SoundRequestLeft -> ioa_Volume            = volume * 8;
  1405.                                                 SoundRequestLeft -> ioa_Cycles            = SoundHeader . Times;
  1406.                                                 SoundRequestLeft -> ioa_Data            = SoundData;
  1407.                                                 SoundRequestLeft -> ioa_Length            = SoundLength;
  1408.  
  1409.                                                     /* Set up the right channel. */
  1410.  
  1411.                                                 SoundRequestRight -> ioa_Request . io_Command    = CMD_WRITE;
  1412.                                                 SoundRequestRight -> ioa_Request . io_Flags    = ADIOF_PERVOL;
  1413.                                                 SoundRequestRight -> ioa_Period            = Rate;
  1414.                                                 SoundRequestRight -> ioa_Volume            = volume * 8;
  1415.                                                 SoundRequestRight -> ioa_Cycles            = SoundHeader . Times;
  1416.                                                 SoundRequestRight -> ioa_Data            = SoundData;
  1417.                                                 SoundRequestRight -> ioa_Length            = SoundLength;
  1418.  
  1419.                                                     /* Set up the control request. */
  1420.  
  1421.                                                 SoundControlRequest -> ioa_Period        = Rate;
  1422.  
  1423.                                                     /* Stop playing any sound. */
  1424.  
  1425.                                                 SoundStop();
  1426.  
  1427.                                                     /* Queue the sound. */
  1428.  
  1429.                                                 BeginIO((struct IORequest *)SoundRequestLeft);
  1430.                                                 BeginIO((struct IORequest *)SoundRequestRight);
  1431.  
  1432.                                                     /* Play the sound. */
  1433.  
  1434.                                                 SoundStart();
  1435.  
  1436.                                                     /* Remember the number of the current sound. */
  1437.  
  1438.                                                 SoundNumber = number;
  1439.                                             }
  1440.                                             else
  1441.                                             {
  1442.                                                     /* The load failed, free the audio memory. */
  1443.  
  1444.                                                 FreeMem(SoundData,SoundLength);
  1445.  
  1446.                                                     /* Leave no traces. */
  1447.  
  1448.                                                 SoundData    = NULL;
  1449.                                                 SoundLength    = 0;
  1450.                                             }
  1451.                                         }
  1452.                                     }
  1453.  
  1454.                                         /* Close the sound file. */
  1455.  
  1456.                                     fclose(SoundFile);
  1457.                                 }
  1458.                             }
  1459.                         }
  1460.                     }
  1461.  
  1462.                     break;
  1463.  
  1464.                     /* Stop the current sound. */
  1465.  
  1466.                 case 3:    SoundExit();
  1467.                     break;
  1468.             }
  1469.         }
  1470.     }
  1471. }
  1472.  
  1473. /*
  1474.  * Function:    scr_putmesg()
  1475.  *
  1476.  * Arguments:
  1477.  *      buffer      message string to be printed.
  1478.  *      is_err      1 if message is an error message, 0 if it's not.
  1479.  *
  1480.  * Description:
  1481.  *      This function prints out a message from the interpreter, not
  1482.  *      from the game itself.  Often these are errors (IS_ERROR==1)
  1483.  *      but not necessarily.
  1484.  */
  1485.  
  1486. void
  1487. scr_putmesg(const char *buffer,Bool is_err)
  1488. {
  1489.         /* Provide an empty line. */
  1490.  
  1491.     ConScrollUp();
  1492.  
  1493.         /* Is this supposed to be an error message? */
  1494.  
  1495.     if(is_err)
  1496.     {
  1497.             /* Set error text colour. */
  1498.  
  1499.         ConSetColour(COLOUR_ERROR);
  1500.  
  1501.             /* Display the error message. */
  1502.  
  1503.         ConPrintf("[%s]",buffer);
  1504.  
  1505.             /* Reset text colour. */
  1506.  
  1507.         ConSetColour(COLOUR_TEXT);
  1508.     }
  1509.     else
  1510.         ConPrintf("[%s]",buffer);
  1511. }
  1512.  
  1513. /*
  1514.  * Function:    scr_getline()
  1515.  *
  1516.  * Arguments:
  1517.  *      prompt    - prompt to be printed
  1518.  *      length    - total size of BUFFER
  1519.  *      buffer    - buffer to return nul-terminated response in
  1520.  *
  1521.  * Returns:
  1522.  *      # of chars stored in BUFFER
  1523.  *
  1524.  * Description:
  1525.  *      Reads a line of input and returns it.  Handles all "special
  1526.  *      operations" such as readline history support, shell escapes,
  1527.  *      etc. invisibly to the caller.  Note that the returned BUFFER
  1528.  *      will be at most LENGTH-1 chars long because the last char will
  1529.  *      always be the nul character.
  1530.  *
  1531.  *      If the command begins with ESC_CHAR then it's an interpreter
  1532.  *      escape command; call ti_escape() with the rest of the line,
  1533.  *      then ask for another command.
  1534.  *
  1535.  * Notes:
  1536.  *      May print the STATUS buffer more than once if necessary (i.e.,
  1537.  *      a shell escape messed up the screen, a history listing was
  1538.  *      generated, etc.).
  1539.  */
  1540.  
  1541. int
  1542. scr_getline(const char *prompt,int length,char *buffer)
  1543. {
  1544.     char    *EscapeChar    = ESC_CHAR,
  1545.         *NewPrompt    = (char *)prompt;
  1546.     Bool     Done        = FALSE;
  1547.     int     InputLength;
  1548.  
  1549.         /* Loop until user provides any input. */
  1550.  
  1551.     do
  1552.     {
  1553.             /* Get the scripting menu item. */
  1554.  
  1555.         if(NewOS)
  1556.         {
  1557.             struct MenuItem *Item;
  1558.  
  1559.             if(Item = ItemAddress(Menu,FULLMENUNUM(MENU_PROJECT,PROJECTMENU_SCRIPT,NOSUB)))
  1560.             {
  1561.                     /* Change the state of the checkmark. */
  1562.  
  1563.                 if(!F2_IS_SET(B_SCRIPTING))
  1564.                 {
  1565.                     if(Item -> Flags & CHECKED)
  1566.                         Item -> Flags &= ~CHECKED;
  1567.                 }
  1568.                 else
  1569.                 {
  1570.                     if(!(Item -> Flags & CHECKED))
  1571.                         Item -> Flags |= CHECKED;
  1572.                 }
  1573.             }
  1574.  
  1575.                 /* Update the menu strip. */
  1576.  
  1577.             ConUpdateMenus();
  1578.         }
  1579.  
  1580.             /* Print the status line. */
  1581.  
  1582.         scr_putscore();
  1583.  
  1584.             /* Scroll the screen contents up. */
  1585.  
  1586.         ConScrollUp();
  1587.  
  1588.             /* Do we have any prompt to print? */
  1589.  
  1590.         if(NewPrompt[0])
  1591.         {
  1592.                 /* Split the prompt and print it. */
  1593.  
  1594.             NewPrompt = ConSplitLine(NewPrompt,strlen(NewPrompt),TRUE);
  1595.  
  1596.                 /* If the prompt was turned into several
  1597.                  * lines of text, scroll the screen
  1598.                  * contents up.
  1599.                  */
  1600.  
  1601.             if(NewPrompt != prompt)
  1602.                 ConScrollUp();
  1603.  
  1604.                 /* Is there still anything left of it?
  1605.                  * If so, print it.
  1606.                  */
  1607.  
  1608.             if(NewPrompt[0])
  1609.                 ConWrite(NewPrompt,-1,0);
  1610.         }
  1611.  
  1612.             /* Enough done. */
  1613.  
  1614.         ConLinesPrinted = 0;
  1615.  
  1616.             /* Turn on the cursor. */
  1617.  
  1618.         ConCursorOn(CURSOR_AVERAGE);
  1619.  
  1620.             /* Change the text colour. */
  1621.  
  1622.         ConSetColour(COLOUR_INPUT);
  1623.  
  1624.             /* Read the line of text. */
  1625.  
  1626.         InputLength = ConInput(NewPrompt,buffer,length,TRUE);
  1627.  
  1628.             /* Strip trailing blank spaces. */
  1629.  
  1630.         while(InputLength > 0)
  1631.         {
  1632.             if(buffer[InputLength - 1] == ' ')
  1633.                 InputLength--;
  1634.             else
  1635.                 break;
  1636.         }
  1637.  
  1638.             /* Provide null-termination. */
  1639.  
  1640.         buffer[InputLength] = 0;
  1641.  
  1642.             /* Set the text colour. */
  1643.  
  1644.         ConSetColour(COLOUR_TEXT);
  1645.  
  1646.             /* Turn the cursor off. */
  1647.  
  1648.         ConCursorOff();
  1649.  
  1650.             /* Special actions to be taken? */
  1651.  
  1652.         if(*buffer == *EscapeChar)
  1653.         {
  1654.                 /* Perform special actions. */
  1655.  
  1656.             ti_escape(&buffer[1]);
  1657.  
  1658.                 /* Update options menu items. */
  1659.  
  1660.             if(NewOS)
  1661.                 ConUpdateMenus();
  1662.         }
  1663.         else
  1664.             Done = TRUE;
  1665.     }
  1666.     while(!Done);
  1667.  
  1668.         /* Output text to script file. */
  1669.  
  1670.     if(F2_IS_SET(B_SCRIPTING))
  1671.     {
  1672.             /* Split the prompt. */
  1673.  
  1674.         NewPrompt = ScriptSplitLine((char *)prompt,strlen(prompt),TRUE);
  1675.  
  1676.             /* Build prompt and input string. */
  1677.  
  1678.         strcpy(TempBuffer,NewPrompt);
  1679.         strcat(TempBuffer,buffer);
  1680.  
  1681.             /* Transcribe it. */
  1682.  
  1683.         ScriptWrite(TempBuffer,strlen(TempBuffer));
  1684.     }
  1685.  
  1686.         /* Return number of characters read. */
  1687.  
  1688.     return(InputLength);
  1689. }
  1690.  
  1691. /*
  1692.  * Function:    scr_window()
  1693.  *
  1694.  * Arguments:
  1695.  *      size      - 0 to delete, non-0 means create with SIZE.
  1696.  *
  1697.  * Description:
  1698.  *      Causes a status window to be created if supported by the
  1699.  *      terminal interface; note this function won't be called unless
  1700.  *      F1_SETB(B_STATUS_WIN) is invoked in scr_begin().
  1701.  *
  1702.  * Notes:
  1703.  */
  1704.  
  1705. void
  1706. scr_window(int size)
  1707. {
  1708.         /* Are we to set up the status window? */
  1709.  
  1710.     if(size)
  1711.     {
  1712.             /* Determine new status window area. */
  1713.  
  1714.         ConNumStatusLines = size + 1;
  1715.  
  1716.             /* Clear the status window area. */
  1717.  
  1718.         SetAPen(RPort,ConBackPen);
  1719.         RectFill(RPort,WindowBorderLeft,WindowBorderTop + TextFontHeight,Window -> Width - WindowBorderRight - 1,WindowBorderTop + TextFontHeight * (size + 1) - 1);
  1720.         SetAPen(RPort,ConTextPen);
  1721.     }
  1722.     else
  1723.     {
  1724.             /* Reset to defaults. */
  1725.  
  1726.         ConNumStatusLines    = 1;
  1727.         ConOutputWindow        = 0;
  1728.     }
  1729. }
  1730.  
  1731. /*
  1732.  * Function:    scr_set_win()
  1733.  *
  1734.  * Arguments:
  1735.  *      win       - 0==select text window, 1==select status window
  1736.  *
  1737.  * Description:
  1738.  *      Selects a different window.  This function won't be called
  1739.  *      unless call F1_SETB(B_STATUS_WIN) in scr_begin().
  1740.  *
  1741.  * Notes:
  1742.  */
  1743.  
  1744. void
  1745. scr_set_win(int win)
  1746. {
  1747.     STATIC LONG    SavedCursorX,
  1748.             SavedCursorY;
  1749.  
  1750.         /* Are we to select the status window? */
  1751.  
  1752.     if(win)
  1753.     {
  1754.             /* Is the text window still active? */
  1755.  
  1756.         if(!ConOutputWindow)
  1757.         {
  1758.                 /* Remember old cursor position. */
  1759.  
  1760.             SavedCursorX = CursorX;
  1761.             SavedCursorY = CursorY;
  1762.  
  1763.                 /* Turn the cursor off, we
  1764.                  * won't be needing it.
  1765.                  */
  1766.  
  1767.             ConCursorOff();
  1768.  
  1769.                 /* Remember new output window area. */
  1770.  
  1771.             ConOutputWindow = win;
  1772.         }
  1773.  
  1774.             /* Move to the beginning of the status window. */
  1775.  
  1776.         CursorY = TextFontHeight;
  1777.         CursorX = 0;
  1778.     }
  1779.     else
  1780.     {
  1781.             /* Is the status window still active? */
  1782.  
  1783.         if(ConOutputWindow)
  1784.         {
  1785.                 /* Get back the old cursor position. */
  1786.  
  1787.             CursorX = SavedCursorX;
  1788.             CursorY = SavedCursorY;
  1789.  
  1790.                 /* Turn the cursor back on. */
  1791.  
  1792.             ConCursorOn(CURSOR_NOCHANGE);
  1793.  
  1794.                 /* Change the current output window. */
  1795.  
  1796.             ConOutputWindow = win;
  1797.         }
  1798.     }
  1799. }
  1800.  
  1801. /*
  1802.  * Function:    scr_open_sf()
  1803.  *
  1804.  * Arguments:
  1805.  *      length    - total size of BUFFER
  1806.  *      buffer    - buffer to return nul-terminated filename in
  1807.  *      type      - SF_SAVE     opening the file to save into
  1808.  *                  SF_RESTORE  opening the file to restore from
  1809.  *                  SF_SCRIPT   opening a file for scripting
  1810.  *
  1811.  * Returns:
  1812.  *      FILE* - reference to the opened file, or
  1813.  *      NULL  - errno==0: operation cancelled, else error opening file
  1814.  *
  1815.  * Description:
  1816.  *      Obtains the name of the file to be opened for writing (if
  1817.  *      TYPE==SF_SAVE or SF_SCRIPT) or reading (if TYPE==SF_RESTORE),
  1818.  *      opens the file with fopen(), and returns the FILE*.
  1819.  *
  1820.  *      The name of the file should be stored in BUFFER.  Upon initial
  1821.  *      calling BUFFER contains a possible default filename.
  1822.  *
  1823.  *      if LENGTH==0 then don't ask the user for a name, just use
  1824.  *      BUFFER.  This means, for example, we got the -r option to
  1825.  *      restore the file.
  1826.  *
  1827.  *      If the fopen() fails just return NULL: if errno!=0 then an
  1828.  *      error will be printed.
  1829.  *
  1830.  * Notes:
  1831.  *      History is turned off here (why would anyone want it?)
  1832.  */
  1833.  
  1834. FILE *
  1835. scr_open_sf(int length, char *buffer, int type)
  1836. {
  1837.         /* Prompt buffer and filename buffer. */
  1838.  
  1839.     STATIC char    FileName[MAX_FILENAME_LENGTH],
  1840.             Prompt[MAX_FILENAME_LENGTH + 18];
  1841.  
  1842.         /* Are we running under control of Kickstart 2.04 or higher? */
  1843.  
  1844.     if(NewOS)
  1845.     {
  1846.         Bool     GotName = FALSE,
  1847.              GotFile = FALSE;
  1848.         int     Len;
  1849.         char    *ScriptMode;
  1850.  
  1851.             /* Are we to prompt for a file name? */
  1852.  
  1853.         if(length)
  1854.         {
  1855.                 /* Block window input. */
  1856.  
  1857.             ConBlockWindow(Window);
  1858.  
  1859.                 /* No scripting in this part, please. */
  1860.  
  1861.             if(type != SF_SCRIPT)
  1862.             {
  1863.                     /* Are we to load a saved game file? */
  1864.  
  1865.                 if(ProjectName[0])
  1866.                 {
  1867.                         /* Is the project name small enough to fit? */
  1868.  
  1869.                     if((Len = strlen(ProjectName)) < length)
  1870.                     {
  1871.                             /* Store the project name. */
  1872.  
  1873.                         strcpy(buffer,ProjectName);
  1874.  
  1875.                             /* Now we've got a name. */
  1876.  
  1877.                         GotName = TRUE;
  1878.                     }
  1879.  
  1880.                         /* Clear the project name. */
  1881.  
  1882.                     ProjectName[0] = 0;
  1883.                 }
  1884.                 else
  1885.                 {
  1886.                     char *Index;
  1887.  
  1888.                         /* Loop until a proper name is entered or the
  1889.                          * selection is aborted.
  1890.                          */
  1891.  
  1892.                     do
  1893.                     {
  1894.                             /* Save the input file name. */
  1895.  
  1896.                         strcpy(FileName,buffer);
  1897.  
  1898.                             /* Extract the path name. */
  1899.  
  1900.                         if(Index = PathPart(FileName))
  1901.                             *Index = 0;
  1902.  
  1903.                             /* If no path name is given, supply the
  1904.                              * current directory.
  1905.                              */
  1906.  
  1907.                         if(!FileName[0])
  1908.                         {
  1909.                             /* Try to obtain the current directory name.
  1910.                              * If this fails, leave the path name empty.
  1911.                              */
  1912.  
  1913.                             if(!GetCurrentDirName(FileName,MAX_FILENAME_LENGTH))
  1914.                                 FileName[0] = 0;
  1915.                         }
  1916.  
  1917.                             /* Request a file and path name. */
  1918.  
  1919.                         if(AslRequestTags(GameFileRequest,
  1920.                             ASL_Window,    Window,
  1921.                             ASL_Dir,    FileName,
  1922.                             ASL_File,    FilePart(buffer),
  1923.                             ASL_FuncFlags,    (type == SF_SAVE) ? FILF_SAVE | FILF_PATGAD    : FILF_PATGAD,
  1924.                             ASL_Hail,    (type == SF_SAVE) ? "Select game file to save"    : "Select game file to restore",
  1925.                             ASL_Pattern,    "#?.Save",
  1926.                         TAG_DONE))
  1927.                         {
  1928.                                 /* Did the user select a file? */
  1929.  
  1930.                             if(Len = strlen((char *)GameFileRequest -> rf_File))
  1931.                             {
  1932.                                 char *Name = (char *)GameFileRequest -> rf_File;
  1933.  
  1934.                                     /* Are we to save a game file? */
  1935.  
  1936.                                 if(type == SF_SAVE)
  1937.                                 {
  1938.                                     Bool NewName = FALSE;
  1939.  
  1940.                                         /* Is there enough space left to append
  1941.                                          * the `.Save' suffix?
  1942.                                          */
  1943.  
  1944.                                     if(Len <= AMIGADOS_NAME_LIMIT - SAVE_SUFFIX_LENGTH)
  1945.                                     {
  1946.                                         if(Len > SAVE_SUFFIX_LENGTH)
  1947.                                         {
  1948.                                                 /* Does it already have the `.Save' suffix
  1949.                                                  * attached?
  1950.                                                  */
  1951.  
  1952.                                             if(Stricmp((STRPTR)&Name[Len - SAVE_SUFFIX_LENGTH],SAVE_SUFFIX))
  1953.                                                 NewName = TRUE;
  1954.                                         }
  1955.                                         else
  1956.                                             NewName = TRUE;
  1957.                                     }
  1958.  
  1959.                                         /* Are we to append the `.Save' suffix? */
  1960.  
  1961.                                     if(NewName)
  1962.                                     {
  1963.                                             /* Tack on the suffix. */
  1964.  
  1965.                                         strcpy(TempBuffer,Name);
  1966.                                         strcat(TempBuffer,SAVE_SUFFIX);
  1967.  
  1968.                                         Name = TempBuffer;
  1969.                                     }
  1970.                                 }
  1971.  
  1972.                                     /* Copy the path name. */
  1973.  
  1974.                                 strcpy(FileName,(char *)GameFileRequest -> rf_Dir);
  1975.  
  1976.                                     /* Attach the file name. */
  1977.  
  1978.                                 if(AddPart((STRPTR)FileName,(STRPTR)Name,MAX_FILENAME_LENGTH))
  1979.                                 {
  1980.                                         /* Copy the new file name. */
  1981.  
  1982.                                     strcpy(buffer,FileName);
  1983.  
  1984.                                         /* Check whether the destination file already
  1985.                                          * exists.
  1986.                                          */
  1987.  
  1988.                                     if(type == SF_SAVE)
  1989.                                     {
  1990.                                         BPTR FileLock;
  1991.  
  1992.                                             /* Does it already exist? */
  1993.  
  1994.                                         if(FileLock = Lock(FileName,ACCESS_READ))
  1995.                                         {
  1996.                                                 /* Release the lock. */
  1997.  
  1998.                                             UnLock(FileLock);
  1999.  
  2000.                                                 /* Ask the user what to do next. */
  2001.  
  2002.                                             switch(ConShowRequest(Window,"You are about to overwrite an existing file!","Proceed|New name|Cancel"))
  2003.                                             {
  2004.                                                 case SAVE_CANCEL:    GotFile = TRUE;
  2005.                                                             break;
  2006.  
  2007.                                                 case SAVE_PROCEED:    GotFile = GotName = TRUE;
  2008.                                                             break;
  2009.  
  2010.                                                 case SAVE_NEWNAME:    GotFile = FALSE;
  2011.                                                             break;
  2012.                                             }
  2013.                                         }
  2014.                                         else
  2015.                                         {
  2016.                                                 /* Remember that we got a new file name. */
  2017.  
  2018.                                             GotFile = GotName = TRUE;
  2019.                                         }
  2020.                                     }
  2021.                                     else
  2022.                                     {
  2023.                                             /* Remember that we got a new file name. */
  2024.  
  2025.                                         GotFile = GotName = TRUE;
  2026.                                     }
  2027.                                 }
  2028.                                 else
  2029.                                     GotFile = TRUE;
  2030.                             }
  2031.                             else
  2032.                                 GotFile = TRUE;
  2033.                         }
  2034.                         else
  2035.                             GotFile = TRUE;
  2036.                     }
  2037.                     while(!GotFile);
  2038.                 }
  2039.             }
  2040.             else
  2041.             {
  2042.                     /* If no printer width has been defined yet,
  2043.                      * consult the system preferences settings.
  2044.                      */
  2045.  
  2046.                 if(!ScriptWidth)
  2047.                 {
  2048.                     struct Preferences Prefs;
  2049.  
  2050.                         /* Get the system preferences. */
  2051.  
  2052.                     if(GetPrefs(&Prefs,sizeof(struct Preferences)))
  2053.                     {
  2054.                             /* Adjust the width if too small. */
  2055.  
  2056.                         if((ScriptWidth = (int)Prefs . PrintRightMargin - (int)Prefs . PrintLeftMargin + 1) < MIN_PRINTER_COLUMNS)
  2057.                             ScriptWidth = MIN_PRINTER_COLUMNS;
  2058.                     }
  2059.                 }
  2060.  
  2061.                     /* Loop until we get a name. */
  2062.  
  2063.                 do
  2064.                 {
  2065.                         /* Get the desired output file and width. */
  2066.  
  2067.                     if(ScriptGetPrinterName((STRPTR)buffer,&ScriptWidth))
  2068.                     {
  2069.                         STRPTR Index;
  2070.  
  2071.                             /* Get the file path part. */
  2072.  
  2073.                         Index = PathPart(buffer);
  2074.  
  2075.                             /* Is it a real file or a device
  2076.                              * name such as "PRT:"?
  2077.                              */
  2078.  
  2079.                         if(*Index)
  2080.                         {
  2081.                             BPTR FileLock;
  2082.  
  2083.                                 /* Does it exist already? */
  2084.  
  2085.                             if(FileLock = Lock(buffer,ACCESS_READ))
  2086.                             {
  2087.                                     /* Release the lock. */
  2088.  
  2089.                                 UnLock(FileLock);
  2090.  
  2091.                                     /* Ask the user what to do next. */
  2092.  
  2093.                                 switch(ConShowRequest(Window,"You are about to overwrite an existing file!","Proceed|Append|New name|Cancel"))
  2094.                                 {
  2095.                                     case SCRIPT_CANCEL:    GotFile = TRUE;
  2096.  
  2097.                                                 break;
  2098.  
  2099.                                     case SCRIPT_PROCEED:    ScriptMode = "w";
  2100.  
  2101.                                                 GotFile = GotName = TRUE;
  2102.  
  2103.                                                 break;
  2104.  
  2105.                                     case SCRIPT_APPEND:    ScriptMode = "a";
  2106.  
  2107.                                                 GotFile = GotName = TRUE;
  2108.  
  2109.                                                 break;
  2110.  
  2111.                                     case SCRIPT_NEWNAME:    continue;
  2112.                                 }
  2113.                             }
  2114.                             else
  2115.                             {
  2116.                                 ScriptMode = "w";
  2117.  
  2118.                                 GotFile = GotName = TRUE;
  2119.                             }
  2120.                         }
  2121.                         else
  2122.                         {
  2123.                             ScriptMode = "w";
  2124.  
  2125.                             GotFile = GotName = TRUE;
  2126.                         }
  2127.                     }
  2128.                     else
  2129.                         GotFile = TRUE;
  2130.                 }
  2131.                 while(!GotFile);
  2132.             }
  2133.  
  2134.                 /* Unblock the window. */
  2135.  
  2136.             ConUnblockWindow(Window);
  2137.         }
  2138.         else
  2139.             GotName = TRUE;
  2140.  
  2141.             /* Return the result. */
  2142.  
  2143.         if(GotName)
  2144.             {
  2145.             FILE *File;
  2146.  
  2147.                 /* Get the file name. */
  2148.  
  2149.             strcpy(WindowTitle,FilePart((STRPTR)buffer));
  2150.  
  2151.                 /* Determine file name length. */
  2152.  
  2153.             Len = strlen(WindowTitle);
  2154.  
  2155.                 /* Is it long enough to hold the ".Save" suffix? */
  2156.  
  2157.             if(Len > SAVE_SUFFIX_LENGTH)
  2158.             {
  2159.                     /* Is the ".Save" suffix present? If so,
  2160.                      * get rid of it.
  2161.                      */
  2162.  
  2163.                 if(!Stricmp(&WindowTitle[Len - SAVE_SUFFIX_LENGTH],SAVE_SUFFIX))
  2164.                     WindowTitle[Len - SAVE_SUFFIX_LENGTH] = 0;
  2165.             }
  2166.  
  2167.                 /* Open the output file. */
  2168.  
  2169.             switch(type)
  2170.             {
  2171.                     /* Saved game file handling. */
  2172.  
  2173.                 case SF_SAVE:        if(File = fopen(buffer,"wb"))
  2174.                             {
  2175.                                 if(!Screen)
  2176.                                     SetWindowTitles(Window,WindowTitle,(STRPTR)~0);
  2177.                             }
  2178.  
  2179.                             return(File);
  2180.  
  2181.                 case SF_RESTORE:    if(File = fopen(buffer,"rb"))
  2182.                             {
  2183.                                 if(!Screen)
  2184.                                     SetWindowTitles(Window,WindowTitle,(STRPTR)~0);
  2185.                             }
  2186.  
  2187.                             return(File);
  2188.  
  2189.                     /* Script file handling. */
  2190.  
  2191.                 case SF_SCRIPT:        if(ScriptFile = fopen(buffer,ScriptMode))
  2192.                             {
  2193.                                 struct MenuItem *Item;
  2194.  
  2195.                                 strcpy(ScriptFileName,buffer);
  2196.  
  2197.                                     /* Block the menu strip. */
  2198.  
  2199.                                 ConLockMenus();
  2200.  
  2201.                                     /* Change the `Script...' menu item
  2202.                                      * according to the current scripting
  2203.                                      * settings.
  2204.                                      */
  2205.  
  2206.                                 Item = ItemAddress(Menu,FULLMENUNUM(MENU_PROJECT,PROJECTMENU_SCRIPT,NOSUB));
  2207.  
  2208.                                 Item -> Flags |= CHECKED;
  2209.  
  2210.                                     /* Enable the menu strip again. */
  2211.  
  2212.                                 ConUnlockMenus();
  2213.  
  2214.                                     /* If line padding is enabled,
  2215.                                      * allocate auxilary buffers.
  2216.                                      */
  2217.  
  2218.                                 if(FillLines)
  2219.                                     ScriptPadSetup(ScriptWidth);
  2220.  
  2221.                                     /* Clear the flag. */
  2222.  
  2223.                                 ScriptAborted = FALSE;
  2224.                             }
  2225.  
  2226.                             return(ScriptFile);
  2227.             }
  2228.         }
  2229.     }
  2230.     else
  2231.     {
  2232.             /* Are we to ask the user to provide any input? */
  2233.  
  2234.         if(length)
  2235.         {
  2236.                 /* Tell the user what to do. */
  2237.  
  2238.             scr_putline("Enter a file name.");
  2239.  
  2240.                 /* Build a prompt string. */
  2241.  
  2242.             sprintf(Prompt,"(Default is \"%s\") >",buffer);
  2243.  
  2244.                 /* Read the input line. */
  2245.  
  2246.             if(!scr_getline(Prompt,MAX_FILENAME_LENGTH,FileName))
  2247.                 strcpy(FileName,buffer);
  2248.  
  2249.                 /* Are we to open a file for saving? */
  2250.  
  2251.             if(type == SF_SAVE || type == SF_SCRIPT)
  2252.             {
  2253.                 BPTR    FileLock;
  2254.                 int    Len = strlen(FileName);
  2255.  
  2256.                     /* If no printer width has been defined yet,
  2257.                      * consult the system preferences settings.
  2258.                      */
  2259.  
  2260.                 if(!ScriptWidth && type == SF_SCRIPT)
  2261.                 {
  2262.                     struct Preferences Prefs;
  2263.  
  2264.                         /* Get the system preferences. */
  2265.  
  2266.                     if(GetPrefs(&Prefs,sizeof(struct Preferences)))
  2267.                     {
  2268.                             /* Adjust the width if too small. */
  2269.  
  2270.                         if((ScriptWidth = (int)Prefs . PrintRightMargin - (int)Prefs . PrintLeftMargin + 1) < MIN_PRINTER_COLUMNS)
  2271.                             ScriptWidth = MIN_PRINTER_COLUMNS;
  2272.                     }
  2273.                 }
  2274.  
  2275.                 if(type == SF_SAVE || (type == SF_SCRIPT && FileName[Len - 1] != ':'))
  2276.                 {
  2277.                         /* Does the file already exist? */
  2278.  
  2279.                     if(FileLock = Lock(FileName,ACCESS_READ))
  2280.                     {
  2281.                             /* Release the lock on it. */
  2282.  
  2283.                         UnLock(FileLock);
  2284.  
  2285.                             /* Print a warning message. */
  2286.  
  2287.                         scr_putline("You are about to write over an existing file.");
  2288.  
  2289.                             /* Really continue? */
  2290.  
  2291.                         if(scr_getline("Proceed? (Y/N) >",1,TempBuffer))
  2292.                         {
  2293.                                 /* Check */
  2294.  
  2295.                             if(toupper(TempBuffer[0]) != 'Y')
  2296.                                 return(NULL);
  2297.                         }
  2298.                         else
  2299.                             return(NULL);
  2300.                     }
  2301.  
  2302.                         /* Store the new file name. */
  2303.  
  2304.                     strcpy(buffer,FileName);
  2305.  
  2306.                         /* Open the file. */
  2307.  
  2308.                     if(type == SF_SCRIPT)
  2309.                     {
  2310.                         if(ScriptFile = fopen(buffer,"w"))
  2311.                         {
  2312.                             strcpy(ScriptFileName,buffer);
  2313.  
  2314.                                 /* If line padding is enabled,
  2315.                                  * allocate auxilary buffers.
  2316.                                  */
  2317.  
  2318.                             if(FillLines)
  2319.                                 ScriptPadSetup(ScriptWidth);
  2320.                         }
  2321.  
  2322.                         return(ScriptFile);
  2323.                     }
  2324.                     else
  2325.                         return(fopen(buffer,"wb"));
  2326.                 }
  2327.                 else
  2328.                 {
  2329.                     if(ScriptFile = fopen(buffer,"w"))
  2330.                     {
  2331.                         strcpy(ScriptFileName,buffer);
  2332.  
  2333.                             /* If line padding is enabled,
  2334.                              * allocate auxilary buffers.
  2335.                              */
  2336.  
  2337.                         if(FillLines)
  2338.                             ScriptPadSetup(ScriptWidth);
  2339.                     }
  2340.  
  2341.                     return(ScriptFile);
  2342.                 }
  2343.             }
  2344.             else
  2345.             {
  2346.                     /* Store the new file name. */
  2347.  
  2348.                 strcpy(buffer,FileName);
  2349.  
  2350.                     /* Open the file. */
  2351.  
  2352.                 return(fopen(buffer,"rb"));
  2353.             }
  2354.         }
  2355.         else
  2356.         {
  2357.                 /* Open a file without asking for a name. */
  2358.  
  2359.             switch(type)
  2360.             {
  2361.                 case SF_SCRIPT:        if(ScriptFile = fopen(buffer,"w"))
  2362.                             {
  2363.                                 strcpy(ScriptFileName,buffer);
  2364.  
  2365.                                     /* If line padding is enabled,
  2366.                                      * allocate auxilary buffers.
  2367.                                      */
  2368.  
  2369.                                 if(FillLines)
  2370.                                     ScriptPadSetup(ScriptWidth);
  2371.                             }
  2372.  
  2373.                             return(ScriptFile);
  2374.  
  2375.                 case SF_SAVE:        return(fopen(buffer,"wb"));
  2376.                 case SF_RESTORE:    return(fopen(buffer,"rb"));
  2377.             }
  2378.         }
  2379.     }
  2380.  
  2381.     return(NULL);
  2382. }
  2383.  
  2384. /*
  2385.  * Function:    scr_close_sf()
  2386.  *
  2387.  * Arguments:
  2388.  *      filenm    - name of file just processed
  2389.  *      fp        - FILE* to open saved file
  2390.  *      type      - SF_SAVE     closing a saved game file
  2391.  *                  SF_RESTORE  closing a restored game file
  2392.  *                  SF_SCRIPT   closing a scripting file
  2393.  *
  2394.  * Description:
  2395.  *      This function will be called immediately after a successful
  2396.  *      save or restore of a game file, so that if the interface needs
  2397.  *      to perform any actions related to the saved game it may.  It
  2398.  *      will also be called when the interpreter notices that
  2399.  *      scripting has been turned off.  It should at least close the
  2400.  *      file.
  2401.  *
  2402.  *      This function will only be called if the save/restore of the
  2403.  *      game succeeded; if it fails the file will be closed by the
  2404.  *      interpreter.
  2405.  */
  2406.  
  2407. void
  2408. scr_close_sf(const char * filenm, FILE *fp, int type)
  2409. {
  2410.     struct DiskObject    *Icon = NULL;
  2411.     int             Len;
  2412.  
  2413.         /* Close the file. */
  2414.  
  2415.     fclose(fp);
  2416.  
  2417.         /* What are we to do? */
  2418.  
  2419.     switch(type)
  2420.     {
  2421.             /* Close a saved game file? */
  2422.  
  2423.         case SF_SAVE:
  2424.  
  2425.                 /* Clear the `executable' bit. */
  2426.  
  2427.             SetProtection((char *)filenm,FIBF_EXECUTE);
  2428.  
  2429.                 /* Get the default icon. */
  2430.  
  2431.             if(IconBase)
  2432.             {
  2433.                 if(NewOS)
  2434.                     Icon = GetDiskObject("PROGDIR:Icon.Data");
  2435.                 else
  2436.                     Icon = GetDiskObject("Icon.Data");
  2437.             }
  2438.  
  2439.                 /* Did we get any? */
  2440.  
  2441.             if(Icon)
  2442.             {
  2443.                 STRPTR *ToolTypes;
  2444.  
  2445.                     /* Create the tool type array. */
  2446.  
  2447.                 if(ToolTypes = (STRPTR *)malloc(sizeof(char *) * (NUM_FKEYS + NUM_OPTIONS + 1)))
  2448.                 {
  2449.                     int i,j = 0;
  2450.  
  2451.                         /* Fill in the file type. */
  2452.  
  2453.                     ToolTypes[j++] = "FILETYPE=BOOKMARK|ITF";
  2454.  
  2455.                         /* Add the story file name. */
  2456.  
  2457.                     if(ToolTypes[j] = (STRPTR)malloc(strlen(StoryName) + 7))
  2458.                         sprintf(ToolTypes[j++],"STORY=%s",StoryName);
  2459.  
  2460.                         /* Add the number of inter-page context lines,
  2461.                          * margin and indent settings.
  2462.                          */
  2463.  
  2464.                     if(ToolTypes[j] = (STRPTR)malloc(30))
  2465.                         sprintf(ToolTypes[j++],"CONTEXT=%d",ConLineContext);
  2466.  
  2467.                     if(ToolTypes[j] = (STRPTR)malloc(30))
  2468.                         sprintf(ToolTypes[j++],"INDENT=%d",ConLineIndent);
  2469.  
  2470.                     if(ToolTypes[j] = (STRPTR)malloc(30))
  2471.                         sprintf(ToolTypes[j++],"MARGIN=%d",ConLineMargin);
  2472.  
  2473.                         /* Take care of the remaining options. */
  2474.  
  2475.                     if(ConQueryOption(OPTION_ATTRIBUTE_ASSIGNMENTS))
  2476.                     {
  2477.                         if(ToolTypes[j] = (STRPTR)malloc(21))
  2478.                             strcpy(ToolTypes[j++],"ATTRIBUTEASSIGNMENTS");
  2479.                     }
  2480.  
  2481.                     if(ConQueryOption(OPTION_ATTRIBUTE_TESTS))
  2482.                     {
  2483.                         if(ToolTypes[j] = (STRPTR)malloc(15))
  2484.                             strcpy(ToolTypes[j++],"ATTRIBUTETESTS");
  2485.                     }
  2486.  
  2487.                     if(ConQueryOption(OPTION_ECHO))
  2488.                     {
  2489.                         if(ToolTypes[j] = (STRPTR)malloc(5))
  2490.                             strcpy(ToolTypes[j++],"ECHO");
  2491.                     }
  2492.  
  2493.                     if(!ConQueryOption(OPTION_PAGING))
  2494.                     {
  2495.                         if(ToolTypes[j] = (STRPTR)malloc(8))
  2496.                             strcpy(ToolTypes[j++],"NOPAGER");
  2497.                     }
  2498.  
  2499.                     if(ConQueryOption(OPTION_PROMPT))
  2500.                     {
  2501.                         if(ToolTypes[j] = (STRPTR)malloc(7))
  2502.                             strcpy(ToolTypes[j++],"PROMPT");
  2503.                     }
  2504.  
  2505.                     if(!ConQueryOption(OPTION_STATUS))
  2506.                     {
  2507.                         if(ToolTypes[j] = (STRPTR)malloc(9))
  2508.                             strcpy(ToolTypes[j++],"NOSTATUS");
  2509.                     }
  2510.  
  2511.                     if(ConQueryOption(OPTION_XFERS))
  2512.                     {
  2513.                         if(ToolTypes[j] = (STRPTR)malloc(10))
  2514.                             strcpy(ToolTypes[j++],"TRANSFERS");
  2515.                     }
  2516.  
  2517.                     if(ConQueryOption(OPTION_TANDY))
  2518.                     {
  2519.                         if(ToolTypes[j] = (STRPTR)malloc(6))
  2520.                             strcpy(ToolTypes[j++],"TANDY");
  2521.                     }
  2522.  
  2523.                         /* Add the function key definitions if any. */
  2524.  
  2525.                     for(i = 0 ; i < NUM_FKEYS ; i++)
  2526.                     {
  2527.                         if(FunctionKeys[i] . sb_Len)
  2528.                         {
  2529.                             if(ToolTypes[j] = (STRPTR)malloc(FunctionKeys[i] . sb_Len + 5))
  2530.                                 sprintf((char *)ToolTypes[j++],"F%02d=%s",i + 1,FunctionKeys[i] . sb_Buffer);
  2531.                         }
  2532.                     }
  2533.  
  2534.                         /* Terminate the tool type array. */
  2535.  
  2536.                     ToolTypes[j] = NULL;
  2537.  
  2538.                         /* Were we started from Workbench? */
  2539.  
  2540.                     if(WBenchMsg)
  2541.                     {
  2542.                         if(NewOS)
  2543.                         {
  2544.                                 /* Get the program directory. */
  2545.  
  2546.                             if(NameFromLock(WBenchMsg -> sm_ArgList[0] . wa_Lock,TempBuffer,MAX_FILENAME_LENGTH))
  2547.                             {
  2548.                                     /* Add the file name. */
  2549.  
  2550.                                 if(!AddPart(TempBuffer,WBenchMsg -> sm_ArgList[0] . wa_Name,MAX_FILENAME_LENGTH))
  2551.                                     strcpy((char *)TempBuffer,WBenchMsg -> sm_ArgList[0] . wa_Name);
  2552.                             }
  2553.                             else
  2554.                                 strcpy((char *)TempBuffer,WBenchMsg -> sm_ArgList[0] . wa_Name);
  2555.                         }
  2556.                         else
  2557.                             strcpy((char *)TempBuffer,WBenchMsg -> sm_ArgList[0] . wa_Name);
  2558.                     }
  2559.                     else
  2560.                     {
  2561.                         if(NewOS)
  2562.                         {
  2563.                                 /* Get the program name. */
  2564.  
  2565.                             if(!GetProgramName(TempBuffer,MAX_FILENAME_LENGTH))
  2566.                                 strcpy((char *)TempBuffer,"pinfo");
  2567.                         }
  2568.                         else
  2569.                             strcpy((char *)TempBuffer,"pinfo");
  2570.                     }
  2571.  
  2572.                         /* Fill in the icon data. */
  2573.  
  2574.                     Icon -> do_DefaultTool    = (char *)TempBuffer;
  2575.                     Icon -> do_ToolTypes    = (char **)ToolTypes;
  2576.                     Icon -> do_StackSize    = ThisProcess -> pr_StackSize;
  2577.                     Icon -> do_CurrentX    = NO_ICON_POSITION;
  2578.                     Icon -> do_CurrentY    = NO_ICON_POSITION;
  2579.  
  2580.                         /* Create the icon. */
  2581.  
  2582.                     if(!PutDiskObject((char *)filenm,Icon))
  2583.                         scr_putmesg("Error creating icon file",TRUE);
  2584.  
  2585.                         /* Free the tool type entries. */
  2586.  
  2587.                     for(i = 1 ; i < j ; i++)
  2588.                         free(ToolTypes[i]);
  2589.  
  2590.                         /* Free the tool type array. */
  2591.  
  2592.                     free(ToolTypes);
  2593.                 }
  2594.             }
  2595.             else
  2596.                 scr_putmesg("No icon",FALSE);
  2597.  
  2598.             break;
  2599.  
  2600.                 /* Close a restored game file? */
  2601.  
  2602.         case SF_RESTORE:
  2603.  
  2604.                 /* Get the file icon. */
  2605.  
  2606.             if(IconBase)
  2607.             {
  2608.                 if(Icon = GetDiskObject((char *)filenm))
  2609.                 {
  2610.                     char     Buffer[5],
  2611.                         *Type;
  2612.                     int     i;
  2613.  
  2614.                         /* Does it have a filetype info attached? */
  2615.  
  2616.                     if(Type = FindToolType((STRPTR *)Icon -> do_ToolTypes,"FILETYPE"))
  2617.                     {
  2618.                             /* Is it a bookmark file? */
  2619.  
  2620.                         if(MatchToolValue(Type,"BOOKMARK") && MatchToolValue(Type,"ITF"))
  2621.                         {
  2622.                                 /* Check for function key
  2623.                                  * defintions and set them
  2624.                                  * if approriate.
  2625.                                  */
  2626.  
  2627.                             for(i = 0 ; i < NUM_FKEYS ; i++)
  2628.                             {
  2629.                                     /* Build fkey string. */
  2630.  
  2631.                                 sprintf(Buffer,"F%02d",i + 1);
  2632.  
  2633.                                     /* See if we can find it. */
  2634.  
  2635.                                 if(Type = FindToolType((STRPTR *)Icon -> do_ToolTypes,Buffer))
  2636.                                     ConSetKey(i,Type,strlen(Type));
  2637.                                 else
  2638.                                     ConSetKey(i,"",0);
  2639.                             }
  2640.                         }
  2641.                     }
  2642.                 }
  2643.                 else
  2644.                     scr_putmesg("No icon",FALSE);
  2645.             }
  2646.             else
  2647.                 scr_putmesg("No icon",FALSE);
  2648.  
  2649.             break;
  2650.  
  2651.         /* Close a script file? */
  2652.  
  2653.     case SF_SCRIPT:
  2654.  
  2655.                 /* Clear the script file pointer. */
  2656.  
  2657.             ScriptFile = NULL;
  2658.  
  2659.                 /* Release auxilary padding buffers. */
  2660.  
  2661.             ScriptPadCleanup();
  2662.  
  2663.                 /* Determine file name length. */
  2664.  
  2665.             Len = strlen(filenm);
  2666.  
  2667.                 /* Is this a file or a device name? */
  2668.  
  2669.             if(filenm[Len - 1] != ':')
  2670.             {
  2671.                     /* Clear the executable bit. */
  2672.  
  2673.                 SetProtection((STRPTR)filenm,FIBF_EXECUTE);
  2674.  
  2675.                     /* Try to read the story file icon. */
  2676.  
  2677.                 if(IconBase)
  2678.                 {
  2679.                     if(NewOS)
  2680.                     {
  2681.                         char *Name;
  2682.  
  2683.                             /* Try to locate the story file location... */
  2684.  
  2685.                         if(Name = ConLocateStory("",StoryName))
  2686.                             Icon = GetDiskObject(Name);
  2687.                     }
  2688.  
  2689.                         /* If everything else fails,
  2690.                          * try the default.
  2691.                          */
  2692.  
  2693.                     if(!Icon)
  2694.                         Icon = GetDiskObject("Story.Data");
  2695.                 }
  2696.  
  2697.                     /* Did we get one? */
  2698.  
  2699.                 if(Icon)
  2700.                 {
  2701.                     STATIC char *ToolTypes[] =
  2702.                     {
  2703.                         "FILETYPE=TEXT|ASCII",
  2704.                         NULL
  2705.                     };
  2706.  
  2707.                         /* Set up the default information. */
  2708.  
  2709.                     Icon -> do_DefaultTool    = "SYS:Utilities/More";
  2710.                     Icon -> do_ToolTypes    = ToolTypes;
  2711.                     Icon -> do_StackSize    = 8192;
  2712.                     Icon -> do_CurrentX    = NO_ICON_POSITION;
  2713.                     Icon -> do_CurrentY    = NO_ICON_POSITION;
  2714.  
  2715.                         /* Create the icon. */
  2716.  
  2717.                     if(!PutDiskObject((char *)filenm,Icon))
  2718.                         scr_putmesg("Error creating icon file",TRUE);
  2719.                 }
  2720.                 else
  2721.                     scr_putmesg("No icon",FALSE);
  2722.             }
  2723.  
  2724.             if(NewOS)
  2725.             {
  2726.                 struct MenuItem *Item;
  2727.  
  2728.                     /* Block the menu strip. */
  2729.  
  2730.                 ConLockMenus();
  2731.  
  2732.                     /* Change the `Script...' menu item
  2733.                      * according to the current scripting
  2734.                      * settings.
  2735.                      */
  2736.  
  2737.                 Item = ItemAddress(Menu,FULLMENUNUM(MENU_PROJECT,PROJECTMENU_SCRIPT,NOSUB));
  2738.  
  2739.                 Item -> Flags &= ~CHECKED;
  2740.  
  2741.                     /* Enable the menu strip again. */
  2742.  
  2743.                 ConUnlockMenus();
  2744.             }
  2745.  
  2746.             break;
  2747.     }
  2748.  
  2749.         /* Release the icon data. */
  2750.  
  2751.     if(Icon)
  2752.         FreeDiskObject(Icon);
  2753. }
  2754.