/*-- AutoRev header do NOT edit!
*
*   Program         :   event.c
*   Copyright       :   © 1991 Jaba Development
*   Author          :   Jan van den Baard
*   Creation Date   :   21-Apr-91
*   Current version :   1.0
*   Translator      :   DICE v2.6
*
*   REVISION HISTORY
*
*   Date          Version         Comment
*   ---------     -------         ------------------------------------------
*   21-Apr-91     1.0             View keyboard event-handler + subs.
*
*-- REV_END --*/

#include "view.h"

/*
 * All kinds of qualifier-key combinations.
 */
#define MOUSE           IEQUALIFIER_RELATIVEMOUSE
#define REPEAT          IEQUALIFIER_REPEAT
#define LOCK            IEQUALIFIER_CAPSLOCK
#define NUMPAD          IEQUALIFIER_NUMERICPAD
#define LSHIFT          IEQUALIFIER_LSHIFT
#define RSHIFT          IEQUALIFIER_RSHIFT
#define CONTROL         IEQUALIFIER_CONTROL

#define NORM1           MOUSE
#define NORM2           NORM1+REPEAT
#define NORM3           NORM1+LOCK
#define NORM4           NORM2+LOCK

#define NUMP1           MOUSE+NUMPAD
#define NUMP2           NUMP1+REPEAT
#define NUMP3           NUMP1+LOCK
#define NUMP4           NUMP2+LOCK

#define CTRL1           MOUSE+CONTROL
#define CTRL2           CTRL1+REPEAT
#define CTRL3           CTRL1+LOCK
#define CTRL4           CTRL2+LOCK

#define PRIN1           CTRL1+LSHIFT
#define PRIN2           CTRL3+LSHIFT

#define SHIF1           MOUSE+LSHIFT
#define SHIF2           MOUSE+RSHIFT
#define SHIF3           SHIF1+REPEAT
#define SHIF4           SHIF2+REPEAT
#define SHIF5           SHIF1+LOCK
#define SHIF6           SHIF2+LOCK
#define SHIF7           SHIF3+LOCK
#define SHIF8           SHIF4+LOCK

/*
 * hot-keys to be pressed together with LALT+LAMIGA
 * when view is taking a nap.
 */
#define VIEW            0x34
#define QUIT            0x10
#define FLUSH           0x23

/*
 * some external referenced globals.
 */
extern APTR           ConsoleDevice;
extern ULONG          VW_class;
extern UWORD          VW_qual, VW_code, VW_pmark;
extern UWORD          VW_mode, VW_pmode, VW_printing, VW_err;
extern UBYTE          ClearStr[];
extern struct Screen *VW_scr;

/*
 * some external referenced function proto-types.
 */
extern __regargs void Quit( long );
extern __regargs void Inform( char *);
extern void LineUp( void );
extern void LineDown( void );
extern void DisplayText( void );
extern void Top( void );
extern void Bottom( void );
extern void PageUp( void );
extern void PageDown( void );
extern __regargs void LoadFile( long );
extern void Help( void );
extern void DoFound( void );
extern __regargs void GetSomething( ULONG );
extern void FindN( void );
extern void FindP( void );
extern void PrintFile( void );
extern __regargs void Sleep( BOOL );
extern void InfoLine( void );
extern void EditFile( void );
extern __regargs void SetMark( UWORD );
extern __regargs void UnSetMark( UWORD );
extern __regargs void JumpMark( UWORD );

/*
 * some local proto-types.
 */
void ConvertKeyTab( void );
__regargs void HandleKeyboard( UWORD, UWORD );
__regargs void SteadyRepeat( struct MsgPort * );
__regargs long HandleMsg( struct MsgPort * );
__regargs void ClearMsg( struct MsgPort * );
/*
 * "__stkargs" because it uses the stub routine
 * from "hstub.s" to set-up it's arguments on stack.
 */
__stkargs struct InputEvent *ViewHandler( struct InputEvent *, struct HandlerMuck * );

/*
 * Vanilla key-codes normal and shifted.
 */
UBYTE   KeyTable[64];
UBYTE   SKeyTable[64];

/*
 * Setup a key-table for normal and shifted key codes so
 * View will work with all kinds of foreigh key-mappings.
 */
void ConvertKeyTab()
{
    struct InputEvent ievent;
    UWORD i;

    setmem(&ievent,sizeof(struct InputEvent),0);

    ievent.ie_Class = IECLASS_RAWKEY;

    for(i=0;i<64;i++) {     /* build normal key-table */
        ievent.ie_Code = i;
        RawKeyConvert(&ievent,&KeyTable[i],1,NULL);
    }

    ievent.ie_Qualifier = LSHIFT;

    for(i=0;i<64;i++) {     /* build shifted key-table */
        ievent.ie_Code = i;
        RawKeyConvert(&ievent,&SKeyTable[i],1,NULL);
    }
}

/*
 * Prevent a overhead of RAWKEY message with
 * the REPEAT qualifier. It deletes all but one
 * RAWKEY messages with the REPEAT qualifier
 * set. The one REPEAT message left then get's
 * interpreted by the main loop. This ensures
 * that the text won't scroll more than one
 * page to far after the keys are released.
 */
__regargs void SteadyRepeat( port )
    struct MsgPort  *port;
{
    struct IntuiMessage *m1, *m2;

    Forbid();               /* don't race intuition */
    m1 = (struct IntuiMessage *)port->mp_MsgList.lh_Head;
    while(m2 = (struct IntuiMessage *)m1->ExecMessage.mn_Node.ln_Succ) {
        if(!m2->ExecMessage.mn_Node.ln_Succ)    break;
        if(m1->Class != IDCMP_RAWKEY)           break;
        if(!(m1->Qualifier & REPEAT))           break;
        if(m2->Class != IDCMP_RAWKEY)           break;
        if(!(m2->Qualifier & REPEAT))           break;
        ReplyMsg(GetMsg(port));
        m1 = (struct IntuiMessage *)port->mp_MsgList.lh_Head;
    }
    Permit();
}

/*
 * Get and interpred a message from the port.
 * return TRUE if there was a message received
 * or FALSE if not.
 */
__regargs long HandleMsg( struct MsgPort *port )
{
    struct IntuiMessage *msg;

    if((msg = GT_GetIMsg(port))) { /* gotten a message! */
        VW_class = msg->Class;
        VW_code  = msg->Code;
        VW_qual  = msg->Qualifier;
        GT_ReplyIMsg(msg);         /* gadtools is open so why not... */
        return TRUE;
    }
    return FALSE;
}

/*
 * Reply all pending messages on the msgport
 * without doing something with them.
 */
__regargs void ClearMsg( struct MsgPort *port )
{
    struct IntuiMessage *msg;

    Forbid(); /* don't race intuition. */
    while(msg = GT_GetIMsg(port)) GT_ReplyIMsg(msg);
    Permit();
}

/*
 * This is the input-handler which, if active, looks for
 * wake-up signals. This routine uses the hard-coded keyboard
 * layout instead of the "Vanilla one".
 */
__stkargs __geta4 struct InputEvent *ViewHandler( struct InputEvent *event, struct HandlerMuck *data)
{
    struct InputEvent *ev;

    for(ev = event; ev; ev = ev->ie_NextEvent) {
        if(ev->ie_Class == IECLASS_RAWKEY) { /* only RAWKEY events */
            if((ev->ie_Qualifier & IEQUALIFIER_LALT) &&
               (ev->ie_Qualifier & IEQUALIFIER_LCOMMAND)) {
                switch(ev->ie_Code) { /* look what key was used */
                    case VIEW:
                        ev->ie_Class = IECLASS_NULL;
                        data->View  = TRUE;
                        data->Quit  = FALSE;
                        data->Flush = FALSE;
                        goto SigIT;
                        break;
                    case QUIT:
                        ev->ie_Class = IECLASS_NULL;
                        data->View  = FALSE;
                        data->Quit  = TRUE;
                        data->Flush = FALSE;
                        goto SigIT;
                        break;
                    case FLUSH:
                        ev->ie_Class = IECLASS_NULL;
                        data->View  = FALSE;
                        data->Quit  = FALSE;
                        data->Flush = TRUE;
SigIT:                  Signal(data->ViewTask,data->ViewSigMask);
                        break;
                    default:
                        break;
                }
            }
        }
    }
    return(event);
}

/*
 * Handle all incoming RAWKEY messages.
 */
__regargs void HandleKeyboard( code, qualifier )
    UWORD           code, qualifier;
{
    if((code & IECODE_UP_PREFIX) != IECODE_UP_PREFIX) { /* only key-down */
        if(VW_err)  InfoLine(); /* refresh info line if needed */
        switch(qualifier) {

            case NORM1:
            case NORM2:
            case NORM3:
            case NORM4:  /* normal key without qualifier keys */
                if(code < 64) {
                    switch(KeyTable[code]) { /* keymap keys */

                        case 'h':
                            Help();
                            break;
                        case 'q':
                            if(!VW_printing) Quit( RETURN_OK );
                            break;
                        case '/':
                        case 'f':
                            VW_mode = TRUE;
                            GetSomething(STRING_KIND);
                            break;
                        case '.':
                        case 's':
                            VW_mode = FALSE;
                            GetSomething(STRING_KIND);
                            break;
                        case 'n':
                            VW_mode = TRUE;
                            FindN();
                            break;
                        case 'p':
                            VW_mode = TRUE;
                            FindP();
                            break;
                        case 'r':
                            Inform(ClearStr);
                            DisplayText();
                            break;
                        case 'e':
                            EditFile();
                            break;
                        case 'l':
                            if(!VW_printing) LoadFile(TRUE);
                            break;
                        case 'j':
                            DoFound();
                            break;
                        case 'b':
                            if(!VW_printing) Sleep(FALSE);
                            break;
                        default:
                            break;
                    }
                } else if(code >= 0x50 && code <= 0x59) { /* function keys */
                    SetMark((UWORD)(code - 0x50));
                    break;
                } else {
                    switch(code) { /* RAW keys (the same on any Amiga..?) */
                        case 0x40: /* Space bar  */
                            PageDown();
                            break;
                        case 0x41: /* BackSpace  */
                            PageUp();
                            break;
                        case 0x4d: /* Down arrow */
                        case 0x44: /* Return     */
                            LineDown();
                            break;
                        case 0x4c: /* Up arrow   */
                            LineUp();
                            break;
                        case 0x5f: /* Help       */
                            Help();
                            break;
                        case 0x45: /* Esc        */
                            if(!VW_printing) Quit( RETURN_OK );
                            break;
                        default:
                            break;
                    }
                }
                break;
            case NUMP1:
            case NUMP2:
            case NUMP3:
            case NUMP4: /* Numeric key-pad */
                if(code < 64) { /* keymap keys */
                    switch(KeyTable[code]) {

                        case '7':
                        case '4':
                            Top();
                            break;
                        case '1':
                        case '6':
                            Bottom();
                            break;
                        case '8':
                            LineUp();
                            break;
                        case '2':
                            LineDown();
                            break;
                        case '9':
                            PageUp();
                            break;
                        case '3':
                            PageDown();
                            break;
                        default:
                            break;
                    }
                } else if(code == 0x43) { /* Enter */
                    LineUp();
                    break;
                }
                break;
            case CTRL1:
            case CTRL2:
            case CTRL3:
            case CTRL4: /* key with CTRL */
                if(code < 64) { /* keymap keys */
                    switch(KeyTable[code]) {

                        case 'c':
                            if(!VW_printing) Quit( RETURN_OK );
                            break;
                        case 'n':
                            VW_mode = FALSE;
                            FindN();
                            break;
                        case 'p':
                            VW_mode = FALSE;
                            FindP();
                            break;
                        case 'l':
                            Inform(ClearStr);
                            DisplayText();
                            break;
                        case 'b':
                            if(!VW_printing) Sleep(TRUE);
                            break;
                        default:
                            break;
                    }
                } else if(code >= 0x50 && code <= 0x59) { /* Function keys */
                    JumpMark((UWORD)(code - 0x50));
                    break;
                }
                break;
            case PRIN1:
            case PRIN2: /* LEFT_SHIFT + CONTROL + key */
                if(code < 64) { /* keymap keys */
                    switch(KeyTable[code]) {

                        case 'd':
                            if(!VW_printing) {
                                VW_pmode = PRT_PAGE;
                                PrintFile();
                            }
                            break;
                        case 'p':
                            if(!VW_printing) {
                                VW_pmode = PRT_FILE;
                                PrintFile();
                            }
                            break;
                        default:
                            break;
                    }
                } else if(code >= 0x50 && code <= 0x59) { /* Function keys */
                    VW_pmode = PRT_BLOCK;
                    VW_pmark = (UWORD)(code - 0x50);
                    PrintFile();
                    break;
                }
                break;
            case SHIF1:
            case SHIF2:
            case SHIF3:
            case SHIF4:
            case SHIF5:
            case SHIF6:
            case SHIF7:
            case SHIF8: /* SHIFT + key */
                if(code < 64) { /* keymap key */
                    switch(SKeyTable[code]) {

                        case '<':
                            Top();
                            break;
                        case '>':
                            Bottom();
                            break;
                        case '%':
                            GetSomething(INTEGER_KIND);
                            break;
                        default:
                            break;
                    }
                } else if(code >= 0x50 && code <= 0x59) { /* Function keys */
                    UnSetMark((UWORD)(code - 0x50));
                    break;
                }
            default:
                break;
            }
        }
    }
}
