Mail Archives: djgpp/1997/04/26/09:59:34
From: | boylesgj AT lion DOT cs DOT latrobe DOT edu DOT au (Gregary J Boyles)
|
Newsgroups: | comp.os.msdos.djgpp
|
Subject: | Function locking problem (for ISR).
|
Date: | 26 Apr 1997 12:22:16 GMT
|
Organization: | Comp.Sci & Comp.Eng, La Trobe Uni, Australia
|
Lines: | 2432
|
Distribution: | world
|
Message-ID: | <5jss1o$alv@lion.cs.latrobe.edu.au>
|
NNTP-Posting-Host: | lion.cs.latrobe.edu.au
|
To: | djgpp AT delorie DOT com
|
DJ-Gateway: | from newsgroup comp.os.msdos.djgpp
|
Excuse the size of the file below - you can ignore most of it.
Down near the bottom of the file there is a function called DoLocking
which calls Allego style macros for locking code and data. It causes a
general protection fault because if I comment it out the problem
disappears. Any sugestions?
#define START_FUNC(x) void x##_start(){}
#define END_FUNC(x) void x##_end(){}
#define LOCK_FUNC(x) _go32_dpmi_lock_code(x##_start,(long)x##_end-(long)x##_start);
#define LOCK_DATA(x) _go32_dpmi_lock_data(x,sizeof(x));
#include <dos.h>
#include <iostream.h>
#include <stdlib.h>
#include "string.hh"
#include "misc.hh"
//#define DEBUG
/****************************************************************************/
/* */
/* CLASS NAME : TimeC */
/* */
/* PURPOSE : Stores a time i.e. hour, minute, second and hundredths of */
/* seconds and contains a function to determine the elapsed time */
/* (in hundredths of seconds). */
/* */
/****************************************************************************/
class TimeC
{
private:
/************************/
/* PRIVATE DATA MEMBERS */
/************************/
unsigned char Hour,Minute,Second,Second100;
public:
/********************/
/* PUBLIC FUNCTIONS */
/********************/
// Constructor.
TimeC();
// Destructor.
~TimeC();
// Calculates the elapsed time between this and the specified time.
long unsigned int operator -(TimeC &Time);
// Sets the data members.
void Set(unsigned char Hour_,unsigned char Minute_,unsigned char Second_,unsigned char Second100_);
};
// Constructor.
START_FUNCTION(Func1);
TimeC::TimeC()
{
Hour=Minute=Second=Second100=0;
}
END_FUNCTION(Func1);
// Destructor.
START_FUNCTION(Func2);
TimeC::~TimeC()
{
Hour=Minute=Second=Second100=0;
}
END_FUNCTION(Func2);
// Sets the data members.
START_FUNCTION(Func3);
void TimeC::Set(unsigned char Hour_,unsigned char Minute_,unsigned char Second_,unsigned char Second100_)
{
Hour=Hour_;
Minute=Minute_;
Second=Second_;
Second100=Second100_;
}
END_FUNCTION(Func3);
// Calculates the elapsed time between this and the specified time.
START_FUNCTION(Func4);
long unsigned int TimeC::operator -(TimeC &Time)
{
long int HundSec1,HundSec2;
HundSec1=(Hour*60*60*100)+(Minute*60*100)+(Second*100)+Second100;
HundSec2=(Time.Hour*60*60*100)+(Time.Minute*60*100)+(Time.Second*100)+Time.Second100;
return labs(HundSec1-HundSec2);
}
END_FUNCTION(Func4);
/****************************************************************************/
/* */
/* CLASS NAME : EventC */
/* */
/* PURPOSE : Stores the details of an input event and contains functions for*/
/* manipulating the data members. */
/* */
/****************************************************************************/
typedef enum {Mouse,KeyBoard} MouseOrKeyBoardE;
typedef enum {Left,Center,Right} WhichMouseKeyE;
typedef enum {Pressed,Released} WhatHappenedE;
class EventC
{
public:
/***********************/
/* PUBLIC DATA MEMBERS */
/***********************/
// What type of event.
MouseOrKeyBoardE Type;
// For key board events.
unsigned char ASCII;
unsigned int ScanCode;
// For mouse events.
WhichMouseKeyE MouseKey;
// Was the key pressed or released.
WhatHappenedE What;
// Status of state shift keys.
bool Alt,Ctrl,Shift,CapsLock,NumLock,ScrollLock;
// Position of the mouse.
unsigned int MouseX,MouseY;
// Time stamp.
TimeC Time;
// Pointer to another event.
EventC *Next;
/********************/
/* PUBLIC FUNCTIONS */
/********************/
// Constructor.
EventC();
// Desstructor.
~EventC();
// Copy function
void operator =(EventC &Event);
};
// Constructor.
START_FUNCTION(Func5);
EventC::EventC():Time()
{
Type=KeyBoard;
ScanCode=ASCII=0;
MouseKey=Left;
What=Pressed;
Alt=Ctrl=Shift=CapsLock=NumLock=ScrollLock=false;
MouseX=MouseY=0;
Next=NULL;
}
END_FUNCTION(Func5);
// Desstructor.
START_FUNCTION(Func6);
EventC::~EventC()
{
Type=KeyBoard;
ScanCode=ASCII=0;
MouseKey=Left;
What=Pressed;
Alt=Ctrl=Shift=CapsLock=NumLock=ScrollLock=false;
MouseX=MouseY=0;
Next=NULL;
}
END_FUNCTION(Func6);
// Copy function
START_FUNCTION(Func7);
void EventC::operator =(EventC &Event)
{
Type=Event.Type;
ScanCode=Event.ScanCode;
ASCII=Event.ASCII;
MouseKey=Event.MouseKey;
What=Event.What;
Alt=Event.Alt;
Ctrl=Event.Ctrl;
Shift=Event.Shift;
CapsLock=Event.CapsLock;
NumLock=Event.NumLock;
ScrollLock=Event.ScrollLock;
MouseX=Event.MouseX;
MouseY=Event.MouseY;
Next=NULL;
}
END_FUNCTION(Func7);
/****************************************************************************/
/* */
/* CLASS NAME : EventQueueC */
/* */
/* PURPOSE : Implements a circular queue data structure which is used to */
/* store and provide external access to input events. */
/* */
/****************************************************************************/
class EventQueueC
{
private:
/************************/
/* PRIVATE DATA MEMBERS */
/************************/
// Pointer to the last event in the queue.
EventC *Last;
// The current number and maximum number of events stored.
int Num,Max;
public:
/********************/
/* PUBLIC FUNCTIONS */
/********************/
// Constructor.
EventQueueC();
// Destructor.
~EventQueueC();
// Is the queue empty?
bool Empty();
// Is the queue full?
bool Full();
// Is there one event left in the queue.
bool OneOnly();
// Adds an event to the queue.
bool Enqueue(EventC &Event);
// Removes an event from the queue.
bool Dequeue(EventC &Event);
// Copies the first event on the queue but doesn't remove it.
bool Peek(EventC &Event);
};
// Constructor.
START_FUNCTION(Func8);
EventQueueC::EventQueueC()
{
Last=NULL;
Max=50;
Num=0;
}
END_FUNCTION(Func8);
// Destructor.
START_FUNCTION(Func9);
EventQueueC::~EventQueueC()
{
EventC Event;
while (!Empty())
Dequeue(Event);
Max=0;
}
END_FUNCTION(Func9);
// Is the queue empty?
START_FUNCTION(Func10);
bool EventQueueC::Empty()
{
return Num==0;
}
END_FUNCTION(Func10);
// Is the queue full?
START_FUNCTION(Func11);
bool EventQueueC::Full()
{
return Num==Max;
}
END_FUNCTION(Func11);
// Is there one event left in the queue.
START_FUNCTION(Func12);
bool EventQueueC::OneOnly()
{
return Num==1;
}
END_FUNCTION(Func12);
// Adds an event to the queue.
START_FUNCTION(Func13);
bool EventQueueC::Enqueue(EventC &Event)
{
bool OK=false;
EventC *Temp=NULL;
if (!Full())
{
Temp=new EventC;
*Temp=Event;
Num++;
OK=true;
if (Empty())
{
Temp->Next=Temp;
Last=Temp;
}
else
{
Temp->Next=Last->Next;
Last->Next=Temp;
}
}
return OK;
}
END_FUNCTION(Func13);
// Removes an event from the queue.
START_FUNCTION(Func14);
bool EventQueueC::Dequeue(EventC &Event)
{
EventC *Temp=NULL;
bool OK=false;
if (!Empty())
{
Temp=Last->Next;
Num--;
OK=true;
Event=*Temp;
if (OneOnly())
{
Last=NULL;
}
else
{
Last->Next=Temp->Next;
}
delete Temp;
}
return OK;
}
END_FUNCTION(Func14);
// Copies the first event on the queue but doesn't remove it.
START_FUNCTION(Func15);
bool EventQueueC::Peek(EventC &Event)
{
bool OK=false;
if (!Empty())
{
OK=true;
Event=*(Last->Next);
}
return OK;
}
END_FUNCTION(Func15);
EventQueueC EventQueue;
/****************************************************************************/
/* */
/* CLASS NAME : ISRToolsC */
/* */
/* PURPOSE : Used by the ISR's. It contains functions for reading scan codes*/
/* in from the key board port, updating the the key board LED's, */
/* obtaining and changing the flags, obtaining mouse events via */
/* the mouse service interrupt etc. The ISR's do not access the */
/* various data members directly. */
/* */
/****************************************************************************/
class ISRToolsC
{
private:
/************************/
/* PRIVATE DATA MEMBERS */
/************************/
// Ports
int KeyDataPort,KeyCommandPort,PICPort;
// Interrupt vectors.
int KeyIntVect,TimerIntVect,MouseIntVect;
// Lock key and extended key flags.
bool ExtendedKey,CapsLockOn,NumLockOn,ScrollLockOn,SpecialExtendedKey;
// Shift, alt and ctrl key flags.
// These are unsigned chars because there are two of each hence 2 means
// that both are pressed, 1 means that one is pressed and 0 means that
// neither are pressed.
unsigned char ShiftOn,CtrlOn,AltOn;
// Special key handling flags.
bool CtrlBreakHand,CtrlAltDelHand,PrntScnHand;
/*********************/
/* PRIVATE FUNCTIONS */
/*********************/
// Waits for the key board to become ready to receive data.
bool WaitKeyBoardReady();
// Waits for the key board to acknowledge data sent.
bool WaitKeyBoardAcknowledge();
// Sends data to the key board data port.
void SendKeyBoardData(unsigned char Data);
// Turns of all the LED's.
void ClearLEDs();
public:
/********************/
/* PUBLIC FUNCTIONS */
/********************/
// Constructor.
ISRToolsC();
// Destructor.
~ISRToolsC();
// Updates the key boards LED's.
void UpdateLEDs();
// Acknowledges the PIC chip for the hardware interrupt.
void AcknowledgeInterrupt();
// Reads the scan code from the key board port.
unsigned char GetScanCode();
// Functions for checking and toggling the booloean flags.
bool IsExtendedKey();
void ToggleExtendedKey();
bool IsSpecialExtendedKey();
void ToggleSpecialExtendedKey();
bool IsCapsLockOn();
void ToggleCapsLock();
bool IsNumLockOn();
void ToggleNumLock();
bool IsScrollLockOn();
void ToggleScrollLock();
bool IsCtrlBreakHandOn();
void ToggleCtrlBreakHand();
bool IsPrntScnHandOn();
void TogglePrntScnHand();
bool IsCtrlAltDelHandOn();
void ToggleCtrlAltDelHand();
// Functions for checking and altering the non-boolean flags.
bool IsCtrlOn();
void CtrlInc();
void CtrlDec();
bool IsAltOn();
void AltInc();
void AltDec();
bool IsShiftOn();
void ShiftInc();
void ShiftDec();
// Returns the ASCII character for the given key.
unsigned char GetASCII(unsigned char ScanCode);
};
// Forward declartions.
void DoLocking();
#ifndef DEBUG
void KeyBoardISR(...);
#else
void KeyBoardISR(unsigned char Scan);
#endif
void MousePollISR(...);
// Constructor.
ISRToolsC::ISRToolsC()
{
// Ports and vectors.
KeyDataPort=0x60;
KeyCommandPort=0x64;
PICPort=0x20;
KeyIntVect=0x09;
TimerIntVect=0x1C;
MouseIntVect=0x33;
// Lock all functions and variables touched by the ISR's.
DoLocking();
// Flags
CtrlBreakHand=CtrlAltDelHand=PrntScnHand=false;
AltOn=ShiftOn=CtrlOn=0;
ScrollLockOn=NumLockOn=CapsLockOn=ExtendedKey=SpecialExtendedKey=false;
ClearLEDs();
#ifndef DEBUG
ISRs.Install(KeyIntVect,KeyBoardISR);
ISRs.Install(TimerIntVect,MousePollISR);
#endif
}
// Destructor.
ISRToolsC::~ISRToolsC()
{
#ifndef DEBUG
ISRs.Restore(KeyIntVect);
ISRs.Restore(TimerIntVect);
ClearLEDs();
#endif
}
// Acknowledges the PIC chip for the hardware interrupt.
START_FUNCTION(Func16);
void ISRToolsC::AcknowledgeInterrupt()
{
OutPortB(PICPort,PICPort);
}
END_FUNCTION(Func16);
// Reads the scan code from the key board port.
START_FUNCTION(Func17);
unsigned char ISRToolsC::GetScanCode()
{
unsigned char ScanCode;
InPortB(KeyDataPort,ScanCode);
return ScanCode;
}
END_FUNCTION(Func17);
// Functions for checking and toggling the booloean flags.
START_FUNCTION(Func18);
bool ISRToolsC::IsExtendedKey()
{
return ExtendedKey;
}
END_FUNCTION(Func18);
START_FUNCTION(Func19);
void ISRToolsC::ToggleExtendedKey()
{
ExtendedKey=!ExtendedKey;
}
END_FUNCTION(Func19);
START_FUNCTION(Func20);
bool ISRToolsC::IsSpecialExtendedKey()
{
return SpecialExtendedKey;
}
END_FUNCTION(Func20);
START_FUNCTION(Func21);
void ISRToolsC::ToggleSpecialExtendedKey()
{
SpecialExtendedKey=!SpecialExtendedKey;
}
END_FUNCTION(Func21);
START_FUNCTION(Func22);
bool ISRToolsC::IsCapsLockOn()
{
return CapsLockOn;
}
END_FUNCTION(Func22);
START_FUNCTION(Func23);
void ISRToolsC::ToggleCapsLock()
{
CapsLockOn=!CapsLockOn;
}
END_FUNCTION(Func23);
START_FUNCTION(Func24);
bool ISRToolsC::IsNumLockOn()
{
return NumLockOn;
}
END_FUNCTION(Func24);
START_FUNCTION(Func25);
void ISRToolsC::ToggleNumLock()
{
NumLockOn=!NumLockOn;
}
END_FUNCTION(Func25);
START_FUNCTION(Func26);
bool ISRToolsC::IsScrollLockOn()
{
return ScrollLockOn;
}
END_FUNCTION(Func26);
START_FUNCTION(Func27);
void ISRToolsC::ToggleScrollLock()
{
ScrollLockOn=!ScrollLockOn;
}
END_FUNCTION(Func27);
START_FUNCTION(Func28);
bool ISRToolsC::IsCtrlBreakHandOn()
{
return CtrlBreakHand;
}
END_FUNCTION(Func28);
START_FUNCTION(Func29);
void ISRToolsC::ToggleCtrlBreakHand()
{
CtrlBreakHand=!CtrlBreakHand;
}
END_FUNCTION(Func29);
START_FUNCTION(Func30);
bool ISRToolsC::IsPrntScnHandOn()
{
return PrntScnHand;
}
END_FUNCTION(Func30);
START_FUNCTION(Func31);
void ISRToolsC::TogglePrntScnHand()
{
PrntScnHand=!PrntScnHand;
}
END_FUNCTION(Func31);
START_FUNCTION(Func32);
bool ISRToolsC::IsCtrlAltDelHandOn()
{
return CtrlAltDelHand;
}
END_FUNCTION(Func32);
START_FUNCTION(Func33);
void ISRToolsC::ToggleCtrlAltDelHand()
{
CtrlAltDelHand=!CtrlAltDelHand;
}
END_FUNCTION(Func33);
// Functions for checking and altering the non-boolean flags.
START_FUNCTION(Func34);
bool ISRToolsC::IsCtrlOn()
{
return CtrlOn>0;
}
END_FUNCTION(Func34);
START_FUNCTION(Func35);
void ISRToolsC::CtrlInc()
{
CtrlOn++;
}
END_FUNCTION(Func35);
START_FUNCTION(Func36);
void ISRToolsC::CtrlDec()
{
CtrlOn--;
}
END_FUNCTION(Func36);
START_FUNCTION(Func37);
bool ISRToolsC::IsAltOn()
{
return AltOn>0;
}
END_FUNCTION(Func37);
START_FUNCTION(Func38);
void ISRToolsC::AltInc()
{
AltOn++;
}
END_FUNCTION(Func38);
START_FUNCTION(Func39);
void ISRToolsC::AltDec()
{
AltOn--;
}
END_FUNCTION(Func39);
START_FUNCTION(Func40);
bool ISRToolsC::IsShiftOn()
{
return ShiftOn>0;
}
END_FUNCTION(Func40);
START_FUNCTION(Func41);
void ISRToolsC::ShiftInc()
{
ShiftOn++;
}
END_FUNCTION(Func41);
START_FUNCTION(Func42);
void ISRToolsC::ShiftDec()
{
ShiftOn--;
}
END_FUNCTION(Func42);
// Sends data to the key board data port.
START_FUNCTION(Func43);
void ISRToolsC::SendKeyBoardData(unsigned char Data)
{
OutPortB(KeyDataPort,Data);
}
END_FUNCTION(Func43);
// Waits for the key board to become ready to receive data.
START_FUNCTION(Func44);
bool ISRToolsC::WaitKeyBoardReady()
{
int I=10000;
bool Ready=false;
unsigned char Byte;
do
{
I--;
InPortB(KeyCommandPort,Byte);
Ready=(Byte & 0x02)>0;
}
while (!Ready && (I>0));
return Ready;
}
END_FUNCTION(Func44);
// Waits for the key board to acknowledge data sent.
START_FUNCTION(Func45);
bool ISRToolsC::WaitKeyBoardAcknowledge()
{
int I=10000;
bool Acked=false;
unsigned char Byte;
do
{
I--;
InPortB(KeyCommandPort,Byte);
Acked=Byte==0x1C;
}
while (!Acked && (I>0));
return Acked;
}
END_FUNCTION(Func45);
// Turns of all the LED's.
START_FUNCTION(Func46);
void ISRToolsC::ClearLEDs()
{
unsigned char ChangeLEDsCommand=0xED;
if (WaitKeyBoardReady())
{
SendKeyBoardData(ChangeLEDsCommand);
if (WaitKeyBoardAcknowledge())
SendKeyBoardData(0x00);
}
}
END_FUNCTION(Func46);
// Updates the key boards LED's.
START_FUNCTION(Func47);
void ISRToolsC::UpdateLEDs()
{
unsigned char LEDFlag=0x00,ChangeLEDsCommand=0xED;
// Construct the LED flag which is to be sent to the key board.
if (CapsLockOn)
LEDFlag|=0x04;
if (NumLockOn)
LEDFlag|=0x02;
if (ScrollLockOn)
LEDFlag|=0x01;
if (WaitKeyBoardReady())
{
SendKeyBoardData(ChangeLEDsCommand);
if (WaitKeyBoardAcknowledge())
SendKeyBoardData(LEDFlag);
}
}
END_FUNCTION(Func47);
// Returns the ASCII character for the given key.
START_FUNCTION(Func48);
unsigned char ISRToolsC::GetASCII(unsigned char ScanCode)
{
unsigned char ASCII=0;
if (ShiftOn && CapsLockOn && NumLockOn)
{
switch (ScanCode)
{
case 1 : ASCII=27;break;
case 2 : ASCII='!';break;
case 3 : ASCII='@';break;
case 4 : ASCII='#';break;
case 5 : ASCII='$';break;
case 6 : ASCII='%';break;
case 7 : ASCII='^';break;
case 8 : ASCII='&';break;
case 9 : ASCII='*';break;
case 10 : ASCII='(';break;
case 11 : ASCII=')';break;
case 12 : ASCII='_';break;
case 13 : ASCII='+';break;
case 14 : ASCII=8;break;
case 15 : ASCII=9;break;
case 16 : ASCII='q';break;
case 17 : ASCII='w';break;
case 18 : ASCII='e';break;
case 19 : ASCII='r';break;
case 20 : ASCII='t';break;
case 21 : ASCII='y';break;
case 22 : ASCII='u';break;
case 23 : ASCII='i';break;
case 24 : ASCII='o';break;
case 25 : ASCII='p';break;
case 26 : ASCII='{';break;
case 27 : ASCII='}';break;
case 28 : ASCII=13;break;
case 30 : ASCII='a';break;
case 31 : ASCII='s';break;
case 32 : ASCII='d';break;
case 33 : ASCII='f';break;
case 34 : ASCII='g';break;
case 35 : ASCII='h';break;
case 36 : ASCII='j';break;
case 37 : ASCII='k';break;
case 38 : ASCII='l';break;
case 39 : ASCII=':';break;
case 40 : ASCII='"';break;
case 41 : ASCII='~';break;
case 43 : ASCII='|';break;
case 44 : ASCII='z';break;
case 45 : ASCII='x';break;
case 46 : ASCII='c';break;
case 47 : ASCII='v';break;
case 48 : ASCII='b';break;
case 49 : ASCII='n';break;
case 50 : ASCII='m';break;
case 51 : ASCII='<';break;
case 52 : ASCII='>';break;
case 53 : if (ExtendedKey)
ASCII='/';
else
ASCII='?';
break;
case 55 : ASCII='*';break;
case 57 : ASCII=' ';break;
case 74 : ASCII='-';break;
case 78 : ASCII='+';break;
}
}
else if (ShiftOn && NumLockOn)
{
switch (ScanCode)
{
case 1 : ASCII=27;break;
case 2 : ASCII='!';break;
case 3 : ASCII='@';break;
case 4 : ASCII='#';break;
case 5 : ASCII='$';break;
case 6 : ASCII='%';break;
case 7 : ASCII='^';break;
case 8 : ASCII='&';break;
case 9 : ASCII='*';break;
case 10 : ASCII='(';break;
case 11 : ASCII=')';break;
case 12 : ASCII='_';break;
case 13 : ASCII='+';break;
case 14 : ASCII=8;break;
case 15 : ASCII=9;break;
case 16 : ASCII='A';break;
case 17 : ASCII='W';break;
case 18 : ASCII='E';break;
case 19 : ASCII='R';break;
case 20 : ASCII='T';break;
case 21 : ASCII='Y';break;
case 22 : ASCII='U';break;
case 23 : ASCII='I';break;
case 24 : ASCII='O';break;
case 25 : ASCII='P';break;
case 26 : ASCII='{';break;
case 27 : ASCII='}';break;
case 28 : ASCII=13;break;
case 30 : ASCII='A';break;
case 31 : ASCII='S';break;
case 32 : ASCII='D';break;
case 33 : ASCII='F';break;
case 34 : ASCII='G';break;
case 35 : ASCII='H';break;
case 36 : ASCII='J';break;
case 37 : ASCII='K';break;
case 38 : ASCII='L';break;
case 39 : ASCII=':';break;
case 40 : ASCII='"';break;
case 41 : ASCII='~';break;
case 43 : ASCII='|';break;
case 44 : ASCII='Z';break;
case 45 : ASCII='X';break;
case 46 : ASCII='C';break;
case 47 : ASCII='V';break;
case 48 : ASCII='B';break;
case 49 : ASCII='N';break;
case 50 : ASCII='M';break;
case 51 : ASCII='<';break;
case 52 : ASCII='>';break;
case 53 : if (ExtendedKey)
ASCII='/';
else
ASCII='?';
break;
case 55 : ASCII='*';break;
case 57 : ASCII=' ';break;
case 74 : ASCII='-';break;
case 78 : ASCII='+';break;
}
}
else if (ShiftOn && CapsLockOn)
{
switch (ScanCode)
{
case 1 : ASCII=27;break;
case 2 : ASCII='!';break;
case 3 : ASCII='@';break;
case 4 : ASCII='#';break;
case 5 : ASCII='$';break;
case 6 : ASCII='%';break;
case 7 : ASCII='^';break;
case 8 : ASCII='&';break;
case 9 : ASCII='*';break;
case 10 : ASCII='(';break;
case 11 : ASCII=')';break;
case 12 : ASCII='_';break;
case 13 : ASCII='+';break;
case 14 : ASCII=8;break;
case 15 : ASCII=9;break;
case 16 : ASCII='q';break;
case 17 : ASCII='w';break;
case 18 : ASCII='e';break;
case 19 : ASCII='r';break;
case 20 : ASCII='t';break;
case 21 : ASCII='y';break;
case 22 : ASCII='u';break;
case 23 : ASCII='i';break;
case 24 : ASCII='o';break;
case 25 : ASCII='p';break;
case 26 : ASCII='{';break;
case 27 : ASCII='}';break;
case 28 : ASCII=13;break;
case 30 : ASCII='a';break;
case 31 : ASCII='s';break;
case 32 : ASCII='d';break;
case 33 : ASCII='f';break;
case 34 : ASCII='g';break;
case 35 : ASCII='h';break;
case 36 : ASCII='j';break;
case 37 : ASCII='k';break;
case 38 : ASCII='l';break;
case 39 : ASCII=':';break;
case 40 : ASCII='"';break;
case 41 : ASCII='~';break;
case 43 : ASCII='|';break;
case 44 : ASCII='z';break;
case 45 : ASCII='x';break;
case 46 : ASCII='c';break;
case 47 : ASCII='v';break;
case 48 : ASCII='b';break;
case 49 : ASCII='n';break;
case 50 : ASCII='m';break;
case 51 : ASCII='<';break;
case 52 : ASCII='>';break;
case 53 : if (ExtendedKey)
ASCII='/';
else
ASCII='?';
break;
case 55 : ASCII='*';break;
case 57 : ASCII=' ';break;
case 71 : ASCII='7';break;
case 72 : ASCII='8';break;
case 73 : ASCII='9';break;
case 74 : ASCII='-';break;
case 75 : ASCII='4';break;
case 76 : ASCII='5';break;
case 77 : ASCII='6';break;
case 78 : ASCII='+';break;
case 79 : ASCII='1';break;
case 80 : ASCII='2';break;
case 81 : ASCII='3';break;
case 82 : ASCII='0';break;
case 83 : ASCII='.';break;
}
}
else if (CapsLockOn && NumLockOn)
{
switch (ScanCode)
{
case 1 : ASCII=27;break;
case 2 : ASCII='1';break;
case 3 : ASCII='2';break;
case 4 : ASCII='3';break;
case 5 : ASCII='4';break;
case 6 : ASCII='5';break;
case 7 : ASCII='6';break;
case 8 : ASCII='7';break;
case 9 : ASCII='8';break;
case 10 : ASCII='9';break;
case 11 : ASCII='0';break;
case 12 : ASCII='-';break;
case 13 : ASCII='=';break;
case 14 : ASCII=8;break;
case 15 : ASCII=9;break;
case 16 : ASCII='Q';break;
case 17 : ASCII='W';break;
case 18 : ASCII='E';break;
case 19 : ASCII='R';break;
case 20 : ASCII='T';break;
case 21 : ASCII='Y';break;
case 22 : ASCII='U';break;
case 23 : ASCII='I';break;
case 24 : ASCII='O';break;
case 25 : ASCII='P';break;
case 26 : ASCII='[';break;
case 27 : ASCII=']';break;
case 28 : ASCII=13;break;
case 30 : ASCII='A';break;
case 31 : ASCII='S';break;
case 32 : ASCII='D';break;
case 33 : ASCII='F';break;
case 34 : ASCII='G';break;
case 35 : ASCII='H';break;
case 36 : ASCII='J';break;
case 37 : ASCII='K';break;
case 38 : ASCII='L';break;
case 39 : ASCII=';';break;
case 40 : ASCII='\'';break;
case 41 : ASCII='`';break;
case 43 : ASCII='\\';break;
case 44 : ASCII='Z';break;
case 45 : ASCII='X';break;
case 46 : ASCII='C';break;
case 47 : ASCII='V';break;
case 48 : ASCII='B';break;
case 49 : ASCII='N';break;
case 50 : ASCII='M';break;
case 51 : ASCII=',';break;
case 52 : ASCII='.';break;
case 53 : ASCII='/';break;
case 55 : ASCII='*';break;
case 57 : ASCII=' ';break;
case 71 : ASCII='7';break;
case 72 : ASCII='8';break;
case 73 : ASCII='9';break;
case 74 : ASCII='-';break;
case 75 : ASCII='4';break;
case 76 : ASCII='5';break;
case 77 : ASCII='6';break;
case 78 : ASCII='+';break;
case 79 : ASCII='1';break;
case 80 : ASCII='2';break;
case 81 : ASCII='3';break;
case 82 : ASCII='0';break;
case 83 : ASCII='.';break;
}
}
else if (ShiftOn)
{
switch (ScanCode)
{
case 1 : ASCII=27;break;
case 2 : ASCII='!';break;
case 3 : ASCII='@';break;
case 4 : ASCII='#';break;
case 5 : ASCII='$';break;
case 6 : ASCII='%';break;
case 7 : ASCII='^';break;
case 8 : ASCII='&';break;
case 9 : ASCII='*';break;
case 10 : ASCII='(';break;
case 11 : ASCII=')';break;
case 12 : ASCII='_';break;
case 13 : ASCII='+';break;
case 14 : ASCII=8;break;
case 15 : ASCII=9;break;
case 16 : ASCII='Q';break;
case 17 : ASCII='W';break;
case 18 : ASCII='E';break;
case 19 : ASCII='R';break;
case 20 : ASCII='T';break;
case 21 : ASCII='Y';break;
case 22 : ASCII='U';break;
case 23 : ASCII='I';break;
case 24 : ASCII='O';break;
case 25 : ASCII='P';break;
case 26 : ASCII='{';break;
case 27 : ASCII='}';break;
case 28 : ASCII=13;break;
case 30 : ASCII='A';break;
case 31 : ASCII='S';break;
case 32 : ASCII='D';break;
case 33 : ASCII='F';break;
case 34 : ASCII='G';break;
case 35 : ASCII='H';break;
case 36 : ASCII='J';break;
case 37 : ASCII='K';break;
case 38 : ASCII='L';break;
case 39 : ASCII=':';break;
case 40 : ASCII='"';break;
case 41 : ASCII='~';break;
case 43 : ASCII='|';break;
case 44 : ASCII='Z';break;
case 45 : ASCII='X';break;
case 46 : ASCII='C';break;
case 47 : ASCII='V';break;
case 48 : ASCII='B';break;
case 49 : ASCII='N';break;
case 50 : ASCII='M';break;
case 51 : ASCII='<';break;
case 52 : ASCII='>';break;
case 53 : if (ExtendedKey)
ASCII='/';
else
ASCII='?';
break;
case 55 : ASCII='*';break;
case 57 : ASCII=' ';break;
case 71 : ASCII='7';break;
case 72 : ASCII='8';break;
case 73 : ASCII='9';break;
case 74 : ASCII='-';break;
case 75 : ASCII='4';break;
case 76 : ASCII='5';break;
case 77 : ASCII='6';break;
case 78 : ASCII='+';break;
case 79 : ASCII='1';break;
case 80 : ASCII='2';break;
case 81 : ASCII='3';break;
case 82 : ASCII='0';break;
case 83 : ASCII='.';break;
}
}
else if (CapsLockOn)
{
switch (ScanCode)
{
case 1 : ASCII=27;break;
case 2 : ASCII='1';break;
case 3 : ASCII='2';break;
case 4 : ASCII='3';break;
case 5 : ASCII='4';break;
case 6 : ASCII='5';break;
case 7 : ASCII='6';break;
case 8 : ASCII='7';break;
case 9 : ASCII='8';break;
case 10 : ASCII='9';break;
case 11 : ASCII='0';break;
case 12 : ASCII='-';break;
case 13 : ASCII='=';break;
case 14 : ASCII=8;break;
case 15 : ASCII=9;break;
case 16 : ASCII='Q';break;
case 17 : ASCII='W';break;
case 18 : ASCII='E';break;
case 19 : ASCII='R';break;
case 20 : ASCII='T';break;
case 21 : ASCII='Y';break;
case 22 : ASCII='U';break;
case 23 : ASCII='I';break;
case 24 : ASCII='O';break;
case 25 : ASCII='P';break;
case 26 : ASCII='[';break;
case 27 : ASCII=']';break;
case 28 : ASCII=13;break;
case 30 : ASCII='A';break;
case 31 : ASCII='S';break;
case 32 : ASCII='D';break;
case 33 : ASCII='F';break;
case 34 : ASCII='G';break;
case 35 : ASCII='H';break;
case 36 : ASCII='J';break;
case 37 : ASCII='K';break;
case 38 : ASCII='L';break;
case 39 : ASCII=';';break;
case 40 : ASCII='\'';break;
case 41 : ASCII='`';break;
case 43 : ASCII='\\';break;
case 44 : ASCII='Z';break;
case 45 : ASCII='X';break;
case 46 : ASCII='C';break;
case 47 : ASCII='V';break;
case 48 : ASCII='B';break;
case 49 : ASCII='N';break;
case 50 : ASCII='M';break;
case 51 : ASCII=',';break;
case 52 : ASCII='.';break;
case 53 : ASCII='/';break;
case 55 : ASCII='*';break;
case 57 : ASCII=' ';break;
case 74 : ASCII='-';break;
case 78 : ASCII='+';break;
}
}
else if (NumLockOn)
{
switch (ScanCode)
{
case 1 : ASCII=27;break;
case 2 : ASCII='1';break;
case 3 : ASCII='2';break;
case 4 : ASCII='3';break;
case 5 : ASCII='4';break;
case 6 : ASCII='5';break;
case 7 : ASCII='6';break;
case 8 : ASCII='7';break;
case 9 : ASCII='8';break;
case 10 : ASCII='9';break;
case 11 : ASCII='0';break;
case 12 : ASCII='-';break;
case 13 : ASCII='=';break;
case 14 : ASCII=8;break;
case 15 : ASCII=9;break;
case 16 : ASCII='q';break;
case 17 : ASCII='w';break;
case 18 : ASCII='e';break;
case 19 : ASCII='r';break;
case 20 : ASCII='t';break;
case 21 : ASCII='y';break;
case 22 : ASCII='u';break;
case 23 : ASCII='i';break;
case 24 : ASCII='o';break;
case 25 : ASCII='p';break;
case 26 : ASCII='[';break;
case 27 : ASCII=']';break;
case 28 : ASCII=13;break;
case 30 : ASCII='a';break;
case 31 : ASCII='s';break;
case 32 : ASCII='d';break;
case 33 : ASCII='f';break;
case 34 : ASCII='g';break;
case 35 : ASCII='h';break;
case 36 : ASCII='j';break;
case 37 : ASCII='k';break;
case 38 : ASCII='l';break;
case 39 : ASCII=';';break;
case 40 : ASCII='\'';break;
case 41 : ASCII='`';break;
case 43 : ASCII='\\';break;
case 44 : ASCII='z';break;
case 45 : ASCII='x';break;
case 46 : ASCII='c';break;
case 47 : ASCII='v';break;
case 48 : ASCII='b';break;
case 49 : ASCII='n';break;
case 50 : ASCII='m';break;
case 51 : ASCII=',';break;
case 52 : ASCII='.';break;
case 53 : ASCII='/';break;
case 55 : ASCII='*';break;
case 57 : ASCII=' ';break;
case 71 : ASCII='1';break;
case 72 : ASCII='2';break;
case 73 : ASCII='3';break;
case 74 : ASCII='-';break;
case 75 : ASCII='4';break;
case 76 : ASCII='5';break;
case 77 : ASCII='6';break;
case 78 : ASCII='+';break;
case 79 : ASCII='1';break;
case 80 : ASCII='2';break;
case 81 : ASCII='3';break;
case 82 : ASCII='0';break;
case 83 : ASCII='.';break;
}
}
else
{
switch (ScanCode)
{
case 1 : ASCII=27;break;
case 2 : ASCII='1';break;
case 3 : ASCII='2';break;
case 4 : ASCII='3';break;
case 5 : ASCII='4';break;
case 6 : ASCII='5';break;
case 7 : ASCII='6';break;
case 8 : ASCII='7';break;
case 9 : ASCII='8';break;
case 10 : ASCII='9';break;
case 11 : ASCII='0';break;
case 12 : ASCII='-';break;
case 13 : ASCII='=';break;
case 14 : ASCII=8;break;
case 15 : ASCII=9;break;
case 16 : ASCII='q';break;
case 17 : ASCII='w';break;
case 18 : ASCII='e';break;
case 19 : ASCII='r';break;
case 20 : ASCII='t';break;
case 21 : ASCII='y';break;
case 22 : ASCII='u';break;
case 23 : ASCII='i';break;
case 24 : ASCII='o';break;
case 25 : ASCII='p';break;
case 26 : ASCII='[';break;
case 27 : ASCII=']';break;
case 28 : ASCII=13;break;
case 30 : ASCII='a';break;
case 31 : ASCII='s';break;
case 32 : ASCII='d';break;
case 33 : ASCII='f';break;
case 34 : ASCII='g';break;
case 35 : ASCII='h';break;
case 36 : ASCII='j';break;
case 37 : ASCII='k';break;
case 38 : ASCII='l';break;
case 39 : ASCII=';';break;
case 40 : ASCII='\'';break;
case 41 : ASCII='`';break;
case 43 : ASCII='\\';break;
case 44 : ASCII='z';break;
case 45 : ASCII='x';break;
case 46 : ASCII='c';break;
case 47 : ASCII='v';break;
case 48 : ASCII='b';break;
case 49 : ASCII='n';break;
case 50 : ASCII='m';break;
case 51 : ASCII=',';break;
case 52 : ASCII='.';break;
case 53 : ASCII='/';break;
case 55 : ASCII='*';break;
case 57 : ASCII=' ';break;
case 74 : ASCII='-';break;
case 78 : ASCII='+';break;
}
}
return ASCII;
}
END_FUNCTION(Func48);
ISRToolsC ISRTools;
/****************************************************************************/
/* */
/* FUNCTION NAMES : KeyBoardISR and MousePollISR. */
/* */
/* PURPOSES : KeyBoardISR is installed at interrupt vector 0x09 and its */
/* purpose is to provide more detailed key information than the */
/* old key board handler does. */
/* */
/* The MousePollISR is installed at interrupt vector 0x1C, which */
/* is chained by the timer interrupt about 18.2 times a second. */
/* Its purpose is to queue the mouse input along with the key */
/* board input. */
/* */
/****************************************************************************/
START_FUNCTION(Func49);
#ifndef DEBUG
void KeyBoardISR(...)
#else
void KeyBoardISR(unsigned char Scan)
#endif
{
unsigned char ScanCode;
EventC Event;
#ifndef DEBUG
ScanCode=ISRTools.GetScanCode();
#else
ScanCode=Scan;
#endif
// Update the flags.
switch (ScanCode)
{
case 56 : ISRTools.AltInc();break;
case 184 : ISRTools.AltDec();break;
case 29 : ISRTools.CtrlInc();break;
case 157 : ISRTools.CtrlDec();break;
case 54 : ISRTools.ShiftInc();break;
case 42 : ISRTools.ShiftInc();break;
case 182 : ISRTools.ShiftDec();break;
case 170 : ISRTools.ShiftDec();break;
case 58 : ISRTools.ToggleCapsLock();break;
case 69 : ISRTools.ToggleNumLock();break;
case 70 : ISRTools.ToggleScrollLock();break;
case 224 : if (!ISRTools.IsExtendedKey())
ISRTools.ToggleExtendedKey();
break;
case 225 : if (!ISRTools.IsSpecialExtendedKey())
ISRTools.ToggleSpecialExtendedKey();
break;
};
// Update the LED's
ISRTools.UpdateLEDs();
// This is a key board event.
Event.Type=KeyBoard;
Event.MouseX=Event.MouseY=0;
Event.MouseKey=Left;
// Copy the status of the state shift keys into the event.
Event.Alt=ISRTools.IsAltOn();
Event.Ctrl=ISRTools.IsCtrlOn();
Event.Shift=ISRTools.IsShiftOn();
Event.CapsLock=ISRTools.IsCapsLockOn();
Event.NumLock=ISRTools.IsNumLockOn();
Event.ScrollLock=ISRTools.IsScrollLockOn();
// Time stamp the event.
TimeS Time;
GetTime(Time);
Event.Time.Set(Time.Hour,Time.Minute,Time.Second,Time.Second100);
// Break key handling.
//
// Scan codes sent when key is pressed alone
// -----------------------------------------
// 225,29,69,225,157,197
//
// Scan codes sent when key is pressed and released with ctrl key held
// -------------------------------------------------------------------
// 224,70,224,198
if ((ISRTools.IsSpecialExtendedKey() && ((ScanCode==29) || (ScanCode==69) || (ScanCode==157) || (ScanCode==197))) ||
(ISRTools.IsExtendedKey() && ((ScanCode==70) || (ScanCode==198))))
{
// If CtrlBreak was pressed and CtrlBreak handling is on then call the
// DOS handler.
if ((ScanCode==70) && ISRTools.IsCtrlBreakHandOn())
{
}
// Otherwise we want to queue the key press or release.
//
// Since multiple scan codes are sent we need to ignore some of them otherwise
// we will end up queueing multiple key presses even though it was pressed
// once.
//
// Hence we will acknowledge the scan code 29 (when the break key is pressed
// alone) and the the scan code 70 (when the break key is pressed with the
// ctrl key held. In both case we will identify the key with the scan code
// 224+70=294.
else if ((ScanCode==29) || (ScanCode==157) || (ScanCode==70) || (ScanCode==198))
{
Event.ScanCode=224+70;
Event.ASCII=0;
if ((ScanCode & 0x80) > 0)
Event.What=Released;
else
Event.What=Pressed;
EventQueue.Enqueue(Event);
}
// If the last scan code has been sent then turn off the SpecialExtendedKey
// ExtendedKey flags off.
if (ScanCode==187)
ISRTools.ToggleSpecialExtendedKey();
else if (ScanCode==198)
ISRTools.ToggleExtendedKey();
}
// Print screen/system request handling.
//
// Scan codes sent when key is pressed and released
// ------------------------------------------------
// 224,42,224,55,224,170,224,183
//
// Scan codes sent when key is pressed and released with shift or ctrl keys held
// -----------------------------------------------------------------------------
// 224,55,224,183
//
// Scan codes sent when key is pressed and released with alt key held
// ------------------------------------------------------------------
// 84,212
else if ((ISRTools.IsExtendedKey() && ((ScanCode==42) || (ScanCode==55) || (ScanCode==170) || (ScanCode==183))) ||
(ISRTools.IsExtendedKey() && ((ScanCode==55) || (ScanCode==183))) ||
(ScanCode==84) || (ScanCode==212))
{
// If PrntScn was pressed and PrntScn handling is on then call the
// DOS handler.
if ((ScanCode==42) && ISRTools.IsCtrlBreakHandOn())
{
}
// Otherwise we want to queue the key press or release.
//
// Since multiple scan codes are sent we need to ignore some of them otherwise
// we will end up queueing multiple key presses even though it was pressed
// once.
//
// Hence we will acknowledge the scan code 55 (when the prntscn key is
// pressed alone), the the scan code 55 (when the prntscn key is pressed
// with a ctrl or shift key held and scan code 84 (when the prntscn key is
// pressed with the alt key held). In both case we will identify the key
// with the scan code 224+84=308.
else if ((ScanCode==55) || (ScanCode==183) || (ScanCode==84) || (ScanCode==212))
{
Event.ScanCode=224+84;
Event.ASCII=0;
if ((ScanCode & 0x80) > 0)
Event.What=Released;
else
Event.What=Pressed;
EventQueue.Enqueue(Event);
}
// If the last scan code has been sent then turn off the ExtendedKey flag
// off.
if (ISRTools.IsExtendedKey() && (ScanCode==183))
ISRTools.ToggleExtendedKey();
}
// CtrlAltDel handling.
else if (ISRTools.IsCtrlOn() && ISRTools.IsAltOn() && ((ScanCode==83) || (ScanCode==211)))
{
// If CtrlAltDel was pressed and CtrlAltDel handling is on then call the
// DOS handler.
if (ISRTools.IsCtrlAltDelHandOn())
{
}
// Otherwise just queue the key press or release.
else
{
Event.ScanCode=83;
Event.ASCII=0;
if ((ScanCode & 0x80) > 0)
Event.What=Released;
else
Event.What=Pressed;
EventQueue.Enqueue(Event);
}
}
// Trap extended codes.
else if ((ScanCode==224) || (ScanCode==225))
{
}
// We want to distinguish right ctrl and alt from left ctrl and alt. The
// former are extended keys while the latter are not. We will do so by adding
// 224 to their scan codes.
// Extended keys send the extended code 224 followed by their specific scan
// code.
else if (ISRTools.IsExtendedKey() && ((ScanCode==56) || (ScanCode==29)))
{
// Mask off the 7th bit and add 224.
Event.ScanCode=224+(ScanCode & 0x7F);
// If the 7th bit is set then the key was released.
if ((ScanCode & 0x80) > 0)
Event.What=Released;
else
Event.What=Pressed;
EventQueue.Enqueue(Event);
}
else
{
// Mask out the 7th bit.
Event.ScanCode=ScanCode & 0x7F;
// Get the ASCII character for this key.
Event.ASCII=ISRTools.GetASCII(Event.ScanCode);
// If the 7th bit is set then the key was released.
if ((ScanCode & 0x80) > 0)
Event.What=Released;
else
Event.What=Pressed;
EventQueue.Enqueue(Event);
}
ISRTools.AcknowledgeInterrupt();
}
END_FUNCTION(Func49);
START_FUNCTION(Func50);
void MousePollISR(...)
{
}
END_FUNCTION(Func50);
void DoLocking()
{
LOCK_FUNCTION(Func1);
LOCK_FUNCTION(Func2);
LOCK_FUNCTION(Func3);
LOCK_FUNCTION(Func4);
LOCK_FUNCTION(Func5);
LOCK_FUNCTION(Func6);
LOCK_FUNCTION(Func7);
LOCK_FUNCTION(Func8);
LOCK_FUNCTION(Func9);
LOCK_FUNCTION(Func10);
LOCK_FUNCTION(Func11);
LOCK_FUNCTION(Func12);
LOCK_FUNCTION(Func13);
LOCK_FUNCTION(Func14);
LOCK_FUNCTION(Func15);
LOCK_FUNCTION(Func16);
LOCK_FUNCTION(Func17);
LOCK_FUNCTION(Func18);
LOCK_FUNCTION(Func19);
LOCK_FUNCTION(Func20);
LOCK_FUNCTION(Func21);
LOCK_FUNCTION(Func22);
LOCK_FUNCTION(Func23);
LOCK_FUNCTION(Func24);
LOCK_FUNCTION(Func25);
LOCK_FUNCTION(Func26);
LOCK_FUNCTION(Func27);
LOCK_FUNCTION(Func28);
LOCK_FUNCTION(Func29);
LOCK_FUNCTION(Func30);
LOCK_FUNCTION(Func31);
LOCK_FUNCTION(Func32);
LOCK_FUNCTION(Func33);
LOCK_FUNCTION(Func34);
LOCK_FUNCTION(Func35);
LOCK_FUNCTION(Func36);
LOCK_FUNCTION(Func37);
LOCK_FUNCTION(Func38);
LOCK_FUNCTION(Func39);
LOCK_FUNCTION(Func40);
LOCK_FUNCTION(Func41);
LOCK_FUNCTION(Func42);
LOCK_FUNCTION(Func43);
LOCK_FUNCTION(Func44);
LOCK_FUNCTION(Func45);
LOCK_FUNCTION(Func46);
LOCK_FUNCTION(Func47);
LOCK_FUNCTION(Func48);
LOCK_FUNCTION(Func49);
LOCK_FUNCTION(Func50);
LOCK_DATA(ISRTools);
LOCK_DATA(EventQueue);
}
#ifndef DEBUG
int main()
{
char Scan=0;
EventC Event;
int I=0;
do
{
DisableInts;
if (!EventQueue.Empty())
{
EventQueue.Dequeue(Event);
Scan=Event.ScanCode;
cout<<" Scan code : "<<Event.ScanCode<<endl;
cout<<" ASCII : "<<Event.ASCII<<endl;
cout<<" What : "<<Event.What<<endl;
cout<<" Alt : "<<Event.Alt<<endl;
cout<<" Ctrl : "<<Event.Ctrl<<endl;
cout<<" Shift : "<<Event.Shift<<endl;
cout<<" Caps lock : "<<Event.CapsLock<<endl;
cout<<" Num lock : "<<Event.NumLock<<endl;
cout<<" Scroll lock : "<<Event.ScrollLock<<endl;
}
EnableInts;
}
while (Scan!=1);
return 0;
}
#else
int main()
{
unsigned char Scan=0;
StringC String;
do
{
cout<<"Scan code : ";
cin>>String;
if (String!="")
{
String.ToUnsignedChar(Scan<<endl;
KeyBoardISR(Scan<<endl;
cout<<" Scan code : "<<Event.ScanCode<<endl;
cout<<" ASCII : "<<Event.ASCII<<endl;
cout<<" What : "<<Event.What<<endl;
cout<<" Alt : "<<Event.Alt<<endl;
cout<<" Ctrl : "<<Event.Ctrl<<endl;
cout<<" Shift : "<<Event.Shift<<endl;
cout<<" Caps lock : "<<Event.CapsLock<<endl;
cout<<" Num lock : "<<Event.NumLock<<endl;
cout<<" Scroll lock : "<<Event.ScrollLock<<endl;
}
}
while (Scan!=1);
return 0;
}
#endif
- Raw text -