/*
 * DOS interrupt 16h handler
 */

#include <stdlib.h>
#include <string.h>
#include <unistd.h>

#include "config.h"
#include "module.h"
#include "dosexe.h"
#include "wincon.h"
#include "debugtools.h"
#include "windef.h"
#include "wingdi.h"
#include "winuser.h"
#include "miscemu.h"

DEFAULT_DEBUG_CHANNEL(int16);

/**********************************************************************
 *	    INT_Int16Handler
 *
 * Handler for int 16h (keyboard)
 *
 * NOTE:
 * 
 *    KEYB.COM (DOS >3.2) adds functions to this interrupt, they are
 *    not currently listed here.
 */

void WINAPI INT_Int16Handler( CONTEXT86 *context )
{
   switch AH_reg(context) {

   case 0x00: /* Get Keystroke */
      /* Returns: AH = Scan code
                  AL = ASCII character */   
      TRACE("Get Keystroke\n");
      INT_Int16ReadChar(&AL_reg(context), &AH_reg(context), FALSE);
      break;

   case 0x01: /* Check for Keystroke */
      /* Returns: ZF set if no keystroke */
      /*          AH = Scan code */
      /*          AL = ASCII character */
      TRACE("Check for Keystroke\n");
      if (!INT_Int16ReadChar(&AL_reg(context), &AH_reg(context), TRUE))
      {
          SET_ZFLAG(context);
      }
      else
      {
          RESET_ZFLAG(context);
      }
      break;

   case 0x02: /* Get Shift Flags */      
      AL_reg(context) = 0;

#if 0  /* FIXME: cannot call USER functions here */
      if (GetAsyncKeyState(VK_RSHIFT))
          AL_reg(context) |= 0x01;
      if (GetAsyncKeyState(VK_LSHIFT))
          AL_reg(context) |= 0x02;
      if (GetAsyncKeyState(VK_LCONTROL) || GetAsyncKeyState(VK_RCONTROL))
          AL_reg(context) |= 0x04;
      if (GetAsyncKeyState(VK_LMENU) || GetAsyncKeyState(VK_RMENU))
          AL_reg(context) |= 0x08;
      if (GetAsyncKeyState(VK_SCROLL))
          AL_reg(context) |= 0x10;
      if (GetAsyncKeyState(VK_NUMLOCK))
          AL_reg(context) |= 0x20;
      if (GetAsyncKeyState(VK_CAPITAL))
          AL_reg(context) |= 0x40;
      if (GetAsyncKeyState(VK_INSERT))
          AL_reg(context) |= 0x80;
#endif
      TRACE("Get Shift Flags: returning 0x%02x\n", AL_reg(context));
      break;

   case 0x03: /* Set Typematic Rate and Delay */
      FIXME("Set Typematic Rate and Delay - Not Supported\n");
      break;

   case 0x09: /* Get Keyboard Functionality */
      FIXME("Get Keyboard Functionality - Not Supported\n");
      /* As a temporary measure, say that "nothing" is supported... */
      AL_reg(context) = 0;
      break;

   case 0x0a: /* Get Keyboard ID */
      FIXME("Get Keyboard ID - Not Supported\n");
      break;

   case 0x10: /* Get Enhanced Keystroke */
      TRACE("Get Enhanced Keystroke - Partially supported\n");
      /* Returns: AH = Scan code
                  AL = ASCII character */   
      INT_Int16ReadChar(&AL_reg(context), &AH_reg(context), FALSE);
      break;
  

   case 0x11: /* Check for Enhanced Keystroke */
      /* Returns: ZF set if no keystroke */
      /*          AH = Scan code */
      /*          AL = ASCII character */
      TRACE("Check for Enhanced Keystroke - Partially supported\n");
      if (!INT_Int16ReadChar(&AL_reg(context), &AH_reg(context), TRUE))
      {
          SET_ZFLAG(context);
      }
      else
      {
          RESET_ZFLAG(context);
      }
      break;

   case 0x12: /* Get Extended Shift States */
      FIXME("Get Extended Shift States - Not Supported\n");
      break;
 
   default:
      FIXME("Unknown INT 16 function - 0x%x\n", AH_reg(context));   
      break;

   }
}

int WINAPI INT_Int16ReadChar(BYTE*ascii,BYTE*scan,BOOL peek)
{
  BIOSDATA *data = DOSMEM_BiosData();
  WORD CurOfs = data->NextKbdCharPtr;

  /* check if there's data in buffer */
  if (peek) {
    if (CurOfs == data->FirstKbdCharPtr)
      return 0;
  } else {
    while (CurOfs == data->FirstKbdCharPtr) {
      /* no input available yet, so wait... */
      DOSVM_Wait( -1, 0 );
    }
  }
  /* read from keyboard queue */
  TRACE("(%p,%p,%d) -> %02x %02x\n",ascii,scan,peek,((BYTE*)data)[CurOfs],((BYTE*)data)[CurOfs+1]);
  if (ascii) *ascii = ((BYTE*)data)[CurOfs];
  if (scan) *scan = ((BYTE*)data)[CurOfs+1];
  if (!peek) {
    CurOfs += 2;
    if (CurOfs >= data->KbdBufferEnd) CurOfs = data->KbdBufferStart;
    data->NextKbdCharPtr = CurOfs;
  }
  return 1;
}

int WINAPI INT_Int16AddChar(BYTE ascii,BYTE scan)
{
  BIOSDATA *data = DOSMEM_BiosData();
  WORD CurOfs = data->FirstKbdCharPtr;
  WORD NextOfs = CurOfs + 2;

  TRACE("(%02x,%02x)\n",ascii,scan);
  if (NextOfs >= data->KbdBufferEnd) NextOfs = data->KbdBufferStart;
  /* check if buffer is full */
  if (NextOfs == data->NextKbdCharPtr) return 0;

  /* okay, insert character in ring buffer */
  ((BYTE*)data)[CurOfs] = ascii;
  ((BYTE*)data)[CurOfs+1] = scan;

  data->FirstKbdCharPtr = NextOfs;
  return 1;
}
