
/*
   Defs for the new io stuff.
*/

/* 
   If we had something resembling real object oriented programming tools,
   we could do something reasonable here, ie flavorize it, and use real
   methods, with type inheritance, before and after methods, etc.  As is, 
   all that's available is C or C++.  Sigh.
*/

/* flags that appear in a streamoid's 'flags' short */
#define STR_OPEN_P	0x0001		/* open-p */
#define STR_AT_EOF_P	0x0002		/* if it's been read up to eof */
#define STR_BUFFERED_P	0x0004		/* if this streamoid has a buffer */
#define STR_FORCE_P	0x0008		/* force after output op */
#define STR_TEXT_P	0x0010		/* do text translation */
#define STR_INPUT_P	0x0020		/* can be read from */
#define STR_OUTPUT_P	0x0040		/* can be written to */
#define STR_UNTYIED_P	0x0080		/* there's an untyied char */
#define STR_BUF_DIRTY_P	0x0100		/* buffer is dirty, only used
					   in bidirectional direct access */
#define STR_BUF_READ_P	0x0200		/* handle needs to be re-seeked
					   before writing, if buf-dirty-p.
					   only used in bidir direct access */
#define STR_INTERACTIVE_P 0x0400	/* this is an interactive streamoid */
#define STR_NOCLOSE_P	0x0800		/* don't close this streamoid on exit,
					   just force output of it */

/* basic methods, callable from application level stuff */
#define METHOD_CLOSE	0		/* close this streamoid */
#define METHOD_TYI	1		/* get a byte/char */
#define METHOD_UNTYI	2		/* push one back */
#define METHOD_TYO	3		/* put one */
#define METHOD_READL	4		/* read a line */
#define METHOD_WRITEL	5		/* write a line */
#define METHOD_READBUF	6		/* read a buffer of n bytes */
#define METHOD_WRITEBUF	7		/* ... */
#define METHOD_SEEK	8		/* seek this streamoid */
#define METHOD_INFO	9		/* get info, stream_specific */

/*
   internal methods, called from other methods.  So far, these
   are only used for buffered streamoids
*/
#define METHOD_GETBUF	10		/* fill next buffer */
#define METHOD_PUTBUF	11		/* put this buffer */
#define METHOD_SEEK_I	12		/* do internal work of seeking */
#define METHOD_CLOSE_I	13		/* do internal work of close */

#define METHODS_UNBUFFERED 10		/* n bethods for unbuffered streamoid */
#define METHODS_BUFFERED 14		/* n methods for buffered streamoid */

typedef int (* method_fun)();

/*
   info structure types
*/
#define INF_UNDEF	0		/* undefined */
#define INF_CONSOLE	1		/* ST console */
/* #define INF_FILE	2		/* file stream */

struct console_info_block
	{
	short * linea;			/* the system's linea block */
	short maxx;			/* max xpos */
	short maxy;			/* max ypos */
	short curx;			/* current xpos */
	short cury;			/* current ypos */
	};

/*
   the basic streamoid structure.  NB!  this structure doesn't work
   very well for bidirectional streams like network streams.  It is
   ok for file streams, though; guess we'll do another implementation
   for other kinds of streams later...
*/
struct streamoid
	{
	unsigned short	flags;		/* various state flags */
	unsigned long	file_position;	/* nbytes read/writ in file */
	int		last_error;	/* last err code encountered */
	short		untyied_char;	/* char untyied, if any */
	short		gemdos_handle;	/* handle for gemdos */
	short		n_methods;	/* n elts in method vector */
	method_fun *	method;		/* method vector */
	/* the following fields are only used if we have a buffered streamoid */
	unsigned long	buffer_pos;	/* position in file this buf belongs */
	unsigned long	buffer_index;	/* index into buf, if buffered */
	unsigned long	buffer_size;	/* total buf size */
	unsigned long	buffer_nbytes;	/* nbytes in buffer now */
	unsigned char *	buffer;		/* buffer if any */
	/* maybe add ptr to extra args here, for windows? */
	};

/* the way we call methods */
static inline int method_call_0(self, meth)
struct streamoid * self;
int meth;
{
  if ((self->n_methods > meth) /* && (self->method[meth]) */ )
	return(*self->method[meth])(self);
}

/* where are &rest args when you need them??? */
static inline int method_call_1(self, meth, arg)
struct streamoid * self;
int meth;
long arg;
{
  if ((self->n_methods > meth) /* && (self->method[meth]) */ )
	return(*self->method[meth])(self, arg);
}

static inline int method_call_2(self, meth, arg1, arg2)
struct streamoid * self;
int meth;
long arg1, arg2;
{
  if ((self->n_methods > meth) /* && (self->method[meth]) */ )
	return(*self->method[meth])(self, arg1, arg2);
}

/* forward defs for functions */

extern method_fun * __clone_method_vector();
extern struct streamoid * __make_stream();
extern void __close_all_streamoids();

/* another step in the struggle to make C less incomprehensible */
#define local static

#define DEFMETHOD int


/* random things */

#define EOF_VALUE	-1
extern int errno;		/* compatibility for antique eunuchs s/w */

/* kludge to allow us to compile internal things while still providing
   prototypes for the outside world to use. */
#ifndef FILE
#define FILE struct streamoid
#endif
