/*
 * osdepend.c
 *
 * All non screen specific operating system dependent routines.
 *
 * Olaf Barthel 28-Jul-1992
 * Modified John Holder(jholder@nmsu.edu) 25-July-1995
 * Support for standalone storyfiles by Magnu Olsson (mol@df.lth.se) Nov.1995
 *
 */

#include "ztypes.h"
#include "jzexe.h"

/* File names will be O/S dependent */

#if defined(AMIGA)
#define SAVE_NAME   "Story.Save"   /* Default save name */
#define SCRIPT_NAME "PRT:"         /* Default script name */
#define RECORD_NAME "Story.Record" /* Default record name */
#else /* defined(AMIGA) */
#define SAVE_NAME   "story.sav"   /* Default save name */
#define SCRIPT_NAME "story.scr"   /* Default script name */
#define RECORD_NAME "story.rec"  /* Default record name */
#endif /* defined(AMIGA) */

#if !defined(AMIGA)

/* getopt linkages */

extern int optind;
extern const char *optarg;

#endif /* !defined(AMIGA) */



#if !defined(AMIGA)

/*
 * process_arguments
 *
 * Do any argument preprocessing necessary before the game is
 * started. This may include selecting a specific game file or
 * setting interface-specific options.
 *
 */

#ifdef __STDC__
void process_arguments (int argc, char *argv[])
#else
void process_arguments (argc, argv)
int argc;
char *argv[];
#endif
{
    int c, errflg = 0;
    int infoflag=0;
    int size;
    int expected_args;

    /* Parse the options */

    monochrome=0;
    hist_buf_size=1024;
    bigscreen=0;

    while ((c = getopt (argc, argv, "mbvhl:c:k:r:t:")) != EOF) {
	switch (c) {
	    case 'l': /* lines */
		screen_rows = atoi (optarg);
		break;
	    case 'c': /* columns */
		screen_cols = atoi (optarg);
		break;
	    case 'r': /* right margin */
		right_margin = atoi (optarg);
		break;
	    case 't': /* top margin */
		top_margin = atoi (optarg);
		break;
	    case 'k': /* number of K for hist_buf_size */
		size = atoi (optarg);
		hist_buf_size = (hist_buf_size>size) ? hist_buf_size:size;
		if (hist_buf_size>16384) hist_buf_size=16384;
		break;
	    case 'v': /* version information */

fprintf(stderr,"\nJZIP - An Infocom Z-code Interpreter Program \n");
fprintf(stderr,"       %s %s\n",JZIPVER,JZIPRELDATE);
if (STANDALONE_FLAG) {
fprintf(stderr,"       Standalone game: %s\n",argv[0]);
}
fprintf(stderr,"---------------------------------------------------------\n");
fprintf(stderr,"Author: John Holder (jholder@nmsu.edu)\n");
fprintf(stderr,"Based on ZIP 2.0 source code by Mark Howell\n\n");
fprintf(stderr,"Bugs: Please report bugs and portability bugs to the maintainer.");
fprintf(stderr,"\n\nInterpreter:\n\n");
fprintf(stderr,"\tThis interpreter will run all Infocom V1 to V5 games. It includes\n");
fprintf(stderr,"\tsupport for timeouts in Border Zone, screen displays in Beyond Zork\n");
fprintf(stderr,"\tand implements the #record debugging function, etc.\n\n");
fprintf(stderr,"\tThe patches allow this interpreter to correctly handle the form\n");
fprintf(stderr,"\tin Bureaucracy (on UNIX platforms), to generate slightly more\n");
fprintf(stderr,"\trandom numbers (eliminating a bug in Balances on UNIX platforms),\n");
fprintf(stderr,"\tand the interpreter can now play Inform V8 games, as described\n");
fprintf(stderr,"\tby Graham Nelson in Inform 5.5 beta's documentation.\n\n");
fprintf(stderr,"\tThis interpreter also supports command line editing.\n\n");
		infoflag++;
		break;
	    case 'm':
		monochrome=1;
		break;
	    case 'b':
		bigscreen=1;
		break;
	    case 'h':
	    case '?':
	    default:
		errflg++;
	}
    }

    if (infoflag) exit (EXIT_SUCCESS);

    if (STANDALONE_FLAG)
      expected_args=0;
    else
      expected_args=1;

    /* Display usage */

    if (errflg || optind+expected_args != argc) {

	if (STANDALONE_FLAG)
	  fprintf(stderr,"usage: %s [options...]\n\n",argv[0]);
	else
	  fprintf (stderr, "usage: %s [options...] story-file\n\n", argv[0]);

	fprintf (stderr, "JZIP - an Infocom story file interpreter.\n");
	fprintf (stderr, "      Version %s by John Holder\n",JZIPVER);
	fprintf (stderr, "      Based on ZIP V2.0 source by Mark Howell\n");
	fprintf (stderr, "      Plays type 1 to 5 and 8 Infocom games.\n\n");
	fprintf (stderr, "\t-l n lines in display\n");
	fprintf (stderr, "\t-c n columns in display\n");
	fprintf (stderr, "\t-r n text right margin (default = %d)\n", DEFAULT_RIGHT_MARGIN);
	fprintf (stderr, "\t-t n text top margin (default = %d)\n", DEFAULT_TOP_MARGIN);
	fprintf (stderr, "\t-k n set the size of the command history buffer to n bytes\n");
	fprintf (stderr, "\t     (Default is 1024 bytes.  Maximum is 16384 bytes.)\n");
	fprintf (stderr, "\t-v   display version information\n");
#if defined __MSDOS__
	fprintf (stderr, "\t-m   run in monochrome mode\n");
	fprintf (stderr, "\t-b   run in 43/50 line EGA/VGA mode\n");
#endif
	fprintf (stderr, "\n");
	exit (EXIT_FAILURE);
    }

    /* Open the story file */

    if (!STANDALONE_FLAG) /* mol 951115 */
      open_story (argv[optind]);
    else {
      /* standalone, ie. the .exe file _is_ the story file. */
      if (argv[0][0] ==0) {
	/* some OS's (ie DOS prior to v.3.0) don't supply the path to */
	/* the .exe file in argv[0]; in that case, we give up. (mol) */
	fatal("Sorry, this program will not run on this platform.");
      }
      open_story(argv[0]);
    }

}/* process_arguments */

#endif /* !defined(AMIGA) */

#if !defined(AMIGA)

/*
 * file_cleanup
 *
 * Perform actions when a file is successfully closed. Flag can be one of:
 * GAME_SAVE, GAME_RESTORE, GAME_SCRIPT.
 *
 */

#ifdef __STDC__
void file_cleanup (const char *file_name, int flag)
#else
void file_cleanup (file_name, flag)
const char *file_name;
int flag;
#endif
{

}/* file_cleanup */

#endif /* !defined(AMIGA) */

#if !defined(AMIGA)

/*
 * sound
 *
 * Play a sound file or a note.
 *
 * argc = 1: argv[0] = note# (range 1 - 3)
 *
 *           Play note.
 *
 * argc = 2: argv[0] = 0
 *           argv[1] = 3
 *
 *           Stop playing current sound.
 *
 * argc = 2: argv[0] = 0
 *           argv[1] = 4
 *
 *           Free allocated resources.
 *
 * argc = 3: argv[0] = ID# of sound file to replay.
 *           argv[1] = 2
 *           argv[2] = Volume to replay sound with, this value
 *                     can range between 1 and 8.
 *
 * argc = 4: argv[0] = ID# of sound file to replay.
 *           argv[1] = 2
 *           argv[2] = Control information
 *           argv[3] = Volume information
 *
 *           Volume information:
 *
 *               0x34FB -> Fade sound in
 *               0x3507 -> Fade sound out
 *               other  -> Replay sound at maximum volume
 *
 *           Control information:
 *
 *               This word is divided into two bytes,
 *               the upper byte determines the number of
 *               cycles to play the sound (e.g. how many
 *               times a clock chimes or a dog barks).
 *               The meaning of the lower byte is yet to
 *               be discovered :)
 *
 */

#ifdef __STDC__
void sound (int argc, zword_t *argv)
#else
void sound (argc, argv)
int argc;
zword_t *argv;
#endif
{

    /* Supply default parameters */

    if (argc < 4)
	argv[3] = 0;
    if (argc < 3)
	argv[2] = 0xff;
    if (argc < 2)
	argv[1] = 2;

    /* Generic bell sounder */

    if (argc == 1 || argv[1] == 2)
	display_char ('\007');

}/* sound */

#endif /* !defined(AMIGA) */

/*
 * get_file_name
 *
 * Return the name of a file. Flag can be one of:
 *    GAME_SAVE    - Save file (write only)
 *    GAME_RESTORE - Save file (read only)
 *    GAME_SCRIPT  - Script file (write only)
 *    GAME_RECORD  - Keystroke record file (write only)
 *    GAME_PLABACK - Keystroke record file (read only)
 *
 */

#ifdef __STDC__
int get_file_name (char *file_name, char *default_name, int flag)
#else
int get_file_name (file_name, default_name, flag)
char *file_name;
char *default_name;
int flag;
#endif
{
    char buffer[127 + 2]; /* 127 is the biggest positive char */
    int status = 0;

    /* If no default file name then supply the standard name */

    if (default_name[0] == '\0') {
	if (flag == GAME_SCRIPT)
	    strcpy (default_name, SCRIPT_NAME);
	else if (flag == GAME_RECORD || flag == GAME_PLAYBACK)
	    strcpy (default_name, RECORD_NAME);
	else /* (flag == GAME_SAVE || flag == GAME_RESTORE) */
	    strcpy (default_name, SAVE_NAME);
    }

    /* Prompt for the file name */

    output_line ("Enter a file name.");
    output_string ("(Default is \"");
    output_string (default_name);
    output_string ("\"): ");

    buffer[0] = 127;
    buffer[1] = 0;
    (void) get_line (buffer, 0, 0);

    /* Copy file name from the input buffer */

    strcpy (file_name, (h_type > V4) ? &buffer[2] : &buffer[1]);

    /* If nothing typed then use the default name */

    if (file_name[0] == '\0')
	strcpy (file_name, default_name);

#if !defined(VMS) /* VMS has file version numbers, so cannot overwrite */

    /* Check if we are going to overwrite the file */

    if (flag == GAME_SAVE || flag == GAME_SCRIPT || flag == GAME_RECORD) {
	FILE *tfp;
	char c;

	/* Try to access the file */

	tfp = fopen (file_name, "r");
	if (tfp != NULL) {
	    fclose (tfp);

	    /* If it succeeded then prompt to overwrite */

	    output_line ("You are about to write over an existing file.");
	    output_string ("Proceed? (Y/N) ");

	    do {
		c = (char) input_character (0);
		c = (char) toupper (c);
	    } while (c != 'Y' && c != 'N');

	    output_char (c);
	    output_new_line ();

	    /* If no overwrite then fail the routine */

	    if (c == 'N')
		status = 1;
	}
    }
#endif /* !defined(VMS) */

    /* Record the file name if it was OK */

    if (status == 0)
	record_line (file_name);

    return (status);

}/* get_file_name */

#if !defined(AMIGA)

/*
 * fatal
 *
 * Display message and stop interpreter.
 *
 */

#ifdef __STDC__
void fatal (const char *s)
#else
void fatal (s)
const char *s;
#endif
{

    reset_screen ();
    fprintf (stderr,"\nFatal error: %s (PC = %lx)\n", s, pc);
    exit (1);

}/* fatal */

#endif /* !defined(AMIGA) */

#if !defined(AMIGA)

/*
 * fit_line
 *
 * This routine determines whether a line of text will still fit
 * on the screen.
 *
 * line : Line of text to test.
 * pos  : Length of text line (in characters).
 * max  : Maximum number of characters to fit on the screen.
 *
 */

#ifdef __STDC__
int fit_line (const char *line_buffer, int pos, int max)
#else
int fit_line (line_buffer, pos, max)
const char *line_buffer;
int pos;
int max;
#endif
{

    return (pos < max);

}/* fit_line */

#endif /* !defined(AMIGA) */

#if !defined(AMIGA)

/*
 * print_status
 *
 * Print the status line (type 3 games only).
 *
 * argv[0] : Location name
 * argv[1] : Moves/Time
 * argv[2] : Score
 *
 * Depending on how many arguments are passed to this routine
 * it is to print the status line. The rendering attributes
 * and the status line window will be have been activated
 * when this routine is called. It is to return FALSE if it
 * cannot render the status line in which case the interpreter
 * will use display_char() to render it on its own.
 *
 * This routine has been provided in order to support
 * proportional-spaced fonts.
 *
 */

#ifdef __STDC__
int print_status (int argc, char *argv[])
#else
int print_status (argc, argv)
int argc;
char *argv[];
#endif
{

    return (FALSE);

}/* print_status */

#endif /* !defined(AMIGA) */

#if !defined(AMIGA)

/*
 * set_font
 *
 * Set a new character font. Font can be either be:
 *
 *    TEXT_FONT (1)     = normal text character font
 *    GRAPHICS_FONT (3) = graphical character font
 *
 */

#ifdef __STDC__
void set_font (int font_type)
#else
void set_font (font_type)
int font_type;
#endif
{

}/* set_font */

#endif /* !defined(AMIGA) */

#if !defined(MSDOS) && !defined(AMIGA) &&!defined(HARD_COLORS) &&!defined(ATARIST)

/*
 * set_colours
 *
 * Sets screen foreground and background colours.
 *
 */

#ifdef __STDC__
void set_colours (zword_t foreground, zword_t background)
#else
void set_colours (foreground, background)
zword_t foreground;
zword_t background;
#endif
{

}/* set_colours */

#endif /* !defined(MSDOS) && !defined(AMIGA) */

#if !defined(VMS) && !defined(MSDOS)

/*
 * codes_to_text
 *
 * Translate Z-code characters to machine specific characters. These characters
 * include line drawing characters and international characters.
 *
 * The routine takes one of the Z-code characters from the following table and
 * writes the machine specific text replacement. The target replacement buffer
 * is defined by MAX_TEXT_SIZE in ztypes.h. The replacement text should be in a
 * normal C, zero terminated, string.
 *
 * Return 0 if a translation was available, otherwise 1.
 *
 *  Arrow characters (0x18 - 0x1b):
 *
 *  0x18 Up arrow
 *  0x19 Down arrow
 *  0x1a Right arrow
 *  0x1b Left arrow
 *
 *  International characters (0x9b - 0xa3):
 *
 *  0x9b a umlaut (ae)
 *  0x9c o umlaut (oe)
 *  0x9d u umlaut (ue)
 *  0x9e A umlaut (Ae)
 *  0x9f O umlaut (Oe)
 *  0xa0 U umlaut (Ue)
 *  0xa1 sz (ss)
 *  0xa2 open quote (>>)
 *  0xa3 close quota (<<)
 *
 *  Line drawing characters (0xb3 - 0xda):
 *
 *  0xb3 vertical line (|)
 *  0xba double vertical line (#)
 *  0xc4 horizontal line (-)
 *  0xcd double horizontal line (=)
 *  all other are corner pieces (+)
 *
 */

#ifdef __STDC__
int codes_to_text (int c, char *s)
#else
int codes_to_text (c, s)
int c;
char *s;
#endif
{

}/* codes_to_text */

#endif /* !defined(VMS) && !defined(MSDOS) */
