#ifndef RAWIN_H
#define RAWIN_H

/*  $Filename: RawIN.h $
**  $Release: 1.2 $
**  $Date: August 21, 1994 $
**  $Author: Sam Yee (samy@sfu.ca | 1:153/765) $
**
**  Header file for RawIN.lib
**
**  Freely redistributable if this file is unmodified.
*/

#include <exec/types.h>
#include <dos/dosextens.h>
#include <dos/dos.h>

#define REG(x)          register __ ## x
#define ASM             __asm

#define RAWIN_NAME  "rawin.library" /* name of library */

/*
*********************************************************************
** structures
*********************************************************************
*/

struct Line
{
    UBYTE           *buf,           /* buffer for command line */
                    lastchar,       /* last input character */
                    InputChar;      /* incoming character */
    UWORD           flags;          /* flags, look below */
    ULONG           bufindex,       /* index into buf */
                    buflen,         /* length of current command line */
                    bufmax,         /* max length of buffer */
                    hist_linesmax,  /* maximum number of history lines */
                    hist_linecount, /* as of right now, the number of lines */
                    hist_lineindex; /* current history line */
    struct History  *hist_head,     /* first history line */
                    *hist_tail;     /* last history line */
    struct MsgPort  *ReadReplyPort; /* input handler talks to us through here */
    struct StandardPacket   read_packet; /* for packet reads */

    /* new for 1.2 */
    LONG            hist_lownum;    /* lowest history number in list */
    BPTR            InputStream,    /* ADOS file handle, default Input()/Output() */
                    OutputStream;   /* if NULL, all i/o functions will be ignored */
        /* output callback stuff */
    LONG    (*callback)(APTR,UBYTE *,LONG);  /* output callback function, you set it! */
    APTR    callback_io_block;      /* io block ptr for callback() function */
    LONG    callback_result;        /* result of call will be stored here */
        /* callback_result = callback(callback_io_block,buf,buflen)
                             buf = character buffer, buflen = buffer length */
    UBYTE           *BreakStr,      /* string to display when ^C has been hit,
                                       default is ***Break, NULL for none */
                    *PauseStr,      /* string to display when RI_PauseKey() is called
                                       and user presses the pause key
                                       default is [PAUSED], NULL for none */
                    *no_str,        /* The string No, used by RI_AskNoYes() and
                                       RI_AskYesNo() */
                    *yes_str;       /* The string Yes, used by the same routines */
    LONG            tab_spaces,     /* number of characters per tab, if 0 no tabs.
                                       default 8. */
                    prompt_len,     /* length of your prompt */
                    no_key,         /* key to cause RI_AskNoYes() to return TRUE */
                    yes_key;        /* key to cause RI_AskYesNo() to return TRUE */
    struct MsgPort  *WriteReplyPort; /* input handler talks to us through here */
    struct StandardPacket   write_packet; /* for packet writes */
    APTR            write_buffer;   /* copied from RI_StartWriteRequest */
    LONG            write_length;   /* likewise */
};

#define LNF_ANSI        (1<<0)  /* user's terminal support ANSI control codes?
                                   you may set this flag, else CSI sets it */
#define LNF_CSI         (1<<1)  /* control sequence introducer seen. */
#define LNF_RAWMODE     (1<<2)  /* if on, we are in raw mode. */
#define LNF_STARTEDREAD (1<<3)  /* if on, we've requested a read. *read only* */
#define LNF_EOF         (1<<4)  /* if on, end-of-file on InputStream. *read only* */
#define LNF_BREAKC      (1<<5)  /* I've received a signal C (break) */
#define LNF_STARTEDWRITE (1<<6) /* if on, we've requested a write. *read only* */
#define LNF_READERROR   (1<<7)  /* read error */
#define LNF_WRITEERROR  (1<<8)  /* write error */

/* history node */
struct History
{
    struct History  *last,  /* previous history line */
                    *next;  /* next history line */
    UBYTE           *buf;   /* buffer of the history line */
    ULONG           buflen; /* length of this history line */
};


/*******************************************************************/
#ifdef RAWIN_RUNTIME
/*
** Startup/cleanup/init routines
*/

struct Line *       /* returns allocated Line structure, NULL == failure */
RI_AllocLine(ULONG buf_size,   /* size of input buffer to allocate */
             ULONG hist_size); /* number of history lines */

void    /* de-allocate a Line structure */
RI_FreeLine(struct Line *line);

void    /* reset a Line (eg. initialize the indices, etc.) */
RI_ResetLine(struct Line *line);

/*
** Misc. routines
*/

/* set stdout to raw mode */
void
RI_SetMode(struct Line *line,      /* line allocated with AllocLine() */
           BOOL        raw);       /* TRUE == rawmode, FALSE == cooked mode */

/* start the next raw read */
void
RI_SendReadRequest(struct Line *line);

void
RI_SendWriteRequest(struct Line *line,
                    APTR        buffer,  /* what to write */
                    LONG        length); /* how much to write,
                                            -1L == use strlen(buffer) */

BOOL    /* returns non-zero if user has pressed CR or LF */
RI_BuildLine(struct Line   *line,      /* line to build */
             LONG          max_chars,  /* # of characters for this command line,
                                          -1 == default */
             BOOL          echo);      /* if TRUE, output changes to command line */

BOOL /* check for a keypress.  if TRUE, a key has been typed */
RI_KeyPressed(struct Line *line);


BOOL /* write completed? */
RI_WriteDone(struct Line *line);

void
RI_WaitWrite(struct Line *line);

/*
** History routines
*/

void
RI_AddHistory(struct Line *line,
              UBYTE       *buf,       /* history buffer to add */
              LONG        max_chars); /* length of buffer to add, if -1 use default (strlen()) */

struct History *    /* returns pointer to History, else NULL on failure */
RI_GetHistory(struct Line  *line,      /* line to get history from */
              LONG         num);       /* history line # */

void
RI_ShowHistory(struct Line *line,
               LONG        hist_start, /* start listing history lines from this location,
                                          1 is the beginning, -1 is the end. */
               LONG        hist_lines, /* # of history lines to display, -1L == all */
               BOOL        reverse);   /* if TRUE then reverse order of output */

void
RI_DeleteHistory(struct Line   *line,  /* line to delete history*/
                 LONG          num);   /* history # to delete, 1 is the first, -1 is the last */


/*
** Input routines
*/

LONG /* -1L == read unsuccessful due to EOL or break.
        0L == user only pressed return, else the # of chars read */
RI_Gets(struct Line     *line,
        UBYTE           *buf,     /* buffer to store command line, if NULL use line->buf */
        ULONG           buflen,   /* length of buffer */
        ULONG           defsize,  /* default size of buffer to display */
        BOOL            hot,      /* hotkey if true, returns when a key is hit. */
        BOOL            caps,     /* CAPS if true */
        BOOL            echo);    /* if TRUE, output keypresses */

LONG    /* key user pressed, else -1 */
RI_PauseKey(struct Line    *line,
            LONG           pause_key,      /* key to press to go into paused mode. -1 is any */
            LONG           unpause_key);   /* key to press to return from pause mode. -1 is any */

LONG    /* if greater than or equal to 0 then the user has typed a character */
RI_GetKey(struct Line *line,
          BOOL        caps,   /* if TRUE, capitalize input */
          BOOL        echo);  /* if TRUE, echo input */

LONG    /* if greater than or equal to 0 then the user has typed a character,
           else read line->flag for reason. */
RI_WaitKey(struct Line    *line,
           BOOL           caps,   /* if TRUE, capitalize input */
           BOOL           echo);  /* if TRUE, echo input */

BOOL /* did user select No? */
RI_AskNoYes(struct Line    *line,
            BOOL           verbose);   /* Display Yes/No accordingly? */

BOOL /* did user select Yes? */
RI_AskYesNo(struct Line    *line,
            BOOL           verbose);   /* Display Yes/No accordingly? */

LONG /* number of characters read, 0 for none */
RI_GetBlock(struct Line *line,
            BOOL        caps,   /* if TRUE, capitalize input */
            BOOL        echo,   /* if TRUE, echo input */
            void        *buffer, /* location to store input */
            LONG        length); /* maximum we can read */


#pragma libcall RawINBase RI_AllocLine 1E 1002
#pragma libcall RawINBase RI_FreeLine 24 801
#pragma libcall RawINBase RI_ResetLine 2A 801
#pragma libcall RawINBase RI_SetMode 30 0802
#pragma libcall RawINBase RI_SendReadRequest 36 801
#pragma libcall RawINBase RI_BuildLine 3C 10803
#pragma libcall RawINBase RI_KeyPressed 42 801
#pragma libcall RawINBase RI_AddHistory 48 19803
#pragma libcall RawINBase RI_GetHistory 4E 0802
#pragma libcall RawINBase RI_ShowHistory 54 210804
#pragma libcall RawINBase RI_DeleteHistory 5A 0802
#pragma libcall RawINBase RI_Gets 60 543219807
#pragma libcall RawINBase RI_GetKey 66 10803
#pragma libcall RawINBase RI_WaitKey 6C 10803
#pragma libcall RawINBase RI_PauseKey 72 10803
#pragma libcall RawINBase RI_AskNoYes 78 0802
#pragma libcall RawINBase RI_AskYesNo 7E 0802
#pragma libcall RawINBase RI_GetBlock 84 2A10805
#pragma libcall RawINBase RI_SendWriteRequest 8A 19803
#pragma libcall RawINBase RI_WriteDone 90 801
#pragma libcall RawINBase RI_WaitWrite 96 801

/*******************************************************************/

#else /* we want to the linked library includes */

/*******************************************************************/
/* initialization/exit routines */
ASM struct Line *       /* returns allocated Line structure, NULL == failure */
RI_AllocLine(REG(d0)   ULONG buf_size,   /* size of input buffer to allocate */
             REG(d1)   ULONG hist_size); /* number of history lines */

ASM void                /* de-allocate a Line structure */
RI_FreeLine(REG(a0)    struct Line *line);

ASM void                /* reset a Line (eg. initialize the indices, etc.) */
RI_ResetLine(REG(a0)   struct Line *line);

/*
** Misc. routines
*/

/* set stdout to raw mode */
ASM void
RI_SetMode(REG(a0) struct Line *line,   /* line allocated with AllocLine */
           REG(d0) BOOL        raw);    /* TRUE == rawmode, FALSE == cooked mode */

/* start the next raw read */
ASM void
RI_SendReadRequest(REG(a0)  struct Line *line);

/* start the next write */
ASM void
RI_SendWriteRequest(REG(a0) struct Line *line,
                    REG(a1) APTR        buffer,  /* what to write */
                    REG(d1) LONG        length); /* how much to write */

ASM BOOL    /* returns non-zero if user has pressed CR or LF */
RI_BuildLine(REG(a0)   struct Line   *line,      /* line to build */
             REG(d0)   LONG          max_chars,  /* # of characters for this command line,
                                                    -1 == default */
             REG(d1)   BOOL          echo);      /* if TRUE, output changes to command line */

ASM BOOL /* check for a keypress.  if TRUE, a key has been typed */
RI_KeyPressed(REG(a0)  struct Line *line);


ASM BOOL /* write completed? */
RI_WriteDone(REG(a0)  struct Line *line);

ASM void
RI_WaitWrite(REG(a0)  struct Line *line);


/*
** History routines
*/

ASM void
RI_AddHistory(REG(a0) struct Line *line,
              REG(a1) UBYTE       *buf,         /* history buffer to add */
              REG(d1) LONG        max_chars);   /* length of buffer to add,
                                                   if -1 use default (strlen()) */

ASM struct History *    /* returns pointer to History, else NULL on failure */
RI_GetHistory(REG(a0)  struct Line  *line,      /* line to get history from */
              REG(d0)  LONG         num);       /* history line # */

ASM void
RI_ShowHistory(REG(a0) struct Line *line,
               REG(d0) LONG        hist_start, /* start listing history lines from this location,
                                                  1 is the beginning, -1 is the end. */
               REG(d1) LONG        hist_lines, /* # of history lines to display, -1L == all */
               REG(d2) BOOL        reverse);   /* if TRUE then reverse order of output */

ASM void
RI_DeleteHistory(REG(a0)   struct Line   *line,  /* line to delete history*/
                 REG(d0)   LONG          num);   /* history # to delete, 1 is the first,
                                                    -1 is the last */


/*
** Input routines
*/

ASM LONG /* -1L == read unsuccessful due to EOL or ^C break.
            0L == user only pressed return, else the # of chars read */
RI_Gets(REG(a0) struct Line *line,
        REG(a1) UBYTE       *buf,       /* buffer to store command line,
                                           if NULL use line->buf */
        REG(d1) ULONG       buflen,     /* length of buffer */
        REG(d2) ULONG       defsize,    /* default size of buffer to display */
        REG(d3) BOOL        hot,        /* hotkey if true, returns when a key is hit. */
        REG(d4) BOOL        caps,       /* CAPS if true */
        REG(d5) BOOL        echo);      /* if TRUE, output keypresses */

ASM LONG    /* key user pressed, else -1 */
RI_PauseKey(REG(a0) struct Line    *line,
            REG(d0) LONG           pause_key,       /* key to press to go into paused mode.
                                                       -1 is any */
            REG(d1) LONG           unpause_key);   /* key to press to return from pause mode.
                                                      -1 is any */

ASM LONG    /* if greater than or equal to 0 then the user has typed a character, else error */
RI_GetKey(REG(a0) struct Line *line,
          REG(d0) BOOL        caps,     /* if TRUE, capitalize input */
          REG(d1) BOOL        echo);    /* if TRUE, echo input */

ASM LONG    /* if greater than 0 then the user has typed a character, else read line->flag
               for reason. */
RI_WaitKey(REG(a0) struct Line  *line,
           REG(d0) BOOL         caps,   /* if TRUE, capitalize input */
           REG(d1) BOOL         echo);  /* if TRUE, echo input */

ASM BOOL /* did user select No? */
RI_AskNoYes(REG(a0) struct Line *line,
            REG(d0) BOOL        verbose);   /* Display Yes/No accordingly? */

ASM BOOL /* did user select Yes? */
RI_AskYesNo(REG(a0) struct Line    *line,
            REG(d0) BOOL           verbose);   /* Display Yes/No accordingly? */

ASM LONG /* number of characters read, 0 for none */
RI_GetBlock(REG(a0) struct Line *line,
            REG(d0) BOOL        caps,   /* if TRUE, capitalize input */
            REG(d1) BOOL        echo,   /* if TRUE, echo input */
            REG(a2) void        *buffer, /* location to store input */
            REG(d2) LONG        length); /* maximum we can read */

#endif  /* RAWIN_RUNTIME */

/*******************************************************************/
#endif  /* RAWIN_H */
