| home | contents | previous | next page | send comment | send link | add bookmark |

input.cpp

/*-------------------------------------------------------------------------*
    INPUT.CPP

    console input module

    by:  Stephen R. Schmitt
 *-------------------------------------------------------------------------*/

#include <bios.h>
#include <conio.h>
#include <dos.h>
#include <stdio.h>
#include "input.h"

/*-------------------------------------------------------------------------*
 *  "input" is the class constructor.  It determines whether a mouse driver
 *  is installed and how  many buttons the mouse has.
 *
 *  returns:  nothing
 */
input::input()
{
    union REGS ireg;

    ireg.x.ax = 0x00;
    int86( 0x33, &ireg, &ireg );

    buttons = ireg.x.bx;
    present = ireg.x.ax;
    delta   = 20;
}

/*-------------------------------------------------------------------------*
 *  "mouse_reset" restores the mouse.  It is mainly used when a program
 *  disables the mouse by writing to the comm port used by the mouse.
 *
 *  returns:  nothing
 */
void input::mouse_reset()
{
    union REGS ireg;

    ireg.x.ax = 0x00;
    int86( 0x33, &ireg, &ireg );

    buttons = ireg.x.bx;
    present = ireg.x.ax;
    delta   = 20;
}

/*-------------------------------------------------------------------------*
 *  "mouse_cursor_on" toggles the mouse cursor on. The funtion maintains
 *  an internal counter that determines whether the cursor is on; if the
 *  counter is 0, the cursor is on.  By calling this function and
 *  function 0x02, the mouse cursor is switched between on and off.
 *
 *  returns:  nothing
 */
void input::mouse_cursor_on()
{
    union REGS ireg;

    ireg.x.ax = 0x01;
    int86(0x33, &ireg, &ireg);
}

/*-------------------------------------------------------------------------*
 *  "mouse_cursor_off" toggles the mouse cursor off. The function
 *  decrements the internal cursor counter.  Calls to mouse_cursor_on()
 *  and mouse_cursor_off() should be alternated for things to work
 *  properly.
 *
 *  returns:  nothing
 */
void input::mouse_cursor_off()
{
    union REGS ireg;

    ireg.x.ax = 0x02;
    int86(0x33, &ireg, &ireg);
}

/*-------------------------------------------------------------------------*
 *  "set_mouse" sets the mouse position.  The new values must fall within
 *  the row-column ranges that have been set.  When in the text mode,
 *  values are rounded to the nearest values permitted.
 *
 *  returns:  nothing
 */
void input::set_mouse( int x,                   // new column
                       int y )                  // new row
{
    union REGS ireg;

    ireg.x.ax = 0x04;
    ireg.x.cx = x * 8;
    ireg.x.dx = y * 8;
    int86( 0x33, &ireg, &ireg );
}

/*------------------------------------------------------------------------*
 *  "mouse_move" enables reading the mouse row-col counters.
 *  Each unit represents about .01 inch and has the range of a signed
 *  int (about plus/minus 32000).  Note that the values returned
 *  represent the changes in the counts since the last call.
 *
 *  returns:  nothing
 */
void input::mouse_move( int *x,                 // col count
                        int *y )                // row count
{
    union REGS ireg;

    ireg.x.ax = 0x0b;
    int86(0x33, &ireg, &ireg);
    *x = ireg.x.cx;
    *y = ireg.x.dx;
}


/*-------------------------------------------------------------------------*
 *  "read_mouse" obtains the mouse's position and status.  On return from
 *  the interrupt, the following information is available:
 *
 *  ireg.x.bx  =  button status, where bits 0 and 1 are for the
 *                left and right buttons. If the button is pressed,
 *                the bit is 1. If there is a middle button, it
 *                uses bit 2.
 *
 *  ireg.x.cx  =  horizontal cursor position
 *  ireg.x.dx  =  vertical cursor position
 *
 *  returns:  nothing
 */
void input::read_mouse( int *x,                 // column of mouse cursor
                        int *y,                 // row of mouse cursor
                        int *button )           // status bits
{
    union REGS reg;

    reg.x.ax = 0x03;
    int86( 0x33, &reg, &reg );
    *button = reg.x.bx;
    *x = reg.x.cx;
    *y = reg.x.dx;
}

/*-------------------------------------------------------------------------*
 *  "post_key" puts a key press message into the keyboard buffer.
 *
 *  WARNING:  The keyboard buffer can hold up to 15 messages and no more.
 *
 *  returns:  nothing
 */
void input::post_key( int key )                 // the key
{
    struct REGPACK reg;

    reg.r_ax = 0x05 << 8;                       // shift 05h into AH
    reg.r_cx = key;
    intr( 0x16, &reg );
}

/*-------------------------------------------------------------------------*
 *  "xbios_key" returns extended keyboard code for each user key press.
 *
 *  returns:  integer corresponding to key.
 */
int input::xbios_key( int op )                  // operation selector
{
    struct REGPACK reg;

    switch( op )
    {
    case 0:                                     // get next key
        reg.r_ax = 0x10 << 8;                   // shift 10h into AH
        intr( 0x16, &reg );
        return( reg.r_ax );

    case 1:                                     // check for key available
        reg.r_ax = 0x11 << 8;                   // shift 11h into AH
        intr( 0x16, &reg);
        if( reg.r_flags & 64 )                  // zero flag at 40h
            return( 0 );
        else
            return( reg.r_ax );

    case 2:                                     // get special key states
        reg.r_ax = 0x12 << 8;                   // shift 12h into AH
        intr( 0x16, &reg);
        return( reg.r_ax );
    }
}

/*-------------------------------------------------------------------------*
 *  "message" reads the keyboard and mouse for user input.  This is
 *  the user input to the system.
 *
 *  returns:  message type code; 
 *            mod indicates whether shift, ctrl, or alt was pressed
 */
unsigned int input::message( int *mod,          // keyboard modifier
                             int *code,         // message
                             int *ampl )        // message amplifier
{
    union { int word; unsigned char ch[2]; } key;
    int button, msg, mx, my;

    *mod = 0;

    if( present )
    {
        while( 1 )
        {
            read_mouse( &mx, &my, &button );
            if( button == 0 )
                break;
        }
    }

    while( 1 )
    {
        if( present )
        { 
            read_mouse( &mx, &my, &button );

            *code = mx / 8;
            *ampl = my / 8;

            if( button == 1 )
                return MSG_MOUSE_LF;
            else if( button == 2 )
                return MSG_MOUSE_RT;
            else if( button == 4 )
                return MSG_MOUSE_MD;

            mouse_move( &mx, &my );
            if( mx || my )
            {
                *code = mx / 8;
                *ampl = my / 8;
                return MSG_MOUSE_MOVE;
            }
        }

#ifndef DEBUG_INPUT

        key.word = xbios_key( 1 );              // poll the keyboard
        if( key.word == 0 )
            continue;                           // no key press
        else
#endif
            key.word = xbios_key( 0 );

        *mod = xbios_key( 2 );

        if( key.ch[0] == 224 || key.ch[0] == 0 )
        {
            *code = key.ch[1] + MAX_ASCII;
            msg = MSG_FUNCTION;
        }
        else if( key.ch[0] )
        {
            if( *mod & MOD_CTRL )
            {
                *code = key.ch[0] + CTRL_LETTER;
                msg = MSG_FUNCTION;
            }
            else
            {
                *code = key.ch[0];
                msg = MSG_CHARACTER;
            }
        }

        break;
    }

    return( msg );
}

| home | contents | previous | next page | send comment | send link | add bookmark |

Copyright © 2004, Stephen R. Schmitt