/*
 * DOS interrupt 09h handler (IRQ1 - KEYBOARD)
 *
 * Copyright 1999 Ove Kåven
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
 */

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

#include "windef.h"
#include "winbase.h"
#include "wingdi.h"
#include "winuser.h"
#include "wine/debug.h"
#include "dosexe.h"

WINE_DEFAULT_DEBUG_CHANNEL(int);

#define QUEUELEN 31

static struct
{
  BYTE queuelen,queue[QUEUELEN],ascii[QUEUELEN];
} kbdinfo;


/*
 * Update the BIOS data segment's keyboard status flags (mem 0x40:0x17/0x18)
 * if modifier/special keys have been pressed.
 * FIXME: we merely toggle key status and don't actively set it instead,
 * so we might be out of sync with the real current system status of these keys.
 * Probably doesn't matter too much, though.
 */
static void DOSVM_Int09UpdateKbdStatusFlags(BYTE scan, BOOL extended, BIOSDATA *data, BOOL *modifier)
{
    BYTE realscan = scan & 0x7f; /* remove 0x80 make/break flag */
    BYTE bit1 = 255, bit2 = 255;
    INPUT_RECORD msg;
    DWORD res;

    *modifier = TRUE;

    switch (realscan)
    {
      case 0x36: /* r shift */
	      bit1 = 0;
	      break;
      case 0x2a: /* l shift */
	      bit1 = 1;
	      break;
      case 0x1d: /* l/r control */
	      bit1 = 2;
	      if (!extended) /* left control only */
		  bit2 = 0;
	      break;
      case 0x37: /* SysRq inner parts */
	      /* SysRq scan code sequence: 38, e0, 37, e0, b7, b8 */
	      FIXME("SysRq not handled yet.\n");
	      break;
      case 0x38: /* l/r menu/alt, SysRq outer parts */
	      bit1 = 3;
	      if (!extended) /* left alt only */
	          bit2 = 1;
	      break;
      case 0x46: /* scroll lock */
	      bit1 = 4;
	      if (!extended) /* left ctrl only */
	          bit2 = 4;
	      break;
      case 0x45: /* num lock, pause */
	      if (extended) /* distinguish from non-extended Pause key */
              { /* num lock */
	          bit1 = 5;
	          bit2 = 5;
              }
	      else
              { /* pause */
                  if (!(scan & 0x80)) /* "make" code */
                      bit2 = 3;
              }
	      break;
      case 0x3a: /* caps lock */
	      bit1 = 6;
	      bit2 = 6;
	      break;
      case 0x52: /* insert */
	      bit1 = 7;
	      bit2 = 7;
	      *modifier = FALSE; /* insert is no modifier: thus pass to int16 */
	      break;
    }
    /* now that we know which bits to set, update them */
    if (!(scan & 0x80)) /* "make" code (keypress) */
    {
        if (bit2 != 255)
        {
	    if (bit2 == 3)
	    {
                data->KbdFlags2 |= 1 << bit2; /* set "Pause" flag */
                TRACE("PAUSE key, sleeping !\n");
                /* wait for keypress to unlock pause */
		do {
                    Sleep(55);
		} while (!(ReadConsoleInputA(GetStdHandle(STD_INPUT_HANDLE),&msg,1,&res) && (msg.EventType == KEY_EVENT)));
                data->KbdFlags2 &= ~(1 << bit2); /* release "Pause" flag */
            }
	    else
                data->KbdFlags2 |= 1 << bit2;
        }
        if (bit1 != 255)
        {
            if (bit1 < 4) /* key "pressed" flag */
	        data->KbdFlags1 |= 1 << bit1;
            else /* key "active" flag */
                data->KbdFlags1 ^= 1 << bit1;
        }
    }
    else /* "break" / release */
    {
        if (bit2 != 255)
            data->KbdFlags2 &= ~(1 << bit2);
        if (bit1 < 4) /* is it a key "pressed" bit ? */
	    data->KbdFlags1 &= ~(1 << bit1);
    }
    TRACE("ext. %d, bits %d/%d, KbdFlags %02x/%02x\n", extended, bit1, bit2, data->KbdFlags1, data->KbdFlags2);
}

/**********************************************************************
 *	    DOSVM_Int09Handler
 *
 * Handler for int 09h.
 * See http://www.execpc.com/~geezer/osd/kbd/ for a very good description
 * of keyboard mapping modes.
 */
void WINAPI DOSVM_Int09Handler( CONTEXT86 *context )
{
  BIOSDATA *data = DOSVM_BiosData();
  BYTE ascii, scan = DOSVM_Int09ReadScan(&ascii);
  BYTE realscan = scan & 0x7f; /* remove 0x80 make/break flag */
  BOOL modifier = FALSE;
  static BOOL extended = FALSE; /* indicates start of extended key sequence */
  BYTE ch[2];
  int cnt, c2;

  TRACE("scan=%02x, ascii=%02x[%c]\n",scan, ascii, ascii ? ascii : ' ');

  if (scan == 0xe0) /* extended keycode */
      extended = TRUE;
  
  /* check for keys concerning keyboard status flags */
  if ((realscan == 0x52 /* insert */)
  ||  (realscan == 0x3a /* caps lock */)
  ||  (realscan == 0x45 /* num lock (extended) or pause/break */)
  ||  (realscan == 0x46 /* scroll lock */)
  ||  (realscan == 0x2a /* l shift */)
  ||  (realscan == 0x36 /* r shift */)
  ||  (realscan == 0x37 /* SysRq */)
  ||  (realscan == 0x38 /* l/r menu/alt, SysRq */)
  ||  (realscan == 0x1d /* l/r control */))
      DOSVM_Int09UpdateKbdStatusFlags(scan, extended, data, &modifier);

  if (scan != 0xe0)
      extended = FALSE; /* reset extended flag now */

  /* only interested in "make" (press) codes, not "break" (release),
   * and also not in "modifier key only" (w/o ascii) notifications */
  if (!(scan & 0x80) && !(modifier && !ascii))
  {
    if (ascii) {
      /* we already have an ASCII code, no translation necessary */
      if (data->KbdFlags1 & 8) /* Alt key ? */
	ch[0] = 0; /* ASCII code needs to be 0 if Alt also pressed */
      else
        ch[0] = ascii;
      /* FIXME: need to handle things such as Shift-F1 etc. */
      cnt = 1;
    } else {
      /* translate */
      UINT vkey = MapVirtualKeyA(scan&0x7f, 1);
      BYTE keystate[256];
      GetKeyboardState(keystate);
      cnt = ToAscii(vkey, scan, keystate, (LPWORD)ch, 0);
    }
    if (cnt>0) {
      for (c2=0; c2<cnt; c2++)
        DOSVM_Int16AddChar(ch[c2], scan);
    } else
    if (cnt==0) {
      /* FIXME: need to handle things like shift-F-keys,
       * 0xE0 extended keys, etc */
      DOSVM_Int16AddChar(0, scan);
    }
  }

  DOSVM_AcknowledgeIRQ( context );
}

static void KbdRelay( CONTEXT86 *context, void *data )
{
  if (kbdinfo.queuelen) {
    /* cleanup operation, called from DOSVM_PIC_ioport_out:
     * we'll remove current scancode from keyboard buffer here,
     * rather than in ReadScan, because some DOS apps depend on
     * the scancode being available for reading multiple times... */
    if (--kbdinfo.queuelen) {
      memmove(kbdinfo.queue,kbdinfo.queue+1,kbdinfo.queuelen);
      memmove(kbdinfo.ascii,kbdinfo.ascii+1,kbdinfo.queuelen);
    }
  }
}

void DOSVM_Int09SendScan( BYTE scan, BYTE ascii )
{
  if (kbdinfo.queuelen == QUEUELEN) {
    ERR("keyboard queue overflow\n");
    return;
  }
  /* add scancode to queue */
  kbdinfo.queue[kbdinfo.queuelen] = scan;
  kbdinfo.ascii[kbdinfo.queuelen++] = ascii;
  /* tell app to read it by triggering IRQ 1 (int 09) */
  DOSVM_QueueEvent(1,DOS_PRIORITY_KEYBOARD,KbdRelay,NULL);
}

BYTE DOSVM_Int09ReadScan( BYTE*ascii )
{
    if (ascii) *ascii = kbdinfo.ascii[0];
    return kbdinfo.queue[0];
}
