SWAGOLX.EXE (c) 1993 GDSOFT ALL RIGHTS RESERVED 00085 KEYBOARD I/O ROUTINES 1 05-28-9313:49ALL SWAG SUPPORT TEAM Stuff Keyboard Buffer IMPORT 19 ╝ {πROB PERELMANππ> I want to put the character and scan code for ALT-V in the keyboard buffer.π> In fact I would like to put it in there twice. I need it to be in theπ> buffer so that when my program terminates the parent process will act onπ> that key.ππ{π If this is being used with Turbo Pascal Version 3.0, you MUST setπ the C and U compiler directives to MINUS!π If this is being used with Turbo Pascal Version 4.0, then set theπ CheckBreak variable of the CRT unit to FALSE!π}ππUsesπ Crt;ππTypeπ BufType = Array[30..62] of Byte;ππVarπ Head : Integer Absolute $0000 : $041A; { Location of head of buffer }π Tail : Integer Absolute $0000 : $041C; { Location of tail of buffer }π KBDBuf : BufType absolute $0000 : $041E; { Absolute location of buffer }π S : String[80]; { Input string }ππProcedure StufftheBuff (Ch : Char; Code : Byte);πVarπ TempTail : Integer; { Temporary holding of Tail }πBeginπ TempTail := Tail; { Store the Temporary Tail }π Tail := Tail + 2; { Incriment Tail to next pos }π If Head = Tail Then { Is the buffer full? }π Beginπ Tail := TempTail; { Reset to previos value }π Sound(440); { Beep the user }π Delay(400); { Delay for the beep }π NoSound; { Turn off the sound }π Endπ Elseπ Beginπ KBDBuf[TempTail] := Ord(Ch); { Put the ASCII value in buf }π KBDBuf[TempTail + 1] := Code; { Put extended keypress valu }π If Tail > 60 then { Last position. Wrap? }π Tail := 30; { Wrap to 1st position }π End;πEnd;ππBeginπ ClrScr; { Clear the Screen }π StufftheBuff ( 'D',0 ); { Start stuffing the buffer }π StufftheBuff ( 'I',0 ); { Another stuff of the Buffer}π StufftheBuff ( 'R',0 ); { " " " " " }π StufftheBuff ( #13,0 ); { CR } { Stuff a carriage return }πEnd.π 2 05-28-9313:49ALL SWAG SUPPORT TEAM Clear Keyboard Buffer IMPORT 8 ) {πEDWIN CALIMBOππ║ I need to know how I can clear the keyboard buffer.π║ The reason I need to do this is that in a loop I'm reading inπ║ one Character and then calling a Procedure which returns to theπ║ loop For the next Character to be read. But sometimes it takes theπ║ next Character in the buffer that my have been a result of just holdingπ║ down a key For to long.πππ You can clear any keys in the keyboard buffer by using the following loop:π}π While KeyPressed Doπ ch := ReadKey;π{π Another way to clear the keyboard buffer is to set the keyboard headπ equal to the keyboard tail and the keyboard buffer as a circular buffer.π You can set the tail equal to the head this way:π}π MemW[$0000:$041C] := MemW[$0000:$041A]; { flush keyboard buffer }π 3 05-28-9313:49ALL SWAG SUPPORT TEAM INT09 Keyboard handler #1IMPORT 21 T╞ {π> Does anybody know of a way to reWrite the keyboard routines, to be ablπ> to read several keys at once? ReadKey will only read the last keypressπ> anything else I've tried can only read the last key you have pressed dπ>π> For example, in many games it will let you move Forward (With the Forwπ> arrow key) and shoot at the same time, With the space bar...Any suggesπ}ππUnit POLL ; { polled keyboard handler }π { does not support F11 or F12 keys } InterfaceππConstπ EscKey = 1 ; { key codes }π aKey = 30 ; { see TP 6 Programmers guide p 354 }π sKey = 31 ;π endKey = 79 ;π DownKey = 80 ;ππVarπ KeyTable : Array[ 1..127 ] of Boolean ; { KeyTable[ x ] is True when key xπis pressed } { and stays True Until key x is released }ππImplementationππUses Dos, KeyIntr ; { keyboard interrupt support }ππVarπ OldInt09 : Pointer ;π ExitSave : Pointer ;ππ{$F+} Procedure RestoreInt09 ;πbeginπ ExitProc := ExitSave ;π SetIntVec( $09, OldInt09 ) ;πend ;ππ{$F+} Procedure NewInt09 ; interrupt ;πVarπ ScanCode : Byte ;π KeyCode : Byte ;πbeginπ STI ;π ScanCode := ReadScanCode ;π KeyCode := ScanCode and $7F ; { strip make/break bit }π KeyTable[ KeyCode ] := ( ScanCode and $80 ) = 0 ; (* { For non C Programmersπ}π if ( ScanCode and $80 ) = 0 then { make code -- key pressed }π KeyTable[ KeyCode ] := Trueπ else { break code -- key released }π KeyTable[ KeyCode ] := False ;π*)π ResetKeyboard ;π EOI ;πend ;ππVarπ N : Byte ;ππbeginπ ExitSave := ExitProc ;π ExitProc := addr( RestoreInt09 ) ;ππ For N := 1 to 127 do { no key pressed }π KeyTable[ N ] := False ;ππ GetIntVec( $09, OldInt09 ) ;π SetIntVec( $09, addr( NewInt09 ) ) ;πend.π{---------------------------------------------} Program TwoKeys;ππUses Crt, Poll ; { polled keyboard handler } { ----- this Program willπprobably hang a debugger ----- } Varπ X, Y : Byte ;πbeginπ ClrScr ;π X := 40 ;π Y := 12 ;ππ WriteLn( 'Hit keys A S and 1 2 on the keypad' ) ;π WriteLn( ' -- Esc to stop' ) ;ππ While not KeyTable[ EscKey ] doπ beginπ GotoXY( X, Y ) ;π Write( ' ' ) ;ππ{ poll the KeyTable }π if KeyTable[ endKey ] and ( X > 1 ) then Dec( X ) ;π if KeyTable[ DownKey ] and ( X < 80 ) then Inc( X ) ;π if KeyTable[ aKey ] and ( Y > 4 ) then Dec( Y ) ;π if KeyTable[ sKey ] and ( Y < 24 ) then Inc( Y ) ;ππ GotoXY( X, Y ) ;π Write( chr( 1 ) ) ;π Delay( 10 ) ;π end ;πend.π 4 05-28-9313:49ALL SWAG SUPPORT TEAM INT09 Keyboard handler #2IMPORT 29 D¥ {πHere is my source For the keyboard handler.π}ππ{$X+}ππUnit KbIO;ππ(*---------------------------*) Interface (*----------------------------*)ππUses Dos;ππVarπ KbScancode : Byte; { internal Variable, can be used by host Program }π OldInt9Vect : Pointer; { For storing the old interrupt vector }ππProcedure RestoreOldInt9;πProcedure NewInt9; Interrupt;ππ(*------------------------*) Implementation (*--------------------------*)ππProcedure RestoreOldInt9; { Restores control to the old interrupt handler }πbeginπ SetIntVec($09, OldInt9Vect);πend;ππ{$F+}πProcedure NewInt9; (* Interrupt; *)πVarπ scancode : Byte;ππ Procedure ResetKBD;π Varπ b : Byte;π beginπ b := Port[$61];π Port[$61] := b or $80;π Port[$61] := b;π Port[$20] := $20;π end;ππbeginπ scancode := Port[$60];π KbScancode := scancode;π (* at this point, you could add Up, Down, Left & Right Varsπ eg. if (KbScancode = 72) then Up := True;π if (KbScancode = 72 + 128) then Up := False;π .π .π .π Don't Forget to initialize Up, Down, etc. if you use them! *)π ResetKBD;πend;π{$F-}ππbeginπ GetIntVec($09, OldInt9Vect);π SetIntVec($09, @NewInt9);π KbScancode := 0;π (*π At this point, the Unit could install a custom Exit Procedureπ that automatically restores the old keyboard handler when theπ host Program finishes.π *)πend.ππ{πJust include this Unit in your Uses clause, and, at any time during yourπProgram, you can check 'KbScancode' to see which key was currently pressed orπreleased. Pressed keys have values between 0..127, and released keys have aπvalue between 128..255. ESC = scancode #1, so here's a sample.π}πFunction Check4Quit : Boolean;πVarπ kbcode : Byte;π tmpBool : Boolean;πbeginπ tmpBool := False;π kbcode := KbScancode;π if (kbcode = 1) thenπ beginππ Repeatπ kbcode := KbScancodeπ Until (kbcode <> 1);π (* the above line Repeats Until a different key is pressedπ or released *)ππ if (kbcode = 129) thenπ tmpBool := True;π (* if they released ESC directly after pressing it, withoutπ pressing or releasing any other keys, return a True value *)ππ end;π Check4Quit := tmpBool;πend;ππ{πSo, basically, it's a good idea to save KbScancode in a temporary VariableπbeFore doing any checks on it, as it may change if you do this:ππif (KbScancode = 1) then beginπ Delay(1);π WriteLn('You pressed key #', KbScancode);πend;ππIn that short Delay, they may have released the key or pressed a new one,so theπvalue would have changed, and the Program might screw up.ππSomething to add: Boolean Variables For Up, Down, Left, and Right, For use inπgames and such. See the section in Procedure NewInt9.πππHey, Drew. I Forgot one thing in my message about the custom KB handler.πYou'll probably receive this message at the same time as the Unit I sent.πHere is the important message:ππWhen using the KbIO Unit, at the very end of your Program, include the lineπthat restores the old int9 vector. It is a Procedure called 'RestoreOldInt9'.πIt may not be Absolutely essential to include this line, but if you don'tπrestore the old keyboard handler, you might not be able to Type anything whenπthe Program Exits! (not so good, huh?) What to do: you can install a customπexit Procedure that restores the old int9 vector. if you don't know how to doπthis, quote these lines, or Write to me about "custom Exit Procedures toπrestore the old int9 vector," or something like that. Bye For now.π}π 5 05-28-9313:49ALL SWAG SUPPORT TEAM INT09 Keyboard handler #3IMPORT 30 T╞ {π> Does anybody know of a way to reWrite the keyboard routines, to be ablπ> to read several keys at once? ReadKey will only read the last keypressπ> anything else I've tried can only read the last key you have pressed dπ>π> For example, in many games it will let you move Forward (With the Forwπ> arrow key) and shoot at the same time, With the space bar...Any suggesπOops, I Forgot to include one of the Units you'll need to do this. I've alreadyπsent you POLL.PAS and TWOKEYS.PAS. Here's KEYinTR.PAS:π}πUnit KeyIntr ; { support For inT 09 routines } { Turbo Pascal 5.5 } InterfaceπProcedure CLI ; Inline( $FA ) ; { disable interrupts } Procedure STI ;πInline( $FB ) ; { enable interrupts } { cannot be used outside an interruptπProcedure } Procedure JumpInterrupt( p : Pointer ) ; { see TP5 Ref p 222π} Inline( $5B/$58/ { POP BX, AX AX:BX = p }π $89/$EC/ { MOV SP, BP }π $87/$46/$10/ { XCHG AX, [BP+10H] }π $87/$5E/$0E/ { XCHG BX, [BP+0EH] }π $5D/$07/$1F/$5F/$5E/ { POP BP, ES, DS, DI, SI }π $5A/$59/ { POP DX, CX }π $FA/ { CLI }π $CB ) ; { RETF jmp Far p }ππFunction Control_Pressed : Boolean ;πProcedure EOI ; { end of interrupt to 8259 } FunctionπReadScanCode : Byte ; { read keyboard } Procedure ResetKeyboard ;π { prepare For next key } Procedure StoreKey( Scan, Key : Byte )π;π { put key in buffer For inT 16 }πImplementation Uses Crt ; { Sound, NoSound } Typeπ Address = Record { used in Pointer manipulation }π offset : Word ;π Segment : Word ;π end ;πConstπ BiosDataSegment = $40 ;πVarπ KeyState : Word Absolute BiosDataSegment:$0017 ;π KeyBufferHead : Word Absolute BiosDataSegment:$001A ;π KeyBufferTail : Word Absolute BiosDataSegment:$001C ;π KeyBufferStart : Word Absolute BiosDataSegment:$0080 ;π KeyBufferend : Word Absolute BiosDataSegment:$0082 ;πππFunction Control_Pressed : Boolean ;πbeginπControl_Pressed := ( KeyState and 4 ) = 4 ; end ;ππProcedure EOI ; { end of interrupt to 8259 interrupt controller } beginπ CLI ;π Port[$20] := $20 ; { see TP5 ref p 211 } end ;ππFunction ReadScanCode : Byte ;πbeginπReadScanCode := Port[$60] ;πend ;ππProcedure ResetKeyboard ; { prepare For next key } Varπ N : Byte ;πbeginπ N := Port[$61] ;π Port[$61] := ( N or $80 ) ;π Port[$61] := N ;πend ;ππProcedure StoreKey( Scan, Key : Byte ) ; Var { put key in bufferπthat inT 16 reads }π P : ^Word ;π N : Word ;πbeginπ address(P).segment := BiosDataSegment ;π N := KeyBufferTail ;π address(P).offset := N ;π Inc( N, 2 ) ; { advance Pointer two Bytes }π if( N = KeyBufferend ) then { end of the circular buffer }π N := KeyBufferStart ;π if( N = KeyBufferHead ) then { buffer full }π beginπ EOI ; { EOI must be done beFore Exit }π Sound( 2200 ) ; { but beFore anything that takes a lot }π Delay( 80 ) ; { of time and can be interrupted }π NoSound ;π endπ elseπ begin { high Byte is scan code, low is ASCII }π P^ := Scan * $100 + Key ; { store key in circular buffer }π KeyBufferTail := N ; { advance tail Pointer }π EOI ;π end ;πend ;πend.π 6 05-28-9313:49ALL SWAG SUPPORT TEAM Turn Keyboard OFF IMPORT 15 █╘ {IDIOT PASCAL 101π----------------ππWelcome to IP 101. In today's lesson we will be answering a fewπoften asked questions about Turbo Pascal. if you signed up ForπIDIOT C/C++ 101, please get up and run beFore you get shot.ππQ: HOW do I TURN ofF/ON THE KEYBOARD FROM MY Program?πA: Easy. Though you may search through many books, you will findπ the answer in a Excellent reference called _THE MS-Dosπ ENCYCLOPEDIA_. It tells of a mystical I/O port where you canπ turn off/on the keyboard by just flipping a bit. This port isπ the 8259 Programmible Interrupt Controller. Now, part of theπ 8259 is the Interrupt Mask Register, or IMR For short. Theπ port location is $21. to turn off the Keyboard...(RECKLESSLY)ππ} Procedure KEYBOARD_ofF;ππ beginπ PorT[$21]:=$02π end;π{π to turn the keyboard back on (RECKLESSLY), just set the portπ back to $0.ππ (THE MSDos ENCYCLOPEDIA (C) 1988 Microsoft Press p417)ππQ: HOW do I FLIP BITS ON/ofF in A Byte or Integer?πA: Simple, Really. The following Procedures work on bothπ Byte,Char,Boolean,Integer, and Word values(I hope).π}πProcedure SBIT(Var TARGET;BITNUM:Integer); {set bit}ππVarπ SUBJECT : Integer Absolute TARGET;π MASK : Integer;ππ beginπ MASK := 1 SHL BITNUM;π SUBJECT := SUBJECT or MASKπ end;ππProcedure CBIT(Var TARGET;BITNUM:Integer); {clear bit}ππ Varπ SUBJECT : Integer Absolute TARGET;π MASK : Integer;ππ beginπ MASK := not(1 SHL BITNUM);π SUBJECT := SUBJECT and MASKπ end;ππProcedure SETBIT(Var TARGET;BITNUM:Integer;VALUE:Byte);{control}π {Proc. }π beginπ if VALUE = 1 thenπ SBIT(TARGET,BITNUM)π elseπ CBIT(TARGET,BITNUM)π end;ππ 7 05-28-9313:49ALL SWAG SUPPORT TEAM Keyboard Handler IMPORT 43 L {π> I need help on reading the keyboard in a specific way, I need toπ> read it as a whole not a key at a time. I need to do this forπ> the games I make, I have to ba able to hold down one key toπ> perform a Function and then hold down another key and scan bothπ> keys at the same time but to perform 2 different Functions. Forπ> instance, if I hold down the left arrow key to make a Characterπ> run I should be able to hold down the space bar to make himπ> fire a gun at the same time.π> I would Really appreciate any help anyone could give me With this.ππGrab this (TWOKEYS.PAS) and the next 2 messages (KEYINTR.PAS and POLL.PAS).π}ππProgram TwoKeys;ππUsesπ Crt, Poll ; { polled keyboard handler }ππ{ ----- this Program will probably hang a debugger ----- }ππVarπ X, Y : Byte ;ππbeginπ ClrScr ;π X := 40 ;π Y := 12 ;ππ WriteLn( 'Hit keys A S and 1 2 on the keypad' ) ;π WriteLn( ' -- Esc to stop' ) ;ππ While not KeyTable[ EscKey ] doπ beginπ GotoXY( X, Y ) ;π Write( ' ' ) ;ππ { poll the KeyTable }π If KeyTable[ endKey ] and ( X > 1 ) then Dec( X ) ;π If KeyTable[ DownKey ] and ( X < 80 ) then Inc( X ) ;π If KeyTable[ aKey ] and ( Y > 4 ) then Dec( Y ) ;π If KeyTable[ sKey ] and ( Y < 24 ) then Inc( Y ) ;ππ GotoXY( X, Y ) ;π Write( chr( 1 ) ) ;π Delay( 10 ) ;π end ;πend.πππππUnit KeyIntr ; { support For INT 09 routines }ππInterfaceππProcedure CLI ; Inline( $FA ) ; { disable interrupts }πProcedure STI ; Inline( $FB ) ; { enable interrupts }ππ{ cannot be used outside an interrupt Procedure }πProcedure JumpInterrupt( p : Pointer ) ;πInline(π $5B/$58/ { POP BX, AX AX:BX = p }π $89/$EC/ { MOV SP, BP }π $87/$46/$10/ { XCHG AX, [BP+10H] }π $87/$5E/$0E/ { XCHG BX, [BP+0EH] }π $5D/$07/$1F/$5F/$5E/ { POP BP, ES, DS, DI, SI }π $5A/$59/ { POP DX, CX }π $FA/ { CLI }π $CB ) ; { RETF jmp far p }πππFunction Control_Pressed : Boolean ;ππProcedure EOI ;π{ end of interrupt to 8259 }ππFunction ReadScanCode : Byte ;π{ read keyboard }ππProcedure ResetKeyboard ;π{ prepare For next key }ππProcedure StoreKey( Scan, Key : Byte );π{ put key in buffer For INT 16 }πππImplementationππUsesπ Crt ; { Sound, NoSound }ππTypeπ Address = Record { used in Pointer manipulation }π Offset : Word ;π Segment : Word ;π end ;πConstπ BiosDataSegment = $40 ;ππVarπ KeyState : Word Absolute BiosDataSegment:$0017 ;π KeyBufferHead : Word Absolute BiosDataSegment:$001A ;π KeyBufferTail : Word Absolute BiosDataSegment:$001C ;π KeyBufferStart : Word Absolute BiosDataSegment:$0080 ;π KeyBufferend : Word Absolute BiosDataSegment:$0082 ;πππFunction Control_Pressed : Boolean ;πbeginπ Control_Pressed := ( KeyState and 4 ) = 4 ;πend;ππProcedure EOI ;π{ end of interrupt to 8259 interrupt controller }πbeginπ CLI ;π Port[$20] := $20 ;πend ;ππFunction ReadScanCode : Byte ;πbeginπ ReadScanCode := Port[$60] ;πend ;ππProcedure ResetKeyboard ;π{ prepare For next key }πVarπ N : Byte ;πbeginπ N := Port[$61] ;π Port[$61] := ( N or $80 ) ;π Port[$61] := N ;πend ;ππProcedure StoreKey( Scan, Key : Byte ) ;πVarπ{ put key in buffer that INT 16 reads }π P : ^Word ;π N : Word ;πbeginπ address(P).segment := BiosDataSegment ;π N := KeyBufferTail ;π address(P).offset := N ;π Inc( N, 2 ) ; { advance Pointer two Bytes }π If( N = KeyBufferend ) then { end of the circular buffer }π N := KeyBufferStart ;π If( N = KeyBufferHead ) then { buffer full }π beginπ EOI ; { EOI must be done before Exit }π Sound( 2200 ) ; { but before anything that takes a lot }π Delay( 80 ) ; { of time and can be interrupted }π NoSound ;π endπ Elseπ begin { high Byte is scan code, low is ASCII }π P^ := Scan * $100 + Key ; { store key in circular buffer }π KeyBufferTail := N ; { advance tail Pointer }π EOI ;π end ;πend ;ππend.πππππUnit POLL ; { polled keyboard handler }π { does not support F11 or F12 keys } InterfaceππConstπ EscKey = 1 ; { key codes }π aKey = 30 ;π sKey = 31 ;π endKey = 79 ;π DownKey = 80 ;ππVarπ KeyTable : Array[ 1..127 ] of Boolean ;ππ{ KeyTable[ x ] is True when key x is pressed and stays True Until keyπ x is released }πππImplementationππUsesπ Dos, KeyIntr ; { keyboard interrupt support }ππVarπ OldInt09 : Pointer ;π ExitSave : Pointer ;ππProcedure RestoreInt09 ; Far;πbeginπ ExitProc := ExitSave ;π SetIntVec( $09, OldInt09 ) ;πend ;ππProcedure NewInt09 ; interrupt ; Far;πVarπ ScanCode : Byte ;π KeyCode : Byte ;πbeginπ STI ;π ScanCode := ReadScanCode ;π KeyCode := ScanCode and $7F ; { strip make/break bit }π KeyTable[ KeyCode ] := ( ScanCode and $80 ) = 0 ;π ResetKeyboard ;π EOI ;πend ;ππVarπ N : Byte ;ππbeginπ ExitSave := ExitProc ;π ExitProc := addr( RestoreInt09 ) ;ππ For N := 1 to 127 do { no key pressed }π KeyTable[ N ] := False ;ππ GetIntVec( $09, OldInt09 ) ;π SetIntVec( $09, addr( NewInt09 ) ) ;πend.π 8 05-28-9313:49ALL SWAG SUPPORT TEAM Get Keyboard CLICK IMPORT 8 C∞ {$M $800,0,0 } { 2K stack, no heap }π{ This Program caUses a click each timeπ a key is pressed.}πUses Crt, Dos;πVarπ KbdIntVec : Procedure;π{$F+}πProcedure Keyclick; interrupt;πbeginπ if Port[$60] < $80 thenπ { Only click when key is pressed }π beginπ Sound(5000);π Delay(1);π NoSound;π end;π Inline ($9C); { PUSHF -- Push flags }π { Call old ISR using saved vector }π KbdIntVec;πend;π{$F-}πbeginπ { Insert ISR into keyboard chain }π GetIntVec($9,@KbdIntVec);π SetIntVec($9,Addr(Keyclick));π Keep(0); { Terminate, stay resident }π readln;πend.ππ{πActually this works as long as you change the GETinTVEC line, where it saysπ@@KbdIntVec, it should be only one @, odd that borland would have an exampleπthat didn't Compile. (It's a fine example, surprised myself too)π} 9 05-28-9313:49ALL SWAG SUPPORT TEAM Int 09 Support IMPORT 22 ╣º UNIT KeyIntr ; { support for INT 09 16 routines } { Turbo Pascal 5.5+ }ππINTERFACEππTypeπ InterruptProcedure = Procedure ;ππConstπ BiosDataSegment = $40 ;ππProcedure DisableInterrupts ; Inline( $FA ) ; { CLI }πProcedure EnableInterrupts ; Inline( $FB ) ; { STI }πProcedure CallInterrupt( P : Pointer ) ;ππFunction AltPressed : Boolean ;πFunction ControlPressed : Boolean ;πFunction ShiftPressed : Boolean ;ππProcedure EOI ; { end of interrupt to 8259 }πFunction ReadScanCode : Byte ; { read keyboard }πProcedure ResetKeyboard ; { prepare for next key }π { put key in buffer for INT 16 }πFunction StoreKey( Scan, Key : Byte ) : Boolean ;ππIMPLEMENTATIONππTypeπ TwoBytesPtr = ^TwoBytes ;π TwoBytes = { one key in the keyboard buffer }π Recordπ KeyCode,π ScanCode : Byte ;π End ;ππVarπ KeyState : Word Absolute BiosDataSegment:$17 ;π KeyBufferHead : Word Absolute BiosDataSegment:$1A ;π KeyBufferTail : Word Absolute BiosDataSegment:$1C ;π KeyBufferStart : Word Absolute BiosDataSegment:$80 ;π KeyBufferEnd : Word Absolute BiosDataSegment:$82 ;ππProcedure CallInterrupt( P : Pointer ) ;πBeginπ Inline( $9C ) ; { PUSHF }π InterruptProcedure(P) ;πEnd ;ππFunction AltPressed : Boolean ;πBeginπ AltPressed := (KeyState and 8) <> 0 ;πEnd ;ππFunction ControlPressed : Boolean ;πBeginπ ControlPressed := (KeyState and 4) <> 0 ;πEnd ;ππFunction ShiftPressed : Boolean ;πBeginπ ShiftPressed := (KeyState and 3) <> 0 ;πEnd ;ππProcedure EOI ; { end of interrupt to 8259 interrupt controller }πBeginπ Port[$20] := $20 ;πEnd ;ππFunction ReadScanCode : Byte ;πVarπ N : Byte ;πBeginπ N := Port[$60] ; { $FF means keyboard overrun }π ReadScanCode := N ;πEnd ;ππProcedure ResetKeyboard ; { prepare for next key }πVarπ N : Byte ;πBeginπ N := Port[$61] ;π Port[$61] := (N or $80) ;π Port[$61] := N ;πEnd ;ππFunction StoreKey( Scan, Key : Byte ) : Boolean ;πVar { put key in buffer that INT 16 reads }π P : TwoBytesPtr ;π N : Word ;πBeginπ DisableInterrupts ;ππ N := KeyBufferTail ;π P := Ptr( BiosDataSegment, N ) ;ππ Inc( N, 2 ) ;π If( N = KeyBufferEnd ) then { end of the circular buffer }π N := KeyBufferStart ;π If( N = KeyBufferHead ) then { buffer full }π Beginπ EnableInterrupts ;π StoreKey := False ;π Endπ Elseπ Beginπ P^.KeyCode := Key ;π P^.ScanCode := Scan ; { store key in circular buffer }π KeyBufferTail := N ; { advance tail pointer }π EnableInterrupts ;π StoreKey := True ;π End ;πEnd ;πππEND.ππππ 10 05-28-9313:49ALL SWAG SUPPORT TEAM Keyboard SCAN Keys IMPORT 28 |° {π> I need help on reading the keyboard in a specific way, I need to read itπ>as a whole not a key at a time. I need to do this For the games I make, Ihaπ>to ba able to hold down one key to perform a Function and then hold downπ>another key and scan both keys at the same time but to perform 2 differentπ>Functions. For instance, if I hold down the left arrow key to make aCharactπ>run I should be able to hold down the space bar to make him fire agun at thπ>same time.ππ by Sean Palmer, 1993, released to public domainπ}ππUnit keyScan; {for now, ignores extended codes ($E0 prefix)}ππInterfaceππTypeπ scanCode = (π kNone, kEsc, k1, k2, k3, k4, k5, k6, k7, k8, k9, k0, kMinus, kEqual,π kBack, kTab, kQ, kW, kE, kR, kT, kY, kU, kI, kO, kP, kLBracket,π kRBracket, kEnter, kCtrl, kA, kS, kD, kF, kG, kH, kJ, kK, kL, kColon,π kQuote, kTilde, kLShift, kBackSlash, kZ, kX, kC, kV, kB, kN, kM, kComma,π kPeriod, kSlash, kRShift, kPadStar, kAlt, kSpace, kCaps, kF1, kF2, kF3,π kF4, kF5, kF6, kF7, kF8, kF9, kF10, kNum, kScroll, kHome, kUp, kPgUp,π kPadMinus, kLf, kPad5, kRt, kPadPlus, kend, kDn, kPgDn, kIns, kDel,π kSysReq, kUnknown55, kUnknown56, kF11, kF12);ππConstπ kPad7 = kHome;π kPad8 = kUp;π kPad9 = kPgUp;π kPad4 = kLf;π kPad6 = kRt;π kPad1 = kend;π kPad2 = kDn;π kPad3 = kPgDn;π letters = [kQ..kP, kA..kL, kZ..kM];π numbers = [k1..k0, kPad1..kPad3, kPad4..kPad6, kPad7..kPad9];π FunctionKeys = [kF1..kF10, kF11..kF12];π keyPad = [kPadStar, kNum..kDel];ππVarπ keyboard : set of scanCode;π lastKeyDown : scanCode;ππImplementationπUses Dos;ππConstπ normChar : Array [scanCode] of Char = (π {00} #0,^[,'1','2','3','4','5','6','7','8','9','0','-','=',^H,^I,π {10} 'q','w','e','r','t','y','u','i','o','p','[',']',^M,#0,'a','s',π {20} 'd','f','g','h','j','k','l',';','''','`',#0,'\','z','x','c','v',π {30} 'b','n','m',',','.','/',#0,'*',#0,' ',#0,#0,#0,#0,#0,#0,π {40} #0,#0,#0,#0,#0,#0,#0,'7','8','9','-','4','5','6','+','1',π {50} '2','3','0','.',#0,#0,#0,#0,#0);π shiftChar : Array [scanCode] of Char = (π {00} #0,^[,'!','@','#','$','%','^','&','*','(',')','_','+',^H,^I,π {10} 'Q','W','E','R','T','Y','U','I','O','P','{','}',^M,#0,'A','S',π {20} 'D','F','G','H','J','K','L',':','"','~',#0,'|','Z','X','C','V',π {30} 'B','N','M','<','>','?',#0,'*',#0,' ',#0,#0,#0,#0,#0,#0,π {40} #0,#0,#0,#0,#0,#0,#0,'7','8','9','-','4','5','6','+','1',π {50} '2','3','0','.',#0,#0,#0,#0,#0);ππFunction ascii(k : scanCode) : Char;πbeginπ if [kLShift, kRShift] * keyboard <> [] thenπ ascii := shiftChar[k]π elseπ ascii := normChar[k];πend;ππVarπ oldKeyInt : Pointer;ππProcedure keyISR; interrupt;πVarπ k : scanCode;π b : Byte;πbeginπ Asmπ in al, $60;π mov b, al;π and al, $7F;π mov k, al;π pushF;π call [oldKeyInt]; {allow BIOS to process also}π end;π memW[$40 : $1A] := memW[$40 : $1C]; {clear BIOS keyboard buffer}π if shortint(b) >= 0 thenπ beginπ keyboard := keyboard + [k];π lastKeyDown := k;π endπ elseπ if b <> $E0 thenπ keyboard := keyboard - [k]π else ;πend;ππProcedure keybegin;πbeginπ keyboard := [];π lastKeyDown := kNone;π getIntVec(9, oldKeyInt);π setIntVec(9, @KeyISR);πend;ππVarπ ExitSave:Pointer;ππProcedure keyend;πbeginπ setIntVec(9, oldKeyInt);π ExitProc := ExitSave;πend;πππbeginπ keybegin;π ExitSave := ExitProc;π ExitProc := @keyend;πend.π 11 05-28-9313:49ALL SWAG SUPPORT TEAM Lock Keyboard IMPORT 14 HY {$X+}ππ{ Author Trevor J Carlsen. Released into the public domain. Req TP6 }π{ Compile and run this Program and all keyboard input except keys that }π{ make up a valid passWord will be ignored. In this Case the passWord }π{ is '1234' and the scancodes For those keys are stored in a Constant. }π{ to change the passWord Compute the scancodes For the desired passWord}π{ and change the passWord approriately. }ππUsesπ Dos,π Crt;ππVarπ OldInt9 : Pointer; { For storing the old interrupt vector }π passWord : String[4];π pwdlen : Byte Absolute passWord;π πProcedure RestoreOldInt9;π { Restores control to the old interrupt handler }π beginπ SetIntVec($09,OldInt9);π end;ππ{$F+}πProcedure NewInt9; interrupt;π π Constπ masterpwd :String[4] = #2#3#4#5; { '1234' scancodes }π Var π scancode : Byte;ππ Procedure ResetKBD;π Varπ b : Byte;π beginπ b := port[$61]; π port[$61] := b or $80;π port[$61] := b;π port[$20] := $20; { Signals EOI to PIC }π end;π πbeginπ scancode := port[$60]; π if chr(scancode) = masterpwd[pwdlen+1] then beginπ passWord[pwdlen+1] := chr(scancode);π inc(pwdlen);π if passWord = masterpwd thenπ RestoreOldInt9;π endπ else if not odd(scancode shr 7) then { invalid key }π pwdlen := 0;π ResetKBD;πend; π{$F-}ππbeginπ pwdlen := 0;π GetIntVec($09,OldInt9);π SetIntVec($09,@NewInt9);π ReadKey;πend. π π πππTeeCeeπππ--- TC-ED v2.01 π * origin: The Pilbara's Pascal Centre (+61 91 732569) (3:690/644)ππ 12 05-28-9313:49ALL SWAG SUPPORT TEAM Read CTRL/ALT/SHIFT Keys IMPORT 11 {π> I was sitting here thinking about how usefull it would be to be ableπ> to check the status of the different Locks (eg. scroll lock, num lockπ> or how to do it. I think it is some sort of Bios or Dos service??π> Any help would be greatly appreciated.ππThe easiest way is to access BIOS memory at address 40h:17hππ}πProcedure TestKeys;ππVarπ Scroll_Lock,π Caps_Lock,π Num_Lock,π Ins,π Alt,π Ctrl,π Left_Shift,π Right_Shift : Boolean;π Bios_Keys : Byte Absolute $40:$17;ππbeginπ Ins := ((Bios_Keys And $80) = $80);π Caps_Lock := ((Bios_Keys And $40) = $40);π Num_Lock := ((Bios_Keys And $20) = $20);π Scroll_Lock := ((Bios_Keys And $10) = $10);π Alt := ((Bios_Keys And $8) = $8);π Ctrl := ((Bios_Keys And $4) = $4);π Left_Shift := ((Bios_Keys And $2) = $2);π Right_Shift := ((Bios_Keys And $1) = $1);ππ Writeln('Insert : ', Ins);π Writeln('CapsLock : ', Caps_Lock);π Writeln('NumLock : ', Num_Lock);π Writeln('ScrollLock : ', Scroll_Lock);π Writeln('Alt : ', Alt);π Writeln('Control : ', Ctrl);π Writeln('Left Shift : ', Left_Shift);π Writeln('Right Shift : ', Right_Shift);πend;ππbeginπ TestKeys;π Readln;πend. 13 05-28-9313:49ALL SWAG SUPPORT TEAM Read CTL/ALT/SHIFT #2 IMPORT 8 -▐ Uses Dos;πVarπ regs : Registers;π stat : Byte;π inse, caps, numl, scrll, alt, ctrl, lshift, rshift : Boolean;π { declaration of all the bools hidden :) }πbeginπ regs.ah:=2; intr($16,regs);π stat:=regs.al;ππ inSE := stat and 128 <> 0; { Insert on }π CAPS := stat and 64 <> 0; { CapsLock }π NUML := stat and 32 <> 0; { NumLock }π SCRLL := stat and 16 <> 0; { ScrolLock }π ALT := stat and 8 <> 0; { ALT pressed }π CTRL := stat and 4 <> 0; { CTRL pressed }π LSHifT := stat and 2 <> 0; { left Shift " }π RSHifT := stat and 1 <> 0; { right Shift" }ππ Writeln(inSE);π Writeln(CAPS);π Writeln(NUML);π Writeln(SCRLL);π Writeln(ALT);π Writeln(CTRL);π Writeln(LSHifT);π Writeln(RSHifT);πend.π 14 05-28-9313:49ALL SWAG SUPPORT TEAM Read Keyboard STATE Keys IMPORT 17 ½σ {π>Can someone give me some code to make the lights Num lock/capsπ>lock/scroll lock keys to turn on?π}ππProgram KeySet;πConstπ CapsState = $40; { Mask For Caps Lock state }π NumState = $20; { Mask For Num Lock state }π ScrollState = $10; { Mask For Scroll Lock state }πVarπ Kb : Byte Absolute $0040:$0017; { Address of keyboard flags }π I : Byte;π S : String;πbeginπ if ParamCount = 0 thenπ beginπ WriteLn;π WriteLn(' Command line options:');π WriteLn;π WriteLn(' C toggle Cap lock state');π WriteLn(' N toggle Num lock state');π WriteLn(' S toggle Scroll lock state');π WriteLn(' Add + to turn on and - to turn off');π Halt(1);π end;π For I := 1 to ParamCount Doπ beginπ S := ParamStr(I);π S[1] := UpCase(S[1]);π { toggle Caps Lock }π if S = 'C' then Kb := Kb xor CapsState;π { toggle Num Lock }π if S = 'N' then Kb := Kb xor NumState;π { toggle Scroll Lock }π if S = 'S' then Kb := Kb xor ScrollState;π { Set Caps Lock on }π if S = 'C+' then Kb := Kb or CapsState;π { Set Num Lock on }π if S = 'N+' then Kb := Kb or NumState;π { Set Scroll Lock on }π if S = 'S+' then Kb := Kb or ScrollState;π { Set Caps Lock off }π if S = 'C-' then Kb := Kb and not (CapsState or not Kb);π { Set Num Lock off }π if S = 'N-' then Kb := Kb and not (NumState or not Kb);π { Set Scroll Lock off }π if S = 'S-' then Kb := Kb and not (ScrollState or not Kb);π end;ππ Write('Caps Lock : ');π if (Kb and CapsState) = CapsState thenπ WriteLn('ON')π elseπ WriteLn('ofF');ππ Write('Num Lock : ');π if (Kb and NumState) = NumState thenπ WriteLn('ON')π elseπ WriteLn('ofF');ππ Write('Scroll Lock: ');π if (Kb and ScrollState) = ScrollState thenπ WriteLn('ON')π elseπ WriteLn('ofF');πend.ππ{πThis Program will toggle, Turn on, or Turn off the Caps Lock, NumπLock, and Scroll Lock lights. and when its done it tells you theπstate of each key.π}π 15 05-28-9313:49ALL SWAG SUPPORT TEAM Keyboard SCAN Keys IMPORT 86 └A {AM▒Hi everyone, I have a question. I need to know if there is some simpleπAM▒way to do the following. I want to pass as a parameter to a ProcedureπAM▒that will indicate what keypresses are valid. I am doing this alreadyπAM▒for regular keys, but I need to be able to list regular keys as well asπAM▒extended key(mostly Function keys).ππAM▒I do like so,ππAM▒Command_Keys : Set of Char ['Q', 'A', 'K'];πAM▒Is there a way to add extended keys to the above.ππDeclare extended scan codes, then format them into an Array:π}πConstππ(* Function keys *)π F1 = $3B00; ShF1 = $5400; CtrlF1 = $5E00; AltF1 = $6800;π F2 = $3C00; ShF2 = $5500; CtrlF2 = $5F00; AltF2 = $6900;π F3 = $3D00; ShF3 = $5600; CtrlF3 = $6000; AltF3 = $6A00;π F4 = $3E00; ShF4 = $5700; CtrlF4 = $6100; AltF4 = $6B00;π F5 = $3F00; ShF5 = $5800; CtrlF5 = $6200; AltF5 = $6C00;π F6 = $4000; ShF6 = $5900; CtrlF6 = $6300; AltF6 = $6D00;π F7 = $4100; ShF7 = $5A00; CtrlF7 = $6400; AltF7 = $6E00;π F8 = $4200; ShF8 = $5B00; CtrlF8 = $6500; AltF8 = $6F00;π F9 = $4300; ShF9 = $5C00; CtrlF9 = $6600; AltF9 = $7000;π F10 = $4400; ShF10 = $5D00; CtrlF10 = $6700; AltF10 = $7100;π F11 = $8500; ShF11 = $8700; CtrlF11 = $8900; AltF11 = $8B00;π F12 = $8600; ShF12 = $8800; CtrlF12 = $8A00; AltF12 = $8C00;ππ(* Numeric keypad *)π Up = $4800; ShUp = $4838; CtrlUp = $8D00; AltUp = $9800;π Down = $5000; ShDown = $5032; CtrlDown = $9100; AltDown = $A000;π Left = $4B00; ShLeft = $4B34; CtrlLeft = $7300; AltLeft = $9B00;π Right = $4D00; ShRight = $4D36; CtrlRight = $7400; AltRight = $9D00;π Home = $4700; ShHome = $4737; CtrlHome = $7700; AltHome = $9700;πendKey = $4F00; Shend = $4F31; Ctrlend = $7500; Altend = $9F00;π PgUp = $4900; ShPgUp = $4939; CtrlPgUp = $8400; AltPgUp = $9900;π PgDn = $5100; ShPgDn = $5133; CtrlPgDn = $7600; AltPgDn = $A100;π Ins = $5200; ShIns = $5230; CtrlIns = $9200; AltIns = $A200;π Del = $5300; ShDel = $532E; CtrlDel = $9300; AltDel = $A300;π Pad5 = $4C00; ShPad5 = $4C35; CtrlPad5 = $8F00; AltPad5 = $9C00;ππ(* Alphabetic keys *)π LowA = $1E61; UpA = $1E41; CtrlA = $1E01; AltA = $1E00;π LowB = $3062; UpB = $3042; CtrlB = $3002; AltB = $3000;π LowC = $2E63; UpC = $2E43; CtrlC = $2E03; AltC = $2E00;π LowD = $2064; UpD = $2044; CtrlD = $2004; AltD = $2000;π LowE = $1265; UpE = $1245; CtrlE = $1205; AltE = $1200;π LowF = $2166; UpF = $2146; CtrlF = $2106; AltF = $2100;π LowG = $2267; UpG = $2247; CtrlG = $2207; AltG = $2200;π LowH = $2368; UpH = $2348; CtrlH = $2308; AltH = $2300;π LowI = $1769; UpI = $1749; CtrlI = $1709; AltI = $1700;π LowJ = $246A; UpJ = $244A; CtrlJ = $240A; AltJ = $2400;π LowK = $256B; UpK = $254B; CtrlK = $250B; AltK = $2500;π LowL = $266C; UpL = $264C; CtrlL = $260C; AltL = $2600;π LowM = $326D; UpM = $324D; CtrlM = $320D; AltM = $3200;π LowN = $316E; UpN = $314E; CtrlN = $310E; AltN = $3100;π LowO = $186F; UpO = $184F; CtrlO = $180F; AltO = $1800;π LowP = $1970; UpP = $1950; CtrlP = $1910; AltP = $1900;π LowQ = $1071; UpQ = $1051; CtrlQ = $1011; AltQ = $1000;π LowR = $1372; UpR = $1352; CtrlR = $1312; AltR = $1300;π LowS = $1F73; UpS = $1F53; CtrlS = $1F13; AltS = $1F00;π LowT = $1474; UpT = $1454; CtrlT = $1414; AltT = $1400;π LowU = $1675; UpU = $1655; CtrlU = $1615; AltU = $1600;π LowV = $2F76; UpV = $2F56; CtrlV = $2F16; AltV = $2F00;π LowW = $1177; UpW = $1157; CtrlW = $1117; AltW = $1100;π LowX = $2D78; UpX = $2D58; CtrlX = $2D18; AltX = $2D00;π LowY = $1579; UpY = $1559; CtrlY = $1519; AltY = $1500;π LowZ = $2C7A; UpZ = $2C5A; CtrlZ = $2C1A; AltZ = $2C00;ππ(* Number keys, on top row of keyboard *)π Num1 = $0231; Alt1 = $7800;π Num2 = $0332; Ctrl2 = $0300; Alt2 = $7900;π Num3 = $0433; Alt3 = $7A00;π Num4 = $0534; Alt4 = $7B00;π Num5 = $0635; Alt5 = $7C00;π Num6 = $0736; Ctrl6 = $071E; Alt6 = $7D00;π Num7 = $0837; Alt7 = $7E00;π Num8 = $0938; Alt8 = $7F00;π Num9 = $0A39; Alt9 = $8000;π Num0 = $0B30; Alt0 = $8100;ππ(* Miscellaneous *)π Space = $3920;π BkSp = $0E08; CtrlBkSp = $0E7F; AltBkSp = $0E00;π Tab = $0F09; ShTab = $0F00; CtrlTab = $9400; AltTab = $A500;π Enter = $1C0D; CtrlEnter= $1C0A; AltEnter = $1C00;π Esc = $011B; AltEsc = $0100;ππ Minus = $0C2D; CtrlMinus = $0C1F; AltMinus = $8200;π Plus = $0D2B; AltPlus = $8300;πPadMinus = $4A2D; CtrlPadMinus = $8E00; AltPadMinus= $4A00;π PadPlus = $4E2B; CtrlPadPlus = $9000; AltPadPlus = $4E00;π Star = $092A;π PadStar = $372A; AltPadStar = $3700;ππ{AM>I do like so,πAM>Command_Keys : Set of Char ['Q', 'A', 'K'];π >Is there a way to add extended keys to the above.ππ Hi Andrew!π One painless way is to set the high bit For Function keys.π}πUses Crt;πConstπ Home = #199; UArr = #200; PgUp = #201;π LArr = #203; Five = #204; RArr = #205;π endkey = #207; DArr = #208; PgDn = #209;π Ins = #210; Del = #211;ππ CtrlHome = #247; CtrlUP = #141; CtrlPgUp = #138;π CtrlLArr = #243; CtrlFive = #143; CtrlRArr = #244;π Ctrlend = #245; CtrlDown = #145; CtrlPgDn = #246;π CtrlIns = #146; CtrlDel = #147;ππ BackSp = #8;π Tab = #9; STab = #143;π Enter = #13;π Esc = #27;ππ CtrlPrtsc = #242;ππ CtrlA = #1; AltA = #158; Alt1 = #248;π CtrlB = #2; AltB = #176; Alt2 = #249;π CtrlC = #3; AltC = #174; Alt3 = #250;π CtrlD = #4; AltD = #160; Alt4 = #251;π CtrlE = #5; AltE = #146; Alt5 = #252;π CtrlF = #6; AltF = #161; Alt6 = #253;π CtrlG = #7; AltG = #162; Alt7 = #254;π CtrlH = #8; AltH = #163; Alt8 = #255;π CtrlI = #9; AltI = #151; Alt9 = #134;π CtrlJ = #10; AltJ = #164; Alt0 = #135;π CtrlK = #11; AltK = #165; Altminus = #136;π CtrlL = #12; AltL = #166; Altequals = #137;π CtrlM = #13; AltM = #178;π CtrlN = #14; AltN = #177;π CtrlO = #15; AltO = #152;π CtrlP = #16; AltP = #153;π CtrlQ = #17; AltQ = #144;π CtrlR = #18; AltR = #147;π CtrlS = #19; AltS = #159;π CtrlT = #20; AltT = #148;π CtrlU = #21; AltU = #150;π CtrlV = #22; AltV = #175;π CtrlW = #23; AltW = #145;π CtrlX = #24; AltX = #173;π CtrlY = #25; AltY = #149;π CtrlZ = #26; AltZ = #172;ππ F1 = #187; sF1 = #212; CtrlF1 = #222; AltF1 = #232;π F2 = #188; sF2 = #213; CtrlF2 = #223; AltF2 = #233;π F3 = #189; sF3 = #214; CtrlF3 = #224; AltF3 = #234;π F4 = #190; sF4 = #215; CtrlF4 = #225; AltF4 = #235;π F5 = #191; sF5 = #216; CtrlF5 = #226; AltF5 = #236;π F6 = #192; sF6 = #217; CtrlF6 = #227; AltF6 = #237;π F7 = #193; sF7 = #218; CtrlF7 = #228; AltF7 = #238;π F8 = #194; sF8 = #219; CtrlF8 = #229; AltF8 = #239;π F9 = #195; sF9 = #220; CtrlF9 = #230; AltF9 = #240;π F10 = #196; sF10 = #221; CtrlF10 = #231; AltF10 = #241;π F11 = #139; sF11 = #141; CtrlF11 = #154; AltF11 = #156;π F12 = #140; sF12 = #142; CtrlF12 = #155; AltF12 = #157;ππ Key : Char = #0;ππVarπ NextOn : ^Word Absolute $0040:$001A; {keyboard buffer}π NextOff : ^Word Absolute $0040:$001C; {keyboard buffer}π KeyStatusBits : Word Absolute $0040:$0017; {keyboard buffer}π KeyStatus : Recordπ RShift, LShift,π RCtrl, LCtrl,π RAlt, LAlt,π Caps, CapsON,π Ins, InsON,π Scroll, ScrlON,π Num, NumON : Boolean;π end;ππProcedure GetKeyStatus; { Changes KeyStatus Variable }πConst Old : Word = 0;πbeginπ Old := KeyStatusBits;π FillChar(KeyStatus,SizeOf(KeyStatus),0);π With KeyStatus doπ beginπ RShift := ((Old Shr 0 ) and 1) = 1;π LShift := ((Old Shr 1 ) and 1) = 1;π RCtrl := ((Old Shr 2 ) and 1) = 1; { Test For either CTRL Key }π RAlt := ((Old Shr 3 ) and 1) = 1; { Test For either Alt Key }π ScrlON := ((Old Shr 4 ) and 1) = 1; { Is Scroll Lock light on }π NumON := ((Old Shr 5 ) and 1) = 1; { Is Num Lock light on }π CapsON := ((Old Shr 6 ) and 1) = 1; { Is Caps Lock light on }π InsON := ((Old Shr 7 ) and 1) = 1; { Is Insert State on }π LCtrl := ((Old Shr 8 ) and 1) = 1; { This also sets bit 3 }π LAlt := ((Old Shr 9 ) and 1) = 1; { This also sets bit 4 }π Scroll := ((Old Shr 12) and 1) = 1; { This toggles bit 5 }π Num := ((Old Shr 13) and 1) = 1; { This toggles bit 6 }π Caps := ((Old Shr 14) and 1) = 1; { This toggles bit 7 }π Ins := ((Old Shr 15) and 1) = 1; { This toggles bit 8 }π end;πend; { }ππFunction GetKey : Char;πbeginπ If KeyPressed then { Test For BIOS key pressed }π beginπ Key := ReadKey; { Basic BIOS Keyboard Entry }π if Key = #0 thenπ beginπ Key := ReadKey;π Inc(Key,128); { Make Expanded key codes one Byte }π end; { }π end else Key := #0;π GetKey := Key;πend; { }ππProcedure FlushBuffer;πbeginπ Move(NextOn,NextOff,SizeOf(NextOn));πend; { }ππVar test : Char ;πbeginπ ClrScr;π WriteLN('Press Both Shift Keys to end');π Repeatπ GetKeyStatus;π Test := GetKey;π if Test <> #0 Then Write(Test);ππ Until (KeyStatus.RShift and KeyStatus.LShift);πend.π 16 05-28-9313:49ALL SWAG SUPPORT TEAM Keyboard SCAN Codes IMPORT 16 , {πROBERT ROTHENBURGππ>I have created a Menu Bar, Now I think key #77 is left and key #77 isπ>assigned to "M" or one of them. But anyway so when someone pushes theπ>"M" key the menu bar moves. So how can I stop this, I only want it toπ>use the arrow keys and a few letters but not "M".ππYou guessed it: USE BIOS CALLS!π}ππProgram ShowCodes; {* This Program will output the keyboardπ {* scan codes. Use the Function "ScanCode"π {* in your Program once you know the codesπ {* For each keypress *}πUsesπ Crt, Dos;ππFunction Byte2Hex(numb : Byte): String; { Converts Byte to hex String }πConstπ HexChars : Array[0..15] of Char = '0123456789ABCDEF';πbeginπ Byte2Hex[0] := #2;π Byte2Hex[1] := HexChars[numb shr 4];π Byte2Hex[2] := HexChars[numb and 15];πend; { Byte2Hex }ππFunction Numb2Hex(numb : Word): String; { Converts Word to hex String.}πbeginπ Numb2Hex := Byte2Hex(hi(numb)) + Byte2Hex(lo(numb));πend; { Numb2Hex }ππFunction ScanCode : Word;πVarπ reg : Registers; {* You need the Dos Unit For this! *}πbeginπ reg.AH := $10; {* This should WAIT For a keystroke. Ifπ {* you'd like to POLL For a keystroke andπ {* have your Program do other stuff Whileπ {* "waiting" For a key-stroke change toπ {* reg.AH:=$11 instead... *}π intr($16, reg);π ScanCode := reg.AX {* The high-Byte is the "scan code" *}πend; {* The low-Byte is the ASCII Character *}ππbeginπ Repeatπ Writeln(Numb2Hex(ScanCode) : 6)π Until False; {* You'll have to reboot after running this <g>*}πend.ππ{πI "think" the arrow-key scan codes are:ππ $4800 = Up Arrowπ $5000 = Down Arrowπ $4B00 = Left Arrowπ $4D00 = Right Arrowπ}π 17 05-28-9313:49ALL SWAG SUPPORT TEAM Display MAKE/BREAK codes IMPORT 14 Çñ PROGRAM ScanCode ; { display MAKE and BREAK scan codes }ππUSES Crt, Dos, KeyIntr ; { keyboard interrupt support }ππ{ ----- this program will probably hang a debugger ----- }ππVarπ OldInt09 : Pointer ;π ExitSave : Pointer ;ππ{$F+} Procedure RestoreInt09 ;πBeginπ ExitProc := ExitSave ;π SetIntVec( $09, OldInt09 ) ;πEnd ;ππ{$F+} Procedure NewInt09 ; Interrupt ; { return scan code as key's value }πVarπ ScanCode : Byte ;π BufferFull : Boolean ;ππBeginπ EnableInterrupts ;π ScanCode := ReadScanCode ;π ResetKeyboard ;π BufferFull := Not StoreKey( ScanCode, ScanCode ) ;π EOI ;π If BufferFull thenπ Beginπ Sound( 880 ) ;π Delay( 100 ) ;π Sound( 440 ) ;π Delay( 100 ) ;π NoSound ;π End ;π { variation : move the EOI before the beep to after it }π { note the difference when the keyboard overflows }πEnd ;ππ{ see Turbo Pascal 5.0 reference p 450 for a list of scan codes }π{ 6.0 programmers guide p 354 }ππVarπ N : Byte ;ππBEGINπ ExitSave := ExitProc ;π ExitProc := @RestoreInt09 ;π GetIntVec( $09, OldInt09 ) ;π SetIntVec( $09, @NewInt09 ) ;ππ WriteLn( ' Display "make" and "break" scan codes ' ) ;π WriteLn ;π WriteLn( ' Hit the <Esc> key to exit ' ) ;π Repeatπ Delay( 400 ) ; { make it easy to overrun keyboard }π N := Ord( ReadKey ) ; { n is the scan code from NewInt09 }π If N < 128 thenπ WriteLn( 'Make ', n )π Elseπ WriteLn( ' Break ', n - 128 ) ;π Until n = 1 ; { the make code for Esc }πEND.π 18 05-28-9313:49ALL SWAG SUPPORT TEAM Extended Keys IMPORT 28 ìö { MICHAEL NICOLAI }ππUsesπ Dos;ππFunction Get_Extended_KeyCode : Word;πVarπ regs : Registers;πbeginπ regs.ah := $10;π intr($16, regs);π Get_Extended_KeyCode := (regs.ah shl 4) + regs.al;πend;ππ{πThis Function waits Until a key is pressed. The upper Byte contains theπscan code, the lower Byte contains the ASCII code. If you don't want yourπProgram to hang if no key is pressed, use this funtion to check if anyπkeycode is actually present in the keyboard buffer:π}ππFunction Check_For_Extended_KeyStroke : Boolean; { like KeyPressed }πVarπ regs : Registers;πbeginπ regs.ah := $11;π intr($16, regs);π Check_For_Extended_Keystroke := False;π if ((regs.flags and fzero) = 0) thenπ Check_For_Extended_Keystroke := True;πend;ππ{πAfter this Function returns True, the keycode can be read Withπ'Get_Extended_KeyCode'.ππHere are the routines my Functions are based on:ππINTERRUPT 16h - Function 10hπKeyboard - Get enhanced keystrokeππPurpose: Wait For any keyboard input.πAvailable on: AT or PS/2 With enhanced keyboard support only.πRestrictions: none.πRegisters at call: AH = 10h.πReturn Registers: AH = scan code, AL = ASCII codeπDetails: if no keystroke is available, this Function waits Until one isπ placed in the keyboard buffer. Unlike Function 00h, this Functionπ does not discard extended keystrokes.πConflicts: none known.πππINTERRUPT 16h - Function 11hπKeyboard - Check For enhanced keystrokeππPurpose: Checks For availability of any keyboard input.πAvailable on: AT or PS/2 With enhanced keyboard only.πRestrictions: none.πRegisters at call: AH = 11hπReturn Registers: ZF set if no keystroke availableπ ZF clear if keystroke availableπ AH = scan codeπ AL = ASCII codeπDetails: if a keystroke is available, it is not removed from the keyboardπ buffer. Unlike Function 01h, this Function does not discard extendedπ keystrokes.πconflicts: none known.πππINTERRUPT 16h - Function 12hπKeyboard - Get extended shift statesππPurpose: Returns all shift-flags information from enhanced keyboards.πAvailable: AT or PS/2 With enhanced keyboard only.πRestrictions: none.πRegisters at call: AH = 12hπReturn Registers: AL = shift flags 1 (same as returned by Function 02h):π bit 7: Insert activeπ 6: CapsLock activeπ 5: NumLock activeπ 4: ScrollLock activeπ 3: Alt key pressed (either Alt on 101/102-keyπ keyboard)π 2: Crtl key pressed (either Ctrl on 101/102-keyπ keyboard)π 1: left shift key pressedπ 0: right shift key pressedππ AH = shift flags 2:π bit 7: SysRq key pressedπ 6: CapsLock pressedπ 5: NumLock pressedπ 4: ScrollLock pressedπ 3: right Alt key prssedπ 2: right Ctrl key pressedπ 1: left Alt key pressedπ 0: left Ctrl key pressedπDetails: AL bit 3 is set only For left Alt key on many machines. AH bits 7π through 4 are always clear on a Compaq SLT/286.πConflicts: none known.π}π 19 05-28-9313:49ALL SWAG SUPPORT TEAM Trap CTRL-BREAK IMPORT 13 ≤≡ { >> What sort of code do I need to include in a pascal Program (Writen inπ >> Borland Pascal 6.0) to disable CTRL-BREAK and CTRL-C?π}πUnit CAD;ππInterfaceππUses Dos;ππVarπ Int9Handler : Pointer;ππProcedure InterceptCtrlAltDel;πProcedure RestoreCAD;ππ ImplementationππProcedure InterceptCtrlAltDel; Assembler;ππConstπ Ctrl = 4;π Alt = 8;π Del = $53;π KbdPort = $60; { Keyboard port }π KbdCtrlPort = $61; { Keyboard control port }π PIC = $20; { 8259 Interrupt controller }π EOI = $20; { end-of-interrupt }ππ Asmππ PUSH AXπ PUSH DSπ MOV AX, SEG @Dataπ MOV DS, AXπ STIπ in AL, KbdPortπ and AL, 01111111bπ CMP AL, Delπ JNE @2ππ @1 : MOV AH, 2 { BIOS Get keyboard flags service }π inT 16hπ TEST AL, Ctrl + Altπ JNZ @3ππ @2 : PUSHFπ CALL [Int9Handler]π JMP @4ππ @3 : in AL, KbdCtrlPortπ MOV AH, ALπ or AL, 10000000bπ OUT KbdCtrlPort, ALπ XCHG AH, ALπ OUT KbdCtrlPort, ALπ CLIππ MOV AL, EOIπ OUT PIC, ALπ @4 : POP DSπ POP AXπ IRET { make sure we return correctly }πend; { InterceptCtrlAltDel }ππProcedure RestoreCAD;ππbeginπ SETinTVEC (9, Int9Handler);πend; { RestoreCAD }πππbeginπ GETinTVEC (9, Int9Handler);π SETinTVEC (9, @InterceptCtrlAltDel);πend. {Unit CAD}ππ 20 05-28-9313:49ALL SWAG SUPPORT TEAM Trap CTRL-BREAK #2 IMPORT 19 ô╔ {Here is my solution to the problem of trapping Ctrl-Alt-Del. As extra suger,πI'm providing hooks to make this Program TSR. Happy hacking!ππ<<File: trapboot.pas>>ππ{$m 1024,0,0} { Necesarry if you want to make the Program resident. }π{****************************************************************************}π{* NoBoot *}π{* *}π{* This Program stops rebooting While it is running by trapping *}π{* Ctrl-Alt-Del. *}π{* *}π{----------------------------------------------------------------------------}ππUsesπ Dos, Crt;ππVarπ OldKBVec : Pointer;ππ{ Declare all Variables in our interrupt routine global so that no stack }π{ allocation of Variables will be done during the interrupt. }πVarπ Regs : Registers;π temp : Byte;π KBflag1: Byte Absolute $40:$17;ππProcedure MyKB; inTERRUPT;πConstπ EOI = $20;π KB_DATA = $60;π KB_CTL = $61;π inT_CTL = $20;π DEL_sc = $53; { Scancode of the del key }ππbeginπ { Check if Alt and Ctrl are pressed }π if ((KBFlag1 and 4)=4) and ((KBFlag1 and 8)=8) andπ (Port[KB_DATA]= DEL_sc) then begin { get scancode of pressed key }ππ { The following four lines signals that the key is read and that the }π { hardware interrupt is over. }π temp:=Port[Kb_CTL];π Port[KB_CTL]:= temp or $80;π Port[KB_CTL]:= temp;π Port[inT_CTL]:= EOI;ππ { Don't do ANYTHinG here that requires BIOS. This 'Writeln' is using the }π { Crt Unit. }π Writeln('Ouch! That hurts!'); { Show we are here and alive! }π endπ else beginπ intr($69, Regs); { Call the old interrupt routine }π end;πend;ππVarπ Ch : Char;ππbeginπ GetIntVec($9, OldKBVec);π SetIntVec($69, OldKBVec);π SetIntVec($9, @MyKB);ππ { Keep(0); } { Uncomment and erase the rest of the lines to make this Program}ππ Repeatπ Writeln('Press escape to Exit. or Ctrl-Alt-Del if you want...');π ch:= ReadKey;π Until ch=#27;ππ { Forgetting the next line will very surely crash your Computer. }π SetIntVec($9, OldKbVec);πend.π 21 05-28-9313:49ALL SWAG SUPPORT TEAM Trap PAUSE Key IMPORT 10 T {The problem is that the pause key actually paUses the Computerπvia hardware. to reset the pause, you can use the timer interruptπto generate a reset process at every tick. The method hereπwas taken from some Computer magazine.π}ππProgram TrapPause;πUses Dos;πVarπ Timerint : Pointer;π PauseFlag : Boolean;ππProcedure PauseDetect(flags,CS,IP,AX,BX,CX,DX,SI,DI,DS,ES,BP: Word);π {This latches on to the system timer interrupt to detect if theπ pause key has been pressed, and if so to reset the system to allowπ operation to continue and to set Pauseflag = True}π interrupt;π beginπ if memw[$0:$418] and 8 = 8 then {Test bit 3}π beginπ Pauseflag := True;π memw[$0:$418] := memw[$0:$418] and $F7; {Set bit 3 = 0}π end;π Inline($9C/ {PushF}π $3E/ {DS}π $FF/$1E/timerint);{Far call to usual timer interrupt}π end;πππbeginπ Getintvec($08,Timerint); {Save old interrupt For timer}π Setintvec($08,@PauseDetect); {Redirect timer to PauseDetect}πend.ππ 22 05-28-9313:49ALL SWAG SUPPORT TEAM Trap PAUSE Key #2 IMPORT 28 ■ {GE> Does anyone know how to disable the pause key?ππ Here's one way, done in Assembly, With example Turbo Pascal code ...π}π(*******************************************************************)π Program TestTrapPause; { demo disabling the Pause key }π Uses Crt, { import CheakBreak, KeyPressed }π Dos; { import GetIntVec, SetIntVec }π Var old09Vector : Pointer; { to hold original ISR }π loopc, { a loop count }π ppress : Word; { counts Pause key presses }π{-------------------------------------------------------------------}π{ the following Procedures|Functions mask & count Pause keystrokes }π Procedure InitTrapPause( oldVector : Pointer ); EXTERNAL;π Procedure TrapPause; Interrupt; EXTERNAL;π Function PausePresses : Word; EXTERNAL;π Procedure ForgetPaUses; EXTERNAL;π {$L NOPAUSE.OBJ} { Assembly, Near calls }π{-------------------------------------------------------------------}π beginπ ClrScr;π CheckBreak := False; { don't allow Ctrl-Break }ππ GetIntVec( 9, old09Vector ); { get current keyboard ISR }π InitTrapPause( old09Vector ); { pass vector to TrapPause }π SetIntVec( 9, @TrapPause ); { enable TrapPause ISR }π ForgetPaUses; { zero the PausePresses counter }ππ loopc := 0; { initialize }π WriteLn; WriteLn( 'Press the PAUSE key... ');ππ Repeatπ WriteLn;π ppress := PausePresses; { initial Pause press count }π While (ppress = PausePresses) and (not KeyPressed)π do beginπ inC( loopc ); if (loopc = 65535) then loopc := 0;π Write( loopc:5, ' you''ve pressed the Pause key ' );π Write( ppress, ' times',#13 );π end; {While}π Until KeyPressed;ππ SetIntVec( 9, old09Vector ); { restore Pause & release ISR }ππ end {TestTrapPause}.π(*******************************************************************)ππ{ The following TP Program will create NOPAUSE.ARC, which containsπ NOPAUSE.OBJ ...ππ Program A; Var G:File; Const V:Array [ 1..279 ] of Byte =(π26,8,78,79,80,65,85,83,69,46,79,66,74,0,94,248,0,0,0,43,26,67,140,78,π194,29,1,0,0,12,128,26,0,88,224,230,13,156,48,117,230,148,113,17,100,π74,19,47,150,14,0,0,64,96,200,19,34,69,136,96,146,136,162,13,0,1,2,2,π28,131,4,32,200,196,0,12,140,60,145,114,164,8,21,40,65,170,76,41,50,165,π204,68,6,48,101,22,129,34,133,230,204,41,96,38,54,72,226,36,9,21,42,82,π130,64,201,57,115,34,128,4,72,149,50,45,226,99,34,9,68,4,38,138,10,16,π13,84,28,0,1,38,46,226,102,99,209,17,1,46,70,77,44,123,132,64,218,137,π46,142,25,112,10,64,88,214,33,6,243,200,73,115,6,13,29,16,49,114,228,π144,1,226,136,156,50,103,222,200,201,3,98,138,11,43,124,221,148,65,200,π134,14,167,125,80,200,129,225,81,132,206,1,44,157,92,252,115,1,247,223,π92,0,176,64,152,3,1,250,25,0,72,6,92,132,154,56,44,238,105,218,125,56,π201,0,64,12,1,216,0,90,120,67,248,205,133,119,133,223,94,120,51,249,29,π(96 min left), (H)elp, More? 156,88,20,228,188,197,64,39,134,6,58,43,69,2,38,210,1,26,0);π begin Assign(G,'NOPAUSE.ARC'); ReWrite(G,Sizeof(V));π BlockWrite(G,V,1); Close(G); end (*Gbug1.5*).π}π 23 05-29-9308:53ALL SWAG SUPPORT TEAM Various READ Key/Chars IMPORT 19 á» {πAuthor : GAYLE DAVISππI have seen a number of messages recently about keyboard access. Here areπsome neat FAST routines to use instead of ReadKey (Crt Unit). Be advisedπthat in these routines, I add 128 to the HI Byte in order to be able to useπall 256 Characters. Just remember to add 128 to test For all Function keys.π}ππUsesπ Dos;ππFunction GetKey (Var Key : Word) : Boolean; Assembler;π{ determine if key pressed and return it as a Word }π{ if Lo(key) = 0 and Hi(key) <> 0 then we have a FN key ! }πAsmπ MOV AH, 1π INT 16Hπ MOV AL, 0π JE @@1π xor AH, AHπ INT 16Hπ LES DI, Keyπ MOV Word PTR ES : [DI], AXπ MOV AL, 1π @@1 :πend;ππFunction GetChar (Var Key : Char) : Boolean;π{ determine if key pressed and return it as a Char}πVarπ c : Word;πbeginπ Key := #0;π if GetKey (c) thenπ beginπ GetChar := True;π if (LO (c) = 0) and (HI (c) <> 0) thenπ Key := CHR ( HI (c) + 128 ) { add 128 For FN keys }π elseπ Key := CHR (LO (c) );π endπ elseπ GetChar := False;πend;ππFunction KeyReady : Char;π{ looks For and PEEKS at Char but DOES not read it out of buffer }π{ returns the Char it finds or #0 if no Character waiting }πVarπ Regs : Registers;π Key : Byte;πbeginπ Regs.AH := 1; { determine if a key has been }π INTR ( $16, Regs ); { converted to a key code }π if ( Regs.Flags and FZERO = 0 ) thenπ begin { yes, Character now in keyboard buffer }π { determine what it is }π if ( Regs.AL = 0 ) thenπ Key := Regs.AH + 128π elseπ Key := Regs.AL;π endπ elseπ Key := 0;π KeyReady := CHR (Key);πend;ππProcedure ClearKeyBuffer;πVarπ Regs : Registers;πbeginπ Regs.AH := 0; { Clear ENTIRE keyboard }π INTR ( $16, Regs ); { buffer via the BIOS }πend;ππFunction AnyKeyPressed (Ch : Char; Clear : Boolean) : Boolean;π{ Check if a Character is present in buffer, and optionally clears it }πVarπ Key : Char;π Regs : Registers;ππbeginπ Key := KeyReady;π AnyKeyPressed := (Key = Ch);π if (Key = Ch) and Clear thenπ ClearKeyBuffer;πend;π 24 05-31-9307:14ALL SWAG SUPPORT TEAM Simple KEYSTATE Routines IMPORT 17 û+ BB>procedure ShiftStatus(var Ins,π > CapsLock,π > NumLock,π > ScrollLock,π > Alt,π > Ctrl,π > LeftShift,π > RightShift: Boolean);ππI thought this was a little tedious because it is a pain to have allπthose variables....so I made something like this:πππUnit KeyStats;ππInterfaceππ Function RightShift: Boolean;π Function LeftShift: Boolean;π Function Control: Boolean;π Function Alt: Boolean;π Function ScrollLock: Boolean;π Function NumLock: Boolean;π Function CapsLock: Boolean;π Function Insert: Boolean;ππImplementationππUses Dos;ππFunction ShiftState: Byte;πVar Regs: Registers;πBeginπ Regs.Ah:=2;π Intr($16, Regs);π ShiftState:=Regs.Al;πEnd;ππFunction RightShift: Boolean;πBeginπ RightShift:=(ShiftState and 1)<>0;πEnd;ππFunction LeftShift: Boolean;πBeginπ LeftShift:=(ShiftState and 2)<>0;πEnd;ππFunction Control: Boolean;πBeginπ Control:=(ShiftState and 4)<>0;πEnd;ππFunction Alt: Boolean;πBeginπ Alt:=(ShiftState and 8)<>0;πEnd;ππFunction ScrollLock: Boolean;πBeginπ ScrollLock:=(ShiftState and 16)<>0;πEnd;ππFunction NumLock: Boolean;πBeginπ NumLock:=(ShiftState and 32)<>0;πEnd;ππFunction CapsLock: Boolean;πBeginπ CapsLock:=(ShiftState and 64)<>0;πEnd;ππFunction Insert: Boolean;πBeginπ Insert:=(ShiftState and 128)<>0;πEnd;ππEnd.ππHere is a little something that will turn on the light for you.πThe state of the keys below is at addrees $40 and offset $17 in memory, byπchanging the values at that location, you can turn on the CAPS, the NUM etc..πππTypeππ Toggles = (RShift, LShift, Ctrl, Alt,π ScrollLock, NumLock, CapsLock, Insert);π Status = Set of Toggles;ππVarπ KeyStatus : Status Absolute $40:$17;πππExample : to turn on the caps lock, do this :ππ KeyStatus := KeyStatus + [CapsLock];ππ 25 05-31-9308:07ALL SWAG SUPPORT TEAM Ctrl/Alt/Del Trapping IMPORT 21 Qc ==============================================================================π BBS: ─≡─ The Graphics Connection ─≡─ Specialiπ To: JOE JACOBSON Date: 12-20-92 (15:25)πFrom: GUY MCLOUGHLIN Number: 1137 [121] Pascal-ILπSubj: CTRL-ALT-DELETE TRAPPING Status: Publicπ------------------------------------------------------------------------------π ...Unit captured from FIDONET:ππUNIT CAD;ππ{- Area: PASCAL ---------------------}π{ Date: 10-16-92 22:12 }π{ From: Wilbert van Leijen }π{ To: John Martzall }π{ Subj: Ctrl-Alt-Delete }π{------------------------------------}ππINTERFACEππUSES Dos;ππVARπ Int9Handler : POINTER;ππPROCEDURE InterceptCtrlAltDel;πPROCEDURE RestoreCAD;ππ IMPLEMENTATIONππPROCEDURE InterceptCtrlAltDel; Assembler;ππCONSTπ Ctrl = 4;π Alt = 8;π Del = $53;π KbdPort = $60; { Keyboard port }π KbdCtrlPort = $61; { Keyboard control port }π PIC = $20; { 8259 Interrupt controller }π EOI = $20; { End-of-interrupt }ππ ASMπ { Make sure we can access our global data }ππ PUSH AXπ PUSH DSπ MOV AX, SEG @Dataπ MOV DS, AXπ STIππ { Read keyboard port and mask out the 'break bit'.π Check whether the <Del> key was pressed. }ππ IN AL, KbdPortπ AND AL, 01111111bπ CMP AL, Delπ JNE @2ππ { <Del> key was pressed, now check whether <Ctrl> and <Alt>π are held down }ππ @1 : MOV AH, 2 { BIOS Get keyboard flags service }π INT 16hπ TEST AL, Ctrl + Altπ JNZ @3ππ { Chain to previous owner of INT 9 }ππ @2 : PUSHFπ CALL [Int9Handler]π JMP @4ππ { Ctrl-Alt-Del combination found: send the break code }ππ @3 : IN AL, KbdCtrlPortπ MOV AH, ALπ OR AL, 10000000bπ OUT KbdCtrlPort, ALπ XCHG AH, ALπ OUT KbdCtrlPort, ALπ CLIππ { Signal 'End Of Interrupt' to the 8259 interrupt controller chip }ππ MOV AL, EOIπ OUT PIC, ALπ @4 : POP DSπ POP AXπ IRET { make sure we return correctly }πEND; { InterceptCtrlAltDel }ππPROCEDURE RestoreCAD;ππBEGINπ SETINTVEC (9, Int9Handler);πEND; { RestoreCAD }ππBEGINπ GETINTVEC (9, Int9Handler);π SETINTVEC (9, @InterceptCtrlAltDel);πEND.π - Guyπ---π ■ DeLuxe²/386 1.25 #5060 ■π ■ QNet3ß ■ ILink - Canada Remote Systems - Toronto, Ont (416) 798-4713π 26 06-22-9309:10ALL SWAG SUPPORT TEAM Another Ctrl-Break Trap IMPORT 11 ≈c UNIT Break;π{This unit traps the Ctrl-Break sequence}ππINTERFACEπUSESπ DOS;πCONSTπ BrkTrapped : Boolean = FALSE;πPROCEDURE TrapCtrlBrkOn;πPROCEDURE TrapCtrlBrkOff;ππIMPLEMENTATIONπCONSTπ CtrlBrkInterrupt = $1B;π BrkTrapSet : Boolean = FALSE;πVARπ OldBrkVector : Pointer;π{ The following procedure is the new Ctrl-Breakπ Interrupt handler. It traps the Ctrl-Break keyπ sequence and setsa flag for the currentlyπ running program to check. You should do anyπ special processing based on this flag's value}π{$F+}πPROCEDURE NewCtrlBrkVector; INTERRUPT;π{$F-}πBEGINπ INLINE($FA); {Clear interrupts instruction -CLI}π {Reset bit 7 low}π Mem[$0040:$0071] := Mem[$0040:$0071] AND $E;π BrkTrapped := TRUE;π INLINE($FB) {Set interrupts instruction - STI}πEND;ππPROCEDURE TrapCtrlBrkOn;πBEGINπ {Make sure no stacked calls are possible}π IF NOT BrkTrapSet THENπ BEGINπ BrkTrapSet := TRUE;π GetIntVec(CtrlBrkInterrupt, OldBrkVector);π SetIntVec(CtrlBrkInterrupt, @NewCtrlBrkVector)π ENDπEND;ππPROCEDURE TrapCtrlBrkOff;πBEGIN {Check if there is an old vector to restore}π IF BrkTrapSet THENπ BEGINπ BrkTrapSet := FALSE;π SetIntVec(CtrlBrkInterrupt, OldBrkVector)π ENDπEND;ππEND.π 27 06-22-9309:17ALL SWAG SUPPORT TEAM OOP Keyboard Routines IMPORT 25 |2 UNIT Keybd; { Keybd.PAS / Keybd.TPU }ππINTERFACEππUSES Crt, Dos;ππTYPEπ CType = ( UBAR, BLOCK );π Keyboard = OBJECTπ ThisCursor: CType;π PROCEDURE InitKeyBd;π PROCEDURE SetCursor( Cursor: CType );π FUNCTION GetCursor: CType;π FUNCTION GetKbdFlags: Byte;π FUNCTION GetKey( VAR KeyFlags: Byte; VAR FunctKey: Boolean;π VAR Ch: Char ): Boolean;π END;ππ{***************************************************************}π IMPLEMENTATIONπ{***************************************************************}πππ{Keyboard}ππ{-------------------------------------------------π- Name : InitKeyBd -π- Purpose: Set the cursor to underline style -π- and empty keyboard buffer -π-------------------------------------------------}ππPROCEDURE Keyboard.InitKeyBd;π VARπ Ch : Char;π BEGINπ SetCursor( UBAR );π WHILE( KeyPressed ) DO Ch := ReadKey;π END;ππ{-------------------------------------------------π- Name : SetCursor -π- Purpose: Modify number of lines for cursor -π-------------------------------------------------}ππPROCEDURE Keyboard.SetCursor;π VARπ Regs: Registers;π BEGINπ CASE Cursor OFπ UBAR: Regs.Ch := 6;π BLOCK: Regs.Ch := 1;π END;π Regs.CL := 7;π Regs.AH := 1;π Intr( $10, Regs );π END;ππ{-------------------------------------------------π- Name : GetKbdFlags -π- Purpose: Monitor the Insert key -π- Output : Shift key status flag byte -π-------------------------------------------------}ππFUNCTION Keyboard.GetKbdFlags: Byte;π VARπ Regs: Registers;π BEGINπ (* FOR enhanced keyboards: AH := $12 *)π (* FOR normal keyboards: AH := $02 *)π Regs.AH := $12;π Intr( $16, Regs );π IF( Regs.AX AND $80 = $80 ) THEN SetCursor( BLOCK )π ELSE SetCursor( UBAR );π GetKbdFlags := Regs.AX;π END;ππ{-------------------------------------------------π- Name : GetCursor -π- Purpose: Query current cursor state -π-------------------------------------------------}ππFUNCTION Keyboard.GetCursor;π BEGINπ GetCursor := ThisCursor;π END;ππ{-------------------------------------------------π- Name : GetKey -π- Purpose: Get a keypress contents if any -π- Updates a function keypressed flag -π-------------------------------------------------}ππFUNCTION Keyboard.GetKey;π VARπ Result : Boolean;π BEGINπ Result := KeyPressed;π FunctKey := FALSE;π Ch := #$00; {Use this to check for Function key press}π IF Result THEN BEGINπ Ch := ReadKey;π IF( KeyPressed AND ( Ch = #$00 ) ) THEN BEGINπ Ch := ReadKey;π FunctKey := TRUE;π END;π END;π KeyFlags := GetKbdFlags;π GetKey := Result;π END;ππEND.π 28 06-22-9309:21ALL SWAG SUPPORT TEAM Disable PRINT SCREEN IMPORT 14 Qc ===========================================================================π BBS: Canada Remote SystemsπDate: 06-15-93 (09:40) Number: 26422πFrom: CHRIS JANTZEN Refer#: NONEπ To: JANOS SZAMOSFALVI Recvd: NO πSubj: Re: No print screen Conf: (1221) F-PASCALπ---------------------------------------------------------------------------πOn Sunday June 13 1993, Janos Szamosfalvi wrote to All:ππ JS> PROGRAM NoPrintScreen;ππ JS> PROCEDURE Null; Interrupt;π JS> BEGINπ JS> END;ππ JS> BEGINπ JS> SetIntvec($05, @Null);π JS> Keep(1);π JS> END.ππ JS> I have several questions about this code:π JS> a) when it comes to reloading COMMAND.COM, my computer hangsπ JS> with memory allocation error when the above program is inπ JS> memory.π JS> Any idea why?ππAn easy one: You forgot to tell the compiler how much memory your programπwants. Put the following directive at the beginning of your program:ππ{$M 1024,0,0}πPROGRAM NoPrintScreen;π[...]ππThat little "{$M" tells the compiler to tell DOS that you don't want a lot ofπRAM when loaded. Otherwise, your application will allocate (and Keep) allπavailable RAM in the system (effectively making your program a 640K TSR!).ππ JS> b) can anyone tell me how to modify this so PrintScrenπ JS> would be the second Esc key?ππAh, that would be a bit trickier.... You'd need to trap Int 9 using someπassembly code (but my brain is mush right now, so I'll let someone else helpπyou on that).ππChris KB7RNL =->ππ--- GoldED 2.41π * Origin: SlugPoint * Home to fine silly people everywhere (1:356/18.2)π 29 07-16-9306:10ALL YVAN RIVARD Another READKEY in ASM IMPORT 16 Qc ===========================================================================π BBS: The Beta ConnectionπDate: 06-20-93 (12:25) Number: 1081πFrom: YVAN RIVARD Refer#: 984π To: BOB GIBSON Recvd: NO πSubj: console I/O Conf: (232) T_Pascal_Rπ---------------------------------------------------------------------------πBG> You know, since I wrote my own unit to replace CRT, you'd think I'd knowπBG> something like that!πBG> Which brings up a question...my unit uses direct video writes, andπBG> (supposedly) so does TP unless you tell it otherwise. So why does myπBG> unit do a screen faster than TP's units? Not as much overhead?ππYou made your own 'Crt'? I'd like some help!πThe only thing I haven't been able to do so far is the stupid KeyPressed...πI have successfully made a really good ReadKey (return a String [2], so I canπeven read arrows, Functions keys (even F11 and F12))ππHere's my ReadKey (I case anybody would like to have it),πbut I you could help me with the KeyPressed...π(Byt the way, does your 'direct video' is made like this?π Typeπ VideoChar = Recordπ Ascii : Char;π Color : Byte;π end;π Varπ VideoRam : Array [1..25,1..80] of VideoChar Absolute $B800:0000; )ππHere's my 'ReadKey':ππFunction Inkey : String;π Varπ K : Word;π T : String [2];π Beginπ Asmπ mov ah, 10hπ int 16hπ mov K, axπ end;π T := '';π If ((K and 255) = 0) or ((K and 255) = 224) thenπ T := ' '+ Chr (Trunc ((K and 65280) / 256))π elseπ T := Chr (K and 255);π Inkey := T;π End;ππSo what about a 'KeyPressed' ?ππThanks 'n byeπ---π * Info Tech BBS 819-375-3532π * PostLink(tm) v1.06 ITECH (#535) : RelayNet(tm)π 30 07-16-9306:14ALL LAVI TIDHAR Keyboard Buffer Routines IMPORT 26 áÿ Unit TPbuffer;ππ(* TP-Buffer unit version 1.1 /Update *)π(* Using the keyboard's buffer in Turbo Pascal *)π(* This unit is released to the public domain *)π(* by Lavi Tidhar on 5-10-1992 *)ππ(* This unit adds three special functions not *)π(* incuded in the Turbo Pascal regular package *)ππ(* You may alter this source code, move the *)π(* procedures to your own programs. Please do *)π(* NOT change these lines of documentation *)ππ(* This source might teach you about how to *)π(* use interrupts in pascal, and the keyboard's *)π(* buffer. from the other hand, it might not :-) *)ππ(* Used: INT 16, functions 0 and 1 *)π(* INT 21, function 0Ch *)ππ(* INT 16 - KEYBOARD - READ CHAR FROM BUFFER, WAIT IF EMPTYπ AH = 00hπ Return: AH = scan codeπ AL = character *)ππ(* INT 16 - KEYBOARD - CHECK BUFFER, DO NOT CLEARπ AH = 01hπ Return: ZF = 0 character in bufferπ AH = scan codeπ AL = characterπ ZF = 1 no character in buffer *)ππ(* INT 21 - DOS - CLEAR KEYBOARD BUFFERπ AH = 0Chπ AL must be 1, 6, 7, 8, or 0Ah.π Notes: Flushes all typeahead input, then executes function specified by ALπ (effectively moving it to AH and repeating the INT 21 call).π If AL contains a value not in the list above, the keyboard buffer isπ flushed and no other action is taken. *)ππ(* For more details/help etc, you can contact me on: *)ππ(* Mail: Lavi Tidharπ 46 Bantam Dr.π Blairgowrieπ 2194π South Africa π*)ππ(* Phone:π International: +27-11-787-8093π South Africa: (011)-787-8093π*)ππ(* Netmail: The Catacomb BBS 5:7101/45 (fidonet)π The Catacomb BBS 80:80/100 (pipemail)π*)ππInterfaceππUses Dos;ππFunction GetScanCode:Byte; (* Get SCAN CODE from buffer, wait if empty *)πFunction GetKey:Char; (* Get Char from buffer, do NOT wait *)πProcedure FlushKB;ππImplementationππFunction GetKey:Char;π Var Regs:Registers;π Beginπ Regs.AH:=1; (* Int 16 function 1 *)π Intr ($16,Regs); (* Read a charecter from the keyboard buffer *)π GetKey:=Chr (Regs.AL); (* do not wait. If no char was found, CHR(0) *)π End; (* (nul) is returned *)ππFunction GetScanCode:Byte; (* Int 16 function 0 *)π Var Regs:Registers; (* The same as CRT's Readkey, but gives you *)π Begin (* the scan code. Esp usefull when you want to *)π Regs.AH:=0; (* use special keys as the arrows, there will *)π Intr ($16,Regs); (* be a conflict when using ReadKey *)π GetScanCode:=Regs.AH;π End;ππProcedure FlushKB; (* INT 21 function 0C *)π Var Regs:Registers; (* Flushes (erase) the keyboard buffer *)π Begin (* ONLY. No other function is executed *)π Regs.AH:=$0C;π Regs.AL:=2;π Intr ($21,Regs);π End;ππEnd.π 31 08-17-9308:41ALL SWAG SUPPORT TEAM Using 101 Keys - F11/F12 IMPORT 8 ?> { Return Extended keys for 101 Keyboard including F11/F12.π If key is extended, the BOOLEAN = TRUE. This is needed as Home key willπ return the same character value as 'G' }ππUSES DOS;ππVAR Ch : Char;π Ext : BOOLEAN;ππfunction ExReadKey(VAR Extended : BOOLEAN) : char;πvar Regs : registers;πbeginπ Regs.AX := $1000;π Intr($16,Regs);π Extended := (Regs.AL = 0) OR (Regs.AL > 127);π IF Extended THEN ExReadKey := Chr(Regs.AH)π ELSE ExReadKey := Chr(Regs.AL);πend;ππfunction ReadKey : char;π{ This function adds 128 to char if it is extended }πvar Regs : registers;πbeginπ Regs.AX := $1000;π Intr($16,Regs);π IF (Regs.AL = 0) OR (Regs.AL > 127) THENπ ReadKey := Chr(Regs.AH + 128) ELSE ReadKey := Chr(Regs.AL);πend;ππBeginπRepeatπch := ReadKey;πWriteLn(ch,' ',Ext,' ',ORD(Ch));πUntil Ch = #27;πEND. 32 08-17-9308:45ALL SWAG SUPPORT TEAM Set KBD delay/repeat rateIMPORT 16 } {***********************************************π* KBSETUP - set the desired delay/repeat rate *π* for the keyboard. *π***********************************************}ππUSESπ Dos;ππPROCEDURE Usage;π BEGINπ WriteLn;π WriteLn('KBSETUP Command format:');π WriteLn;π WriteLn('KBSETUP n {A | B | C | D} ');π WriteLn;π Write ('n A number from 0 to 31');π WriteLn(' to set the keyboard repeat rate.');π Write (' 0 is the fastest and');π WriteLn(' 31 is the slowest.');π WriteLn;π Write ('A,B,C or D Sets the keyboard');π WriteLn(' delay before repeating');π Write (' to 1/4, 1/2, 3/4 and');π WriteLn(' 1 second.');π Halt(1);π END;ππVARπ KBDelay, KBRepeat, I : byte;π Code : integer;π Regs : Registers;π KeyString : string[1];ππBEGINππ KBDelay := 0;π KBRepeat := 0;ππ IF ParamCount = 0 THENπ Usageπ ELSEπ BEGINπ FOR I := 1 TO ParamCount DOπ BEGINπ KeyString := ParamStr(I);π IF UpCase(KeyString[1]) in ['A'..'D'] THENπ KBDelay := Ord(UpCase(KeyString[1]))π - Ord('A')π ELSEπ BEGINπ {$R-}π Val(ParamStr(I),KBRepeat,Code);π {$R+}π IF (Code <> 0) or (KBRepeat < 0) orπ (KBRepeat > 31) THENπ BEGINπ Write('-- Invalid Letter or');π Write(' Number Entered --> ');π WriteLn(ParamStr(I));π Usageπ ENDπ ENDπ END;ππ { Set the keyboard delay/repeat rate }ππ WITH Regs DOπ BEGINπ AX := $0305;π BH := KBDelay;π BL := KBRepeat;π Intr($16,Regs)π ENDπ END {of the IF/THEN/ELSE instruction}πEND.π 33 08-18-9312:26ALL JOSE ALMEIDA Complete Scan Codes IMPORT 210 ╕y πUNIT HTkb;ππ{ Complete set of all keyboard scan codes.π Part of the Heartware Toolkit v2.00 (HTkb.PAS) for Turbo Pascal.π Author: Jose Almeida. P.O.Box 4185. 1504 Lisboa Codex. Portugal.π I can also be reached at RIME network, site ->TIB or #5314.π Feel completely free to use this source code in any way you want, and, ifπ you do, please don't forget to mention my name, and, give me and Swag theπ proper credits. }ππINTERFACEππconstππ{ letters ······························································ }ππ kb_AA = $1E61; { a }π kb_A = $1E41; { A }π kb_CtrlA = $1E01; { ^A }π { SOH - Start Of Header }π kb_AltA = $1E00; { ALT A }ππ kb_BB = $3062; { b }π kb_B = $3042; { B }π kb_CtrlB = $3002; { ^B }π { STX - Start Of Text }π kb_AltB = $3000; { ALT B }ππ kb_CC = $2E63; { c }π kb_C = $2E43; { C }π kb_CtrlC = $2E03; { ^C }π { ETX - End Of Text }π kb_AltC = $2E00; { ALT C }ππ kb_DD = $2064; { d }π kb_D = $2044; { D }π kb_CtrlD = $2004; { ^D }π { EOT - End Of Transmission }π kb_AltD = $2000; { ALT D }ππ kb_EE = $1265; { e }π kb_E = $1245; { E }π kb_CtrlE = $1205; { ^E }π { ENQ - Enquire }π kb_AltE = $1200; { ALT E }ππ kb_FF = $2166; { f }π kb_F = $2146; { F }π kb_CtrlF = $2106; { ^F }π { ACK - Acknowledge }π kb_AltF = $2100; { ALT F }ππ kb_GG = $2267; { g }π kb_G = $2247; { G }π kb_CtrlG = $2207; { ^G }π { BEL - Bell }π kb_AltG = $2200; { ALT G }ππ kb_HH = $2368; { h }π kb_H = $2348; { H }π kb_CtrlH = $2308; { ^H }π { BS - BackSpace }π kb_AltH = $2300; { ALT H }ππ kb_II = $1769; { i }π kb_I = $1749; { I }π kb_CtrlI = $1709; { ^I }π { HT - Horizontal Tab }π kb_AltI = $1700; { ALT I }ππ kb_JJ = $246A; { j }π kb_J = $244A; { J }π kb_CtrlJ = $240A; { ^J }π { LF - Line Feed }π kb_AltJ = $2400; { ALT J }ππ kb_KK = $256B; { k }π kb_K = $254B; { K }π kb_CtrlK = $250B; { ^K }π { VT - Vertical Tab }π kb_AltK = $2500; { ALT K }ππ kb_LL = $266C; { l }π kb_L = $264C; { L }π kb_CtrlL = $260C; { ^L }π { FF - Form Feed (new page) }π kb_AltL = $2600; { ALT L }ππ kb_MM = $326D; { m }π kb_M = $324D; { M }π kb_CtrlM = $320D; { ^M }π { CR - Carriage Return }π kb_AltM = $3200; { ALT M }ππ kb_NN = $316E; { n }π kb_N = $314E; { N }π kb_CtrlN = $310E; { ^N }π { SO - Shift Out (numbers) }π kb_AltN = $3100; { ALT N }ππ kb_OO = $186F; { o }π kb_O = $184F; { O }π kb_CtrlO = $180F; { ^O }π { SI - Shift In (letters) }π kb_AltO = $1800; { ALT O }ππ kb_PP = $1970; { p }π kb_P = $1950; { P }π kb_CtrlP = $1910; { ^P }π { DEL - Delete }π kb_AltP = $1900; { ALT P }ππ kb_QQ = $1071; { q }π kb_Q = $1051; { Q }π kb_CtrlQ = $1011; { ^Q }π { DC1 - Device Control 1 }π kb_AltQ = $1000; { ALT Q }ππ kb_RR = $1372; { r }π kb_R = $1352; { R }π kb_CtrlR = $1312; { ^R }π { DC2 - Device Control 2 }π kb_AltR = $1300; { ALT R }ππ kb_SS = $1F73; { s }π kb_S = $1F53; { S }π kb_CtrlS = $1F13; { ^S }π { DC3 - Device Control 3 }π kb_AltS = $1F00; { ALT S }ππ kb_TT = $1474; { t }π kb_T = $1454; { T }π kb_CtrlT = $1414; { ^T }π { DC4 - Device Control 4 }π kb_AltT = $1400; { ALT T }ππ kb_UU = $1675; { u }π kb_U = $1655; { U }π kb_CtrlU = $1615; { ^U }π { NAK - Negative Acknowlegde }π kb_AltU = $1600; { ALT U }ππ kb_VV = $2F76; { v }π kb_V = $2F56; { V }π kb_CtrlV = $2F16; { ^V }π { SYN - Syncronize }π kb_AltV = $2F00; { ALT V }ππ kb_WW = $1177; { w }π kb_W = $1157; { W }π kb_CtrlW = $1117; { ^W }π { ETB - End of Text Block }π kb_AltW = $1100; { ALT W }ππ kb_XX = $2D78; { x }π kb_X = $2D58; { X }π kb_CtrlX = $2D18; { ^X - }π { CAN - Cancel }π kb_AltX = $2D00; { ALT X }ππ kb_YY = $1579; { y }π kb_Y = $1559; { Y }π kb_CtrlY = $1519; { ^Y }π { EM - End of Medium }π kb_AltY = $1500; { ALT Y }ππ kb_ZZ = $2C7A; { z }π kb_Z = $2C5A; { Z }π kb_CtrlZ = $2C1A; { ^Z }π { SUB - Substitute }π kb_AltZ = $2C00; { ALT Z }ππ{ numbers ······························································ }ππ kb_1 = $0231; { 1 }π kb_Pad1 = $4F31; { SHIFT 1 number pad }π kb_Alt1 = $7800; { ALT 1 }ππ kb_2 = $0332; { 2 }π kb_Pad2 = $5032; { SHIFT 2 number pad }π kb_Alt2 = $7900; { ALT 2 }π kb_Ctrl2 = $0300; { ^1 (NUL) }ππ kb_3 = $0433; { 3 }π kb_Pad3 = $5133; { SHIFT 3 number pad }π kb_Alt3 = $7A00; { ALT 3 }ππ kb_4 = $0534; { 4 }π kb_Pad4 = $4B34; { SHIFT 4 number pad }π kb_Alt4 = $7B00; { ALT 4 }ππ kb_5 = $0635; { 5 }π kb_Pad5 = $4C35; { SHIFT 5 number pad }π kb_Alt5 = $7C00; { ALT 5 }ππ kb_6 = $0736; { 6 }π kb_Pad6 = $4D36; { SHIFT 6 number pad }π kb_Ctrl6 = $071E; { ^6 (RS) }π kb_Alt6 = $7D00; { ALT 6 }ππ kb_7 = $0837; { 7 }π kb_Pad7 = $4737; { SHIFT 7 number pad }π kb_Alt7 = $7E00; { ALT 7 }ππ kb_8 = $0938; { 8 }π kb_Pad8 = $4838; { SHIFT 8 number pad }π kb_Alt8 = $7F00; { ALT 8 }ππ kb_9 = $0A39; { 9 }π kb_Pad9 = $4939; { SHIFT 9 number pad }π kb_Alt9 = $8000; { ALT 9 }ππ kb_0 = $0B30; { 0 }π kb_Pad0 = $5230; { SHIFT 0 number pad }π kb_Alt0 = $8100; { ALT 0 }ππ{ etc: characters ······················································ }ππ kb_Less = $333C; { < }π kb_Great = $343E; { > }ππ kb_Minus = $352D; { - }π kb_GrayMinus = $4A2D; { - }π kb_CtrlMinus = $0C1F; { ^- }π kb_AltMinus = $8200; { ALT - }π kb_ShiftGrayMinus = $4A2D; { SHIFT - }ππ kb_Plus = $1A2B; { + }π kb_GrayPlus = $4E2B; { + }π kb_WhitePlus = $0D2B; { + }π kb_ShiftGrayPlus = $4E2B; { SHIFT + }ππ kb_Equal = $0D3D; { = }π kb_AltEqual = $8300; { ALT = }ππ kb_Slash = $352F; { / }ππ kb_BackSlash = $2B5C; { \ }π kb_CtrlBackSlash = $2B1C; { ^\ }π { FS - File Separator }ππ kb_OpenBracket = $1A5B; { [ }π kb_CtrlOpenBracket = $1A1B; { ^[ }π { ESC - Escape }ππ kb_CloseBracket = $1B5D; { ] }π kb_CtrlCloseBracket = $1B1D; { ^] }π { GS - Group Separator }ππ kb_OpenParenthesis = $0A28; { ( }ππ kb_CloseParenthesis = $0B29; { ) }ππ kb_OpenBrace = $1A7B; { can't write it }ππ kb_CloseBrace = $1B7D; { can't write it }ππ kb_Apostrophe = $2827; { ' }π kb_Grave = $2960; { ` }ππ kb_Quote = $2822; { " }ππ kb_Tilde = $297E; { ~ }ππ kb_Cater = $075E; { ^ }ππ kb_Semicolon = $273B; { ; }ππ kb_Comma = $332C; { , }ππ kb_Colon = $273A; { : }ππ kb_Period = $342E; { . }π kb_ShiftPeriod = $532E; { SHIFT . number pad }ππ kb_GrayAsterisk = $372A; { * }π kb_WhiteAsterisk = $1A2A; { * }ππ kb_ExclamationPoint = $0221; { ! }ππ kb_QuestionMark = $353F; { ? }ππ kb_NumberSign = $0423; { # }ππ kb_Dollar = $0524; { $ }ππ kb_Percent = $0625; { % }ππ kb_AmpersAnd = $0826; { & }ππ kb_At = $0340; { @ }π { ^@ = 00h }π { NUL - Null Character }π kb_UnitSeparator = $0C5F; { _ }π { ^_ = 1Fh }π { US - Unit Separator }ππ kb_Vertical = $2B7C; { | }ππ kb_Space = $3920; { SPACE BAR }ππ{ functions ···························································· }ππ kb_F1 = $3B00; { F1 }π kb_ShiftF1 = $5400; { SHIFT F1 }π kb_CtrlF1 = $5E00; { ^F1 }π kb_AltF1 = $6800; { ALT F1 }ππ kb_F2 = $3C00; { F2 }π kb_ShiftF2 = $5500; { SHIFT F2 }π kb_CtrlF2 = $5F00; { ^F2 }π kb_AltF2 = $6900; { ALT F2 }ππ kb_F3 = $3D00; { F3 }π kb_ShiftF3 = $5600; { SHIFT F3 }π kb_CtrlF3 = $6000; { ^F3 }π kb_AltF3 = $6A00; { ALT F3 }ππ kb_F4 = $3E00; { F4 }π kb_ShiftF4 = $5700; { SHIFT F4 }π kb_CtrlF4 = $6100; { ^F4 }π kb_AltF4 = $6B00; { ALT F4 }ππ kb_F5 = $3F00; { F5 }π kb_ShiftF5 = $5800; { SHIFT F5 }π kb_CtrlF5 = $6200; { ^F5 }π kb_AltF5 = $6C00; { ALT F5 }ππ kb_F6 = $4000; { F6 }π kb_ShiftF6 = $5900; { SHIFT F6 }π kb_CtrlF6 = $6300; { ^F6 }π kb_AltF6 = $6D00; { ALT F6 }ππ kb_F7 = $4100; { F7 }π kb_ShiftF7 = $5A00; { SHIFT F7 }π kb_CtrlF7 = $6400; { ^F7 }π kb_AltF7 = $6E00; { ALT F7 }ππ kb_F8 = $4200; { F8 }π kb_ShiftF8 = $5B00; { SHIFT F8 }π kb_CtrlF8 = $6500; { ^F8 }π kb_AltF8 = $6F00; { ALT F8 }ππ kb_F9 = $4300; { F9 }π kb_ShiftF9 = $5C00; { SHIFT F9 }π kb_CtrlF9 = $6600; { ^F9 }π kb_AltF9 = $7000; { ALT F9 }ππ kb_F10 = $4400; { F10 }π kb_ShiftF10 = $5D00; { SHIFT F10 }π kb_CtrlF10 = $6700; { ^F10 }π kb_AltF10 = $7100; { ALT F1\0 }ππ{ cursors ······························································ }ππ kb_Up = $4800; { UP }ππ kb_Down = $5000; { DOWN }ππ kb_Left = $4B00; { LEFT }π kb_CtrlLeft = $7300; { ^LEFT }ππ kb_Right = $4D00; { RIGHT }π kb_CtrlRight = $7400; { ^RIGHT }ππ kb_Home = $4700; { HOME }π kb_CtrlHome = $7700; { ^HOME }ππ kb_End = $4F00; { END }π kb_CtrlEnd = $7500; { ^END }ππ kb_PgUp = $4900; { PG UP }π kb_CtrlPgUp = $8400; { ^PG UP }ππ kb_PgDown = $5100; { PG DN }π kb_CtrlPgDown = $7600; { ^PG DN }ππ{ etc: keys ···························································· }ππ kb_Esc = $011B; { ESC }ππ kb_Enter = $1C0D; { RETURN }π kb_CtrlEnter = $1C0A; { ^ENTER }π { LF - Line Feed }ππ kb_BackSpace = $0E08; { BACKSPACE }π kb_CtrlBackspace = $0E7F; { ^BACKSPACE }π { DEL - Delete }ππ kb_Tab = $0F09; { TAB }π kb_Shift_Tab = $0F00; { SHIFT TAB }ππ kb_Ins = $5200; { INSERT }ππ kb_Del = $5300; { DELETE }ππ kb_45 = $565C; { Key 45 [2] }π kb_Shift45 = $567C; { SHIFT KEY 45 [2] }ππ kb_CtrlPrtSc = $7200; { ^PRTSC [2] }ππ kb_CtrlBreak = $0000; { ^BREAK [2] }ππππ{ footnotes ······························································ππ [1] All key codes refers to Interrupt 16h Services 0 and 1,π the "Standard Function", that works with all keyboards types.ππ [2] These key codes are only availlable in the 101/102-key keyboard,π the current IBM standard ("Enhanced") keyboard.ππ··········································································ππINT 16h, 00h (0) Keyboard Read allππ Returns the next character in the keyboard buffer; if no character isπ available, this service waits until one is available.ππ On entry: AH 00hππ Returns: AL ASCII character codeπ AH Scan codeππ ──────────────────────────────────────────────────────────────────────────ππ Notes: The scan codes are the numbers representing theπ location of the key on the keyboard. As new keysπ have been added and the keyboard layout rearranged,π this numbering scheme has not been consistent withπ its original purpose.ππ If the character is a special character, then ALπ will be 0 and the value in AH will be the extendedπ scan code for the key.ππ Use the scan codes to differentiate between keysπ representing the same ASCII code, such as the plusπ key across the top of the keyboard and the gray plusπ key.ππ After the character has been removed from theπ keyboard buffer, the keyboard buffer start pointerπ (at 0:041Ah) is increased by 2. If the start pointerπ is beyond the end of the buffer, the start pointerπ is reset to the start of the keyboard buffer.ππ If no character is available at the keyboard, thenπ the AT, XT-286, and PC Convertible issue an INT 15h,π Service 90h (Device Busy), for the keyboard,π informing the operating system that there is aπ keyboard loop taking place and thereby allowing theπ operating system to perform another task.ππ After every character is typed, the AT, XT-286, andπ PC Convertible issue an INT 15h, Service 91hπ (Interrupt Complete). This allows the operatingπ system to switch back to a task that is waiting forπ a character at the keyboard.ππ See Service 10h for an equivalent service thatπ supports the enhanced (101/102-key) keyboard.ππ··········································································ππINT 16h, 01h (1) Keyboard Status allπ Checks to see if a character is available in the buffer.ππ On entry: AH 01hππ Returns: Zero 0, if character is availableπ 1, if character is not availableπ AL ASCII character code (if character isπ available)π AH Scan code (if character is available)ππ ──────────────────────────────────────────────────────────────────────────ππ Notes: If a character is available, the Zero Flag isπ cleared and AX contains the ASCII value in AL andπ the scan code in AH. The character is not removedπ from the buffer. Use Service 00h to remove theπ character from the buffer. See Service 00h for aπ complete description of the meaning of AX if aπ character is available.ππ This service is excellent for clearing the keyboardπ or allowing a program to be interruptable by aπ specific key sequence.ππ See Service 11h for an equivalent service thatπ supports the enhanced (101/102-key) keyboard.ππ········································································ }ππππIMPLEMENTATIONπππEND. { HTkb.PAS }πππ 34 08-18-9312:27ALL JOSE ALMEIDA Read a keyboard Key IMPORT 9 » { Reads a key from the keyboard buffer, removing it.π Part of the Heartware Toolkit v2.00 (HTkey1.PAS) for Turbo Pascal.π Author: Jose Almeida. P.O.Box 4185. 1504 Lisboa Codex. Portugal.π I can also be reached at RIME network, site ->TIB or #5314.π Feel completely free to use this source code in any way you want, and, ifπ you do, please don't forget to mention my name, and, give me and Swag theπ proper credits. }ππFUNCTION Get_Scan_Code : word;π{ DESCRIPTION:π Reads a key from the keyboard buffer, removing it.π SAMPLE CALL:π NW := Get_Scan_Code;π RETURNS:π The next character in the keyboard buffer.π NOTES:π If no character is availlable, the service performed by this functionπ waits until one is availlable. }ππvarπ HTregs : registers;ππBEGIN { Get_Scan_Code }π HTregs.AH := $00;π Intr($16,HTregs);π Get_Scan_Code := HTregs.AX;πEND; { Get_Scan_Code }π 35 08-18-9312:27ALL JOSE ALMEIDA Check Char Available IMPORT 8 └ { Checks to see it a character is availlable in the DOS keyboard buffer.π Part of the Heartware Toolkit v2.00 (HTkey1.PAS) for Turbo Pascal.π Author: Jose Almeida. P.O.Box 4185. 1504 Lisboa Codex. Portugal.π I can also be reached at RIME network, site ->TIB or #5314.π Feel completely free to use this source code in any way you want, and, ifπ you do, please don't forget to mention my name, and, give me and Swag theπ proper credits. }ππFUNCTION Key_Ready : boolean;π{ DESCRIPTION:π Checks to see it a character is availlable in the DOS keyboard buffer.π SAMPLE CALL:π B := Key_Ready;π RETURNS:π TRUE : If there is a key waiting to be readed in the keyboard buffer;π FALSE : If it is not. }ππvarπ HTregs : registers;ππBEGIN { Key_Ready }π HTregs.AH := $01;π Intr($16,HTregs);π Key_Ready := not (HTregs.Flags and FZero <> 0);πEND; { Key_Ready }π 36 08-18-9312:27ALL JOSE ALMEIDA Read Key - NO REMOVE IMPORT 11 Å { Reads a key from the keyboard buffer, WITHOUT removing it.π Part of the Heartware Toolkit v2.00 (HTkey1.PAS) for Turbo Pascal.π Author: Jose Almeida. P.O.Box 4185. 1504 Lisboa Codex. Portugal.π I can also be reached at RIME network, site ->TIB or #5314.π Feel completely free to use this source code in any way you want, and, ifπ you do, please don't forget to mention my name, and, give me and Swag theπ proper credits. }ππFUNCTION Read_Key : word;π{ DESCRIPTION:π Reads a key from the keyboard buffer, WITHOUT removing it.π SAMPLE CALL:π NW := Read_Key;π RETURNS:π The scan code of the key that is ready to be readen from the buffer, or,π if there is no key in the buffer, returns $FFFF value.π NOTES:π This is a special function. It's only to be called in very specialπ situations. It checks if a key is ready in the keyboardπ buffer. If there is a key, then the key is readed but NOT removedπ from the buffer. The key will remain in the buffer. }ππvarπ HTregs : registers;ππBEGIN { Read_Key }π HTregs.AH := $01;π Intr($16,HTregs);π if not (HTregs.Flags and FZero <> 0) thenπ Read_Key := HTregs.AXπ elseπ Read_Key := $FFFF;πEND; { Read_Key }π 37 08-27-9321:29ALL WILBERT VAN LEIJEN Trapping ALT and CTRL IMPORT 13 ┌ {πWILBERT VAN LEIJENππ> HEy, I have been using some routines to check if certain keys are pressed,π> but I can't figure out how to test For ALT and CTRL key combinations.π}ππ{$G+}ππUsesπ Dos, Crt;ππVarπ KeyHandlerProc : Procedure;π Int15Vector : Pointer;ππConstπ AltStatus : Array [Boolean] of String[5] = (' ', ' ALT ');π CtrlStatus : Array [Boolean] of String[6] = (' ', ' CTRL ');ππProcedure KeyHandler; Far;πVarπ AltKey : Boolean;π CtrlKey : Boolean;π WhereXY : Recordπ x, y : Byte;π end;ππbeginπ AltKey := False;π CtrlKey := False;ππ Asmπ MOV AH, 2π INT 16hπ CMP AL, 8π JNE @1π INC [AltKey]π @1:π CMP AL, 4π JNE @2π INC [CtrlKey]π @2:π end;ππ WhereXY.x := WhereX;π WhereXY.y := WhereY;π GotoXY(66, 25);π Write(AltStatus[AltKey], ' ', CtrlStatus[CtrlKey]);π GotoXY(WhereXY.x, WhereXY.y);πend; { KeyHandler }ππ{ This INT 15h handler is called every time a key is pressed -π provided you're not running this Program on an XT-class machine }ππProcedure TrapKeyboard; Assembler;πAsmπ PUSH BXπ PUSH DSπ PUSHFπ MOV BX, SEG @Dataπ MOV DS, BXπ CMP AH, 4Fhπ JNE @ChainInt15π PUSH ESπ PUSHAπ CALL [KeyHandlerProc]π POPAπ POP ESππ @ChainInt15:π PUSHFπ CALL [Int15Vector]π POPFπ POP DSπ POP BXπ IRETπend; { TrapKeyboard }ππbeginπ GetIntVec($15, Int15Vector);π KeyHandlerProc := KeyHandler;π SetIntVec($15, @TrapKeyboard);π ReadLn;π SetIntVec($15, Int15Vector);πend.π 38 08-27-9321:30ALL INGO ROHLOFF Detect Keys DOWN IMPORT 12 º= { INGO ROHLOFFππ> I've got a problem I just CAN'T solve...π> In a PASCAL-program I want to execute a procedure every time the userπ> presses a key... Fairly easy, right ? But here comes the problem : I wantπ> to repeat that procedure until he RELEASES that key...ππThe only way to do that is to hook up the int 9 (the Keyoard Int...).π}ππProgram KEY;ππusesπ crt, dos;ππvarπ oldint : pointer;π keydown : byte;π keys : array [0..127] of boolean;π scan,π lastkey : byte;ππprocedure init;πvarπ i : byte;πbeginπ clrscr;π for i := 0 to 127 doπ keys[i] := false; {No keys pressed}π keydown := 0;πend;ππprocedure INT9; interrupt;πbeginπ scan := port[$60]; { Get Scancode }π if scan > $7F then { Key released ? }π beginπ if keys[scan xor $80] thenπ dec(keydown);π keys[scan xor $80] := false; {Yes !}π endπ elseπ beginπ if not keys[scan] thenπ inc(keydown);π keys[scan] := true; {NO ! Key pressed }π lastkey := scan;π end;π port[$20] := $20; { Send EndOfInterrupt to Interruptcontroller }πend;ππbeginπ init;π getintvec(9, oldint);π setintvec(9, @INT9);π repeatπ if (keydown > 0) and not keys[1] thenπ beginπ repeatπ sound(lastkey * 30);π until keydown = 0;π nosound;π end;π until keys[1]; {*** Wait for ESC pressed ***}π setintvec(9, oldint);πend.π 39 08-27-9321:30ALL PER-ERIC LARSSON Klick on keypress IMPORT 4 Cì {πPER-ERIC LARSSONππ> How do you determine if a key is still held down after another isπ> pressed ? KeyPressed returns False after second key is pressed and firstπ> key is still held down. ??ππFrom the helpFile For KEEP :π}ππProcedure Keyclick; interrupt;πbeginπ if Port[$60] < $80 thenπ { Only click when key is pressed }π 40 08-27-9321:30ALL TOM MOORE Sound with Keys IMPORT 6 ▄ε {πTOM MOOREππ> In a PASCAL-Program I want to execute a Procedure every time theπ> user presses a key... Fairly easy, right ? But here comes theπ> problem : I want to Repeat that Procedure Until he RELEASES thatπ> key...π}ππUsesπ Crt;πConstπ Done : Boolean = False;πVarπ Ch : Char;πππProcedure MakeSound;πbeginπ if Port[$60] < $80 thenπ beginπ Sound(220);π Delay(100);π end;π if port[$60] > $80 thenπ NoSound;πend;ππbeginπ Repeatπ Repeatπ { While waiting For KeyPressed }π Until KeyPressed;ππ ch := ReadKey;π if ch = #27 then halt;π makeSound;π Until Done;πend.π 41 08-27-9321:31ALL ROB PERELMAN Getting Key Stats IMPORT 10 {█ { ROB PERELMAN }ππUnit KeyStats;ππInterfaceππFunction RightShift : Boolean;πFunction LeftShift : Boolean;πFunction Control : Boolean;πFunction Alt : Boolean;πFunction ScrollLock : Boolean;πFunction NumLock : Boolean;πFunction CapsLock : Boolean;πFunction Insert : Boolean;ππImplementationππUsesπ Dos;ππFunction ShiftState : Byte;πVarπ Regs : Registers;πbeginπ Regs.Ah := 2;π Intr($16, Regs);π ShiftState := Regs.Al;πend;ππFunction RightShift : Boolean;πbeginπ RightShift := (ShiftState and 1) <> 0;πend;ππFunction LeftShift : Boolean;πbeginπ LeftShift := (ShiftState and 2) <> 0;πend;ππFunction Control : Boolean;πbeginπ Control := (ShiftState and 4) <> 0;πend;ππFunction Alt : Boolean;πbeginπ Alt := (ShiftState and 8) <> 0;πend;ππFunction ScrollLock : Boolean;πbeginπ ScrollLock := (ShiftState and 16) <> 0;πend;ππFunction NumLock : Boolean;πbeginπ NumLock := (ShiftState and 32) <> 0;πend;ππFunction CapsLock : Boolean;πbeginπ CapsLock := (ShiftState and 64) <> 0;πend;ππFunction Insert : Boolean;πbeginπ Insert := (ShiftState and 128) <> 0;πend;ππend.π 42 08-27-9321:31ALL SEAN PALMER Stuffing Keyboard IMPORT 14 ╡₧ {πSEAN PALMERππ>> I am assuming you already have a buffer-stuffer that takes a char and aπ>> scan code as input, so I won't post mine.ππ>No, I don't have a keyboard buffer-stuffer.ππYou said you wanted one that DIDN'T need you to tell it what a char'sπscancode was. Well, this would basically require a lookup table ofπpossible scancodes for each ascii char... Plus some that don't haveπcorresponding scancodes. What you could try is to just send a null (#0)πto the routine as a scan code, I believe that's what happens when youπenter a keystroke using the Alt-Numeric Keypad method... so it'd work asπlong as the program you're sending the keys to doesn't need theπscancode.ππHere's an untested version of the method that other guy sent to you...:π}ππprocedure stuffKey(c : char; scan : byte); assembler;πasmπ mov cl, cπ mov ch, scanπ mov ah, 5π int $16π {al=0 if success, 1 if failed, but we just ignore that here}πend;ππso here's a call that just assumes a 0 scan codeππprocedure stuffChar(c : char); assembler;πasmπ mov cl,cπ xor ch,chπ mov ah,5π int $16πend;ππ{πIf you don't wanna go through the BIOS you can do it directly like this:π(plus this is 'pure' Turbo Pascal code.. 8) }ππvarπ head : word absolute $40 : $1A;π tail : word absolute $40 : $1C;π bufStart : word absolute $40 : $80;π bufEnd : word absolute $40 : $82;ππprocedure stuffKey(c : char; scan : byte);πbeginπ memW[$40 : tail] := word(scan) shl 8 + byte(c);π inc(tail, 2);π if tail = bufEnd thenπ tail := bufStart;πend;ππprocedure clearBuffer;πbeginπ tail := head;πend;πππ 43 08-27-9321:32ALL STEVEN TALLENT Locking the Keyboard IMPORT 9 _Θ {πSTEVEN TALLENTππYou can disable the whole keyboard like this:ππSample program by Kerry Sokalskyπ}ππUsesπ KScreen;ππProcedure KeyboardEnable; {unlocks keyboard}πbeginπ Port[$21] := Port[$21] and 253;π end;ππProcedure KeyboardDisable; {locks keyboard}πbeginπ Port[$21] := Port[$21] or 2;πend;ππVarπ X : Integer;ππbeginπ ClrScr;ππ KeyboardDisable;ππ For X := 1 to 10000 doπ beginπ GotoXY(1,1);π Write(X);π If Keypressed thenπ beginπ ClearBuffer;π gotoxy(10,10);π write('This should never occur! - ', X);π end;π end;ππ ClearBuffer; { This is here because even though the keyboard is turned off,π each key is still placed in the buffer }π KeyboardEnable;ππ For X := 1 to 15000 doπ beginπ GotoXY(1,1);π Write(X);π If Keypressed thenπ beginπ ClearBuffer;π gotoxy(10,10);π write('This could occur! - ', X);π end;π end;ππend. 44 08-27-9321:49ALL SEAN PALMER Another Readkey IMPORT 9 g∩ {πSEAN PALMERππ>I want to be able to transparently read a keypress. Inπ>other Words, I'd like to know what key is being pressed,π>but allow the keypress to return to the keyboard buffer orπ>to be read by the Program that's reading it. I'd like thisπ>to Function as a TSR, and I need some way to Record theπ>keypresses. This is a very complicated problem which Iπ>have consulted many advanced Programmers With. Please helpπ>if you are able. Thanks in advance!ππIt returns the Character part of the Char/scan code combo in the currentπhead of the keyboard buffer queue in the bios data area.πThe scan code would be at the location $40:head+1.ππIt would probably be more efficient if you used $0:$41A instead ofπ$40:$1A, but that might cause problems With protected mode.π}ππVarπ head : Word Absolute $40 : $1A;π tail : Word Absolute $40 : $1C;ππFunction peekKey : Char;πbeginπ if head = tail thenπ peekKey := #0π elseπ peekKey := Char(mem[$40 : head]);πend;ππ 45 09-26-9308:47ALL MARTIN RICHARDSON Clear keyboard buffer IMPORT 5 Y- {****************************************************************************π * Procedure ..... ClearKBBufferπ * Purpose ....... To clear the keyboard buffer of pending keystrokesπ * Parameters .... Noneπ * Returns ....... N/Aπ * Notes ......... Noneπ * Author ........ Martin Richardsonπ * Date .......... May 13, 1992π ****************************************************************************}πPROCEDURE ClearKBBuffer;πBEGINπ WHILE KEYPRESSED DO IF ReadKey = #0 THEN;πEND;π 46 09-26-9309:11ALL MARTIN RICHARDSON Check for *ANY* Key IMPORT 7 Yò {*****************************************************************************π * Function ...... IsKeyPressedπ * Purpose ....... To determine if *ANY* key is pressed on the keyboardπ * Parameters .... Noneπ * Returns ....... TRUE if a key is being pressedπ * Notes ......... Even returns TRUE if a shift/ctrl/alt/caps lock key is π * pressed.π * Author ........ Martin Richardsonπ * Date .......... May 13, 1992π *****************************************************************************}πFUNCTION IsKeyPressed: BOOLEAN;πBEGINπ IsKeyPressed := ((MEM[$40:$17] AND $0F) > 0) OR (MEM[$40:$18] > 0)π OR KEYPRESSED;πEND;ππ 47 09-26-9309:12ALL MARTIN RICHARDSON Keyboard Constants IMPORT 27 G {** Keyboard Constant Codes **}ππCONSTπ K_LEFT = #75; K_RIGHT = #77;π K_UP = #72; K_DOWN = #80;π K_HOME = #71; K_END = #79;π K_PGUP = #73; K_PGDN = #81;π K_DEL = #83; K_INS = #82;π K_ENTER = #13; K_ESC = #27;π K_BACKSPACE = #8; K_TAB = #9;ππ K_SPACE = #32; K_SHIFT_TAB = #15;ππ K_CTRL_LEFT = #115; K_CTRL_RIGHT = #116;π K_CTRL_PGUP = #132; K_CTRL_PGDN = #118;π K_CTRL_HOME = #119; K_CTRL_END = #117;π K_CTRL_ENTER = #10;ππ K_F1 = #59; K_F2 = #60;π K_F3 = #61; K_F4 = #62;π K_F5 = #63; K_F6 = #64;π K_F7 = #65; K_F8 = #66;π K_F9 = #67; K_F10 = #68;ππ K_SHIFT_F1 = #84; K_SHIFT_F2 = #85;π K_SHIFT_F3 = #86; K_SHIFT_F4 = #87;π K_SHIFT_F5 = #88; K_SHIFT_F6 = #89;π K_SHIFT_F7 = #90; K_SHIFT_F8 = #91;π K_SHIFT_F9 = #92; K_SHIFT_F10 = #93;ππ K_CTRL_F1 = #94; K_CTRL_F2 = #95;π K_CTRL_F3 = #96; K_CTRL_F4 = #97;π K_CTRL_F5 = #98; K_CTRL_F6 = #99;π K_CTRL_F7 = #100; K_CTRL_F8 = #101;π K_CTRL_F9 = #102; K_CTRL_F10 = #103;ππ K_ALT_F1 = #104; K_ALT_F2 = #105;π K_ALT_F3 = #106; K_ALT_F4 = #107;π K_ALT_F5 = #108; K_ALT_F6 = #109;π K_ALT_F7 = #110; K_ALT_F8 = #111;π K_ALT_F9 = #112; K_ALT_F10 = #113;ππ K_CTRL_A = #1; K_CTRL_B = #2;π K_CTRL_C = #3; K_CTRL_D = #4;π K_CTRL_E = #5; K_CTRL_F = #6;π K_CTRL_G = #7; K_CTRL_H = #8;π K_CTRL_I = #9; K_CTRL_J = #10;π K_CTRL_K = #11; K_CTRL_L = #12;π K_CTRL_M = #13; K_CTRL_N = #14;π K_CTRL_O = #15; K_CTRL_P = #16;π K_CTRL_Q = #17; K_CTRL_R = #18;π K_CTRL_S = #19; K_CTRL_T = #20;π K_CTRL_U = #21; K_CTRL_V = #22;π K_CTRL_W = #23; K_CTRL_X = #24;π K_CTRL_Y = #25; K_CTRL_Z = #26;ππ K_ALT_A = #30; K_ALT_B = #48;π K_ALT_C = #46; K_ALT_D = #32;π K_ALT_E = #18; K_ALT_F = #33;π K_ALT_G = #34; K_ALT_H = #35;π K_ALT_I = #23; K_ALT_J = #36;π K_ALT_K = #37; K_ALT_L = #38;π K_ALT_M = #50; K_ALT_N = #49;π K_ALT_O = #24; K_ALT_P = #25;π K_ALT_Q = #16; K_ALT_R = #19;π K_ALT_S = #31; K_ALT_T = #20;π K_ALT_U = #22; K_ALT_V = #47;π K_ALT_W = #17; K_ALT_X = #45;π K_ALT_Y = #21; K_ALT_Z = #44;π 48 09-26-9310:12ALL ROB PERELMAN Complete Keyboard Unit IMPORT 30 u╠ (*πFrom: ROB PERELMANπSubj: A COMPLETE Keyboard Unit in ASMπ*)ππUNIT Keyboard;ππINTERFACEππ FUNCTION AltPress: Boolean;π FUNCTION CapsOn: Boolean;π FUNCTION CtrlPress: Boolean;π FUNCTION InsertOn: Boolean;π FUNCTION LAltPress: Boolean;π FUNCTION LCtrlPress: Boolean;π FUNCTION LShiftPress: Boolean;π FUNCTION NumOn: Boolean;π FUNCTION RAltPress: Boolean;π FUNCTION RCtrlPress: Boolean;π FUNCTION RShiftPress: Boolean;π FUNCTION ScrollOn: Boolean;π FUNCTION ShiftPress: Boolean;π PROCEDURE ClearKbd;π PROCEDURE PrintScreen;π PROCEDURE SetCaps (CapsLock: Boolean);π PROCEDURE SetEnhKbd (Enhanced: Boolean);π PROCEDURE SetInsert (Ins: Boolean);π PROCEDURE SetNum (NumLock: Boolean);π PROCEDURE SetPrtSc (PrtScOn: Boolean);π PROCEDURE SetScroll (ScrollLock: Boolean);π PROCEDURE SpeedKey (RepDelay, RepRate: Integer);π PROCEDURE TypeIn (Keys: String);ππIMPLEMENTATIONππ{$F+}ππ{ the routines are actually in assembly language }ππ FUNCTION AltPress; external;π FUNCTION CapsOn; external;π FUNCTION CtrlPress; external;π FUNCTION InsertOn; external;π FUNCTION LAltPress; external;π FUNCTION LCtrlPress; external;π FUNCTION LShiftPress; external;π FUNCTION NumOn; external;π FUNCTION RAltPress; external;π FUNCTION RCtrlPress; external;π FUNCTION RShiftPress; external;π FUNCTION ScrollOn; external;π FUNCTION ShiftPress; external;π PROCEDURE ClearKbd; external;π PROCEDURE PrintScreen; external;π PROCEDURE SetCaps; external;π PROCEDURE SetEnhKbd; external;π PROCEDURE SetInsert; external;π PROCEDURE SetNum; external;π PROCEDURE SetPrtSc; external;π PROCEDURE SetScroll; external;π PROCEDURE SpeedKey; external;π PROCEDURE TypeIn; external;ππ{$L KBD}ππBEGINπEND.ππ{ --------------------- CUT HERE -----------------------}ππ1. CUT THIS OUT TO A SEPARATE FILE.π2. Name it KBD.XX.π3. Execute : XX3401 D KBD.XXπ4. KBD.OBJ will be created.ππHere comes the XX-encoded KBD.OBJ file...ππ*XX3401-001215-010792--68--85-18007---------KBD.OBJ--1-OF--1πU+Y+-qhWN0tVQqrEZUQ+++F1HoF3F7U5+0VT+k6-+RCE6U2++ERHFJF1EJ-HjU++0p-GπGItIIoBGFIJCPE++02ZCIoJGJ2xCAE++0IBIIYlEIYJHImI+++VHFJFEIZFHEqw-++NIπKJ-3GIs2+U+8IoV7FZFEIYJHIy+-++JCJIpDHZo+++hGIoV7FZFEIYJHIuE+++hAIoV7πFZFEIYJHIpA+++ZHFJFHEp7DH2n++E+8H2BIIYlEIYJHIoY+++V1H2J-IYh0F-k+++dGπEpFGH3-GFJBHZU++023AJ3-GFJBH++++0Il-H3FEIYJHIno+++ZGEIlII373IpC4+++4πIoJIHZJBHk2+03B1IYxAH2xCf+++0JB3J2ZCIoJGJ0w-++N1EJ-HHosC+++7IoJIFIt6πGo72rU++03BEFIJ2GoJNw+2+u6U2++0W+R4UsU6-++0o+goKoSXFuB5cUy+-mvE0nFMnπqx1UoC1FotD9h+OmzwoVRTX9h+9B3h5coSW1s+59h+9B3XDPoC1FotD9h-9B3cf2oSW1πs+59h-9B3cf2Uy+-mvE0nFPFu6DU+Qio+goKAxjEsB1UoC1FotD9JJNL9c+y++++REPBπ-JxSLQiQ9jwS++1fx9EGnFO8lB5coSXFu6DU+Qio2goKWgHFuB5cUy+-mvE0nFO1s+59πh+9B3XDPoC1EsB1UoC1FotD9JMjg5ch4-XDPXhg9k5E8U+sL-2+TLQc0+6+a3kGzuzFJπWykSWoM40w-p5Gu+DU+++5EE9gIK++0s3WLB6Gv4-U+++-xRmU6+9c+y++++RTCs3XLBπ6Gu75U++9ck4++0u+++C5vUK7QoV9gM4+++-ux7JWykSWoM4AxiCqkj+R+e+1VQ2U-xRπmU6+U0ML-5zfx3K9v-u9FUMnqsvP0w-o0c+C3kEU5pr8+U0+7VQ2ryjoJMjg5ch4-Uj+πRGkiU1s+++-p5vU3BQoV9cYS+++iX+M++9U37EsTiU++nG2ilUM+++2TLQc0+0u+DU++π+5Hni+IZ9gIK++1B6Gv4-U+++CjVJMjg5ch4-XDPXhg9k5E8U+sL--+TLQc0+6+a3kHjπuzGo+goKAxjFuB5HUy+-0wD9JMjg5cdy06dS-fU3+woK5pr8-+-JWylKJlv3RUMnmTmgπWgWu1k0sE+0Ck9wS+DcaWHsO+9g++8m8s+j+9hRp-2Zo18m4l8h8sCoaWHsQ+DgTLptRπmUE+UDk0RkC+l-+izms++Aw++++++++++++++-sk9W+G6G6X3mEZ7X6l4-YE2lwI3WwFπ9FIg4WgP-kkt+WU2-EM68+c90+on11Ep0k61-+I4-kU70WQbAkooBE6SA0sU2W2W6lQYπ7GMmAFUN2-AT3-Mj2GoJ9-cf4kQA8Fsk9W+G6G6X3mEZ7X6l4-YE2lwI3WwF9FIg4WgPπ8SiQSE12Qp+-KU92UZ+-Kk92v3+-JE92x3+-JU92zZ+-JE930J+-JE933Z+-JU934p+-πK+935Z+-Fk938Z+-JE93TJ+-KU93WZ+-Kk93Xp+-LE93Zp+-J+93bZ+-KU93eJ+-KU93πh3+-Kk93ip+-KU947J+-Lk94IZ+-JU85cUc++Rs0UE++++2+wMc0++-oπ***** END OF XX-BLOCK *****π 49 09-26-9310:17ALL MARK OUELLET Flush/Stuff Keyboard IMPORT 6 âÆ {From: MARK OUELLET}π{ FLUSH/STUFF Keyboard w/INT21}ππPROGRAM StuffKbdTest;πuses dos;ππ procedure FlushKbd; Assembler;ππ asmπ Mov AX, $0C00;π Int 21h;π end;ππ procedure StuffKbd(S:string);ππ varπ Regs : registers;π x : byte;π BufferFull : boolean;ππ beginπ FlushKbd;π Inc(S[0]);π S[byte(S[0])] := #13;π x := 1;π repeatπ Regs.AH := $05;π Regs.CL := Byte(S[x]);π Intr($16, Regs);π BufferFull := boolean(Regs.AL);π inc(x);π until BufferFull or (x>byte(S[0]));π end;ππ beginπ StuffKbd('Dir C:\');π end.π 50 09-26-9310:53ALL MARC BIR Keyboard Simulation IMPORT 10 £∩ (*πFrom: MARC BIRπSubj: KEYBOARD Simulationππ{BW>Ok, here is my problem...I am trying to read a string from aπfile, poke it i the keyboard buffer, and then dump the contents ofπthe buffer, so as to simulate that the user actually typed theπstring...This way the user doesnt have to type it all out..Myπprogram works fine, except if the string is more than characters, andπif I try to clear the buffer after 16 characters, all I get the lastπfew characters in the string..Can anyone please help? I would realπlike to finish this dang project! :> Thank you.}ππ{This should work, tested it out. If it returns a false, you have toπstop sending characters, until those that are in the buffer are used,πdoesn't matter what scancode is if you don't use, ditto for asciicode }π*)ππFunction SimulateKey( AsciiCode, ScanCode : Byte ) : Boolean; AssemblerπAsmπ Mov AH, 05Hπ Mov CH, ScanCodeπ Mov CL, AsciiCodeπ Int 16Hπ XOR AX, 1 { bios returns 1 = error, 0 = false, pascal opposite }πEnd; { Returns false if buffer is full }π 51 10-28-9311:28ALL MARC BIR Clear Keyboard QUICK IMPORT 6 áÉ (*==========================================================================πDate: 08-25-93 (00:32)πFrom: MARC BIRπSubj: CLEAR KEYBOARDππ Here's a quick way to clear keyboard buffer:π*)ππProcedure ClearKeyBoard;πBeginπ ASM CLI End;π MemW[$40:$1A] := MemW[$40:$1C];π ASM STI End;πEnd;ππ(*πMemW[$40:$1A] = ptr to next char in cyclical kbd bufferπMemW[$40:$1C] = ptr to last char ""ππ Incase you haven't had data structures, when the next ptr equals theπlast ptr in a cyclical buufer, the buffer is empty.π Hope that helps ( doesn't need CRT )ππ 52 11-02-9305:29ALL BO KALTOFT Disable Ctrl-Break IMPORT 6 H┴ {πBO KALTOFTππ> How can i disable the Pascal interrupt key Ctrl-Break?π}ππConstπ BreakKey : Boolean = False;π BreakOff : Boolean = False;πVarπ BreakSave : Pointer;ππ{$F+}πProcedure BreakHandler; Interrupt;πbeginπ BreakKey := True;πend;π{$F-}πππProcedure CBOff;πbeginπ GetIntVec($1B, BreakSave);π SetIntVec($1B, Addr(BreakHandler));π BreakOff := True;πend;ππProcedure CBOn;πbeginπ SetIntVec($1B, BreakSave);π BreakOff := False;πend;ππbeginπ BreakSave := Nil;π CBOff; {disable}π .π .π .π CBOn; {enable}πend.ππ 53 11-02-9305:58ALL JAN DOGGEN a VERY Complete KB Unit IMPORT 123 ≤É Unit KeybFAQ;π(* This is version 0.90 of KEYBFAQ, a Unit that answers two questionsπ * often asked in the Pascal message area's:π * - How do I change my cursor ?π * - How can I perform input of String With certain limitationsπ * (such as 'maximum length', 'only numbers' etc.)π *π * I will distribute this Unit *ONCE* in message form (three messages)π * because it takes up 500 lines of code. It is untested code, cut fromπ * my Unit library, and distributed *as is* With no other documentationπ * than these initial lines. You can use this code in your apps as you like,π * and you can redistribute it, provided you:π * - redistribute *source* code;π * - do not Charge anything For the source code;π * - give me credit For the original code if you change anything;π * - keep this 'documentation' With it.π * (Loosely translated: common decency is enough)π * Copyright will formally remain mine.π *π * Please do not respond about this code. I am going away For a few weeksπ * and will distribute version 1.0 in ZIP form after that. That packageπ * will have *tested* code, docs and examples.π *π * Some notes about this code:π * - Use it always, or don't use it. I.e. if you start using GetKeyπ * you should use that throughout your Program, and drop all ReadKeys.π * - The redefinition of Char into Key has two reasons:π * - it allows better Type checkingπ * - it allows future changes to the internal representation of theπ * Key Type (I plan to make it a Word Type to handle the overlapπ * in key definitions that is still present, and/or adapt Unicodeπ * Character definitions)π * - The overlap in the Constant key definitions may lookπ * problematic, but in the years I have been using this, it has notπ * posed any problems, generally because you only allow those keysπ * that have a meaning For your app.π *π * Happy Pascalling,π * Jan Doggen, 27/8/93 *)ππInterfaceππTypeπ Key = Char;π KeySet = Set of Key;π (* See later in this Interface section For defined sets *)ππVarπ BlankChar : Char; (* Char used by GetStr to fill the bar; default ' ' *)ππProcedure FlushKeyBuf;π(* Clears the BIOS keyboard buffer *)ππFunction InsertStatus : Boolean;πProcedure SetInsertStatus(On : Boolean);ππProcedure NiceBeep;π(* Replaces the system beep With a more pleasant one. *)ππTypeπ CursType = (NOCUR, LINECUR, BLOCKCUR);ππProcedure SetCursor(CType: CursType);π(* SetCursor sets a block or line cursor, or no cursor. *)ππFunction GetVidMode : Byte;π(* Return BIOS video mode *)ππFunction MonoChrome(Vmode : Byte) : Boolean;π(* Returns True if a monochrome video mode is specified *)ππFunction WinLeft : Byte;πFunction WinRight : Byte;πFunction WinTop : Byte;πFunction WinBottom : Byte;π(* Return Absolute co-ordinates of current Window *)ππFunction RepeatStr(Str : String; N : Integer) : String;π(* Returns a String consisting of <N> repetitionsof <Str>. *)ππFunction GetKey : Key;π(* Returns a Variable of Type Key; see the table below For the definitions.π * GetKey also accepts the <Alt-numeric keypad> ASCII codes. *)ππVarπ ClearOnFirstChar,π WalkOut,π StartInFront : Boolean;π (* These Booleans influence the way in which GetStr operates:π *π * With WalkOut = True: the left and right arrow keys also act as ExitKeysπ * when they bring us 'outside' of the Word (we Exit the Procedure).π *π * With ClearOnFirstChar = True: if the first key Typed is a Character,π * the initial Str is cleared.π *π * With StartInFront = True: the cursor will be positioned at the firstπ * Character when we start the Procedure (instead of after the last)π *π * Default settings For these Booleans are False. *)ππProcedure GetStr(Xpos, Ypos,π MaxLen,π Ink, Paper : Byte;π AllowedKeys,π ExitKeys : KeySet;π BeepOnError : Boolean;π Var Str : String;π Var ExitKey : Key);π(* Reads a String of max. <MaxLen> Characters starting at relative positionπ * <XPos,YPos>. A bar of length <MaxLen> is placed there With colorsπ * <Ink> on <Paper>. An initial value For the String returned can beπ * passed With <Str>.π *π * - BeepOnError indicates audio feedback on incorrect keypressesπ * - AllowedKeys is a set of Keys that may be entered. if AllowedKeys = [],π * all keys are allowed.π * - ExitKeys is a set of Keys that stop the Procedure; <Str> will thenπ * contain the edited String and <ExitKey> will be key that made us Exit.π * if ExitKeys is [], it will be replaced by [Enter,Escape].π * The keys you specify in ExitKeys, do not have to be specified inπ * AllowedKeys. *)ππFunction WaitKey(LegalKeys : Keyset; Flush : Boolean) : Key;π(* Waits For one of the keys in LegalKeys to be pressed, then returns this.π * if <Flush> = True, the keyboard buffer is flushed first. *)ππConstπ Null = #0; CtrlA = #1; F1 = #187; Home = #199;π BSpace = #8; CtrlB = #2; F2 = #188; endKey = #207;π Tab = #9; CtrlC = #3; F3 = #189; PgUp = #201;π Lfeed = #10; CtrlD = #4; F4 = #190; PgDn = #209;π Ffeed = #12; CtrlE = #5; F5 = #191; Left = #203;π CReturn = #13; CtrlF = #6; F6 = #192; Right = #205;π Escape = #27; CtrlG = #7; F7 = #193; Up = #200;π ShiftTab = #143; CtrlH = #8; F8 = #194; Down = #208;π CtrlPrtsc = #242; CtrlI = #9; F9 = #195; Ins = #210;π Enter = #13; CtrlJ = #10; F10 = #196; Del = #211;π Esc = #27; CtrlK = #11; ShiftF1 = #212; CtrlLeft = #243;π Space = #32; CtrlL = #12; ShiftF2 = #213; CtrlRight = #244;π CtrlM = #13; ShiftF3 = #214; CtrlendKey = #245;π { Note the } CtrlN = #14; ShiftF4 = #215; CtrlPgdn = #246;π { overlap of } CtrlO = #15; ShiftF5 = #216; CtrlPgup = #127;π { Ctrl-keys } CtrlP = #16; ShiftF6 = #217; CtrlHome = #247;π { and others ! } CtrlQ = #17; ShiftF7 = #218;π CtrlR = #18; ShiftF8 = #219;π CtrlS = #19; ShiftF9 = #220;π CtrlT = #20; ShiftF10 = #221;π CtrlU = #21; CtrlF1 = #222;π CtrlV = #22; CtrlF2 = #223;π CtrlW = #23; CtrlF3 = #224;π CtrlX = #24; CtrlF4 = #225;π CtrlY = #25; CtrlF5 = #226;π CtrlZ = #26; CtrlF6 = #227;π AltQ = #144; CtrlF7 = #228;π AltW = #145; CtrlF8 = #229;π AltE = #146; CtrlF9 = #230;π AltR = #147; CtrlF10 = #231;π AltT = #148; AltF1 = #232;π AltY = #149; AltF2 = #233;π AltU = #150; AltF3 = #234;π AltI = #151; AltF4 = #235;π AltO = #152; AltF5 = #236;π AltP = #153; AltF6 = #237;π AltA = #158; AltF7 = #238;π AltS = #159; AltF8 = #239;π AltD = #160; AltF9 = #240;π AltF = #161; AltF10 = #241;π AltG = #162;π AltH = #163;π AltJ = #164;π AltK = #165;π AltL = #166; Alt1 = #248;π AltZ = #172; Alt2 = #249;π AltX = #173; Alt3 = #250;π AltC = #174; Alt4 = #251;π AltV = #175; Alt5 = #252;π AltB = #176; Alt6 = #253;π AltN = #177; Alt7 = #254;π AltM = #178; Alt8 = #255; { No Alt9 or Alt0 ! }ππ{ SETS }π LetterKeys : KeySet = ['A'..'Z','a'..'z'];π SpecialKeys : KeySet =π ['!','?','b','a','a','a','a','a','A','a','A','A','e','e','e',π 'e','E','i','i','i','i','o','o','o','o','o','O','u','u','u',π 'u','U','c','C','n','N'];π UpKeys : KeySet = ['A'..'Z'];π LowKeys : KeySet = ['a'..'z'];π VowelKeys : KeySet = ['a','e','i','o','u','A','E','I','O','U'];π DigitKeys : KeySet = ['0'..'9'];π OperatorKeys : KeySet = ['*','/','+','-'];π YNKeys : KeySet = ['y','n','Y','N'];π JNKeys : KeySet = ['j','n','J','N'];π BlankKeys : KeySet = [#0..#32];π AllKeys : KeySet = [#0..#255];π FKeys : KeySet = [F1..F10];π ShiftFKeys : KeySet = [ShiftF1..ShiftF10];π AltFKeys : KeySet = [AltF1..AltF10];π CtrlFKeys : KeySet = [CtrlF1..CtrlF10];π AllFKeys : KeySet = [F1..F10,ShiftF1..AltF10];ππImplementationππUses Crt,Dos;ππProcedure NiceBeep; (* Replaces the system beep With a more pleasant one. *)πbeginπ Sound(300);π Delay(15);π NoSound;πend;πππProcedure FlushKeyBuf;πVarπ Ch : Char;πbeginπ While KeyPressed doπ Ch := ReadKey;πend;πππFunction InsertStatus : Boolean;πVarπ Regs : Registers;πbeginπ Regs.AH := 2;π Intr($16, Regs);π InsertStatus := ((Regs.AL and 128) = 128);πend;πππProcedure SetInsertStatus(On: Boolean);πbeginπ if ON thenπ Mem[$0040:$0017] := Mem[$0040:$0017] or 128π elseπ Mem[$0040:$0017] := Mem[$0040:$0017] and 127;πend;πππFunction GetVidMode: Byte;πVarπ Regs : Registers;πbeginπ Regs.AH := $0F;π Intr($10, Regs);π GetVidMode := Regs.AL;πend;πππFunction MonoChrome(Vmode : Byte) : Boolean;πbeginπ MonoChrome := (VMode in [0,2,5,6,7,15,17]);πend;πππFunction WinLeft : Byte;πbeginπ WinLeft := Lo(WindMin) + 1;πend;πππFunction WinRight : Byte;πbeginπ WinRight := Lo(WindMax) + 1;πend;πππFunction WinTop : Byte;πbeginπ WinTop := Hi(WindMin) + 1;πend;πππFunction WinBottom : Byte;πbeginπ WinBottom := Hi(WindMax) + 1;πend;πππFunction RepeatStr(Str : String; N : Integer) : String;πVarπ Result : String;π I, J,π NewLen,π Len : Integer;πbeginπ Len := Length(Str);π NewLen := N * Length(Str);π Result[0] := Chr(NewLen);π J := 1;π For I := 1 to N DOπ beginπ Move(Str[1], Result[J], Len);π Inc(J, Len);π end;π RepeatStr := Result;πend;πππProcedure SetCursor(CType : CursType);πVarπ VM : Byte;π Regs : Registers;πbeginπ VM := GetVidMode;π With Regs DOπ Case CType OFπ NOCUR :π beginπ Regs.CX := $2000; { Off-screen cursor position }π Regs.AH := 1;π end;ππ LINECUR : beginπ AX := $0100;π BX := $0000;π if MonoChrome(VM) thenπ CX := $0B0Cπ elseπ CX := $0607π end;ππ BLOCKCUR :π beginπ AX := $0100;π BX := $0000;π if MonoChrome(VM) thenπ CX := $010Dπ elseπ CX := $0107;π end;π end;π Intr($10, Regs);πend;πππFunction GetKey : Key;πVarπ Ch : Char;πbeginπ Ch := ReadKey;π if Ch = #0 thenπ beginπ Ch := ReadKey;π if Ch <= #127 thenπ GetKey := Chr(Ord(Ch) or $80)π elseπ if Ch = #132 thenπ GetKey := CtrlPgUpπ elseπ GetKey := Null;π endπ elseπ GetKey := Ch;πend;ππProcedure GetStr(XPos, YPos, MaxLen, Ink, Paper : Byte; AllowedKeys,π ExitKeys : KeySet; BeepOnError : Boolean;π Var Str : String; Var ExitKey : Key);πVarπ CursPos,π LeftPos,π TopPos,π RightPos,π BottomPos,π X, Y : ShortInt;π InsFlag,π OAFlag,π FirstKey : Boolean;π InKey : Key;π OldTextAttr : Byte;π OldWindMin,π OldWindMax : Word;ππ Procedure CleanUp;π { Second level; called when we leave }π beginπ WindMin := OldWindMin;π WindMax := OldWindMax;π TextAttr := OldTextAttr;π ExitKey := InKey;π end;ππbeginπ LeftPos := WinLeft;π RightPos := WinRight;π TopPos := WinTop;π BottomPos := WinBottom;π X := XPos + LeftPos - 1;π Y := YPos + TopPos - 1;π InsFlag := InsertStatus;π if ExitKeys = [] thenπ ExitKeys := [Enter, Escape];π if AllowedKeys = [] thenπ AllowedKeys := AllKeys;π (* Save old settings here; restore them in proc CleanUp when Exiting *)π OldWindMin := WindMin;π OldWindMax := WindMax;π WindMin := 0; { Set Absolute Window co-ordinates and }π WindMax := $FFFF; { prevent scroll at lower right Character. }π OldTextAttr := TextAttr;π TextAttr := ((Paper SHL 4) or Ink) and $7F;π { Note: the 'AND $F' ensures that blink is off }π if StartInFront thenπ CursPos := 1π elseπ if Length(Str)+1 < MaxLen thenπ CursPos := Length(Str) + 1π elseπ CursPos := MaxLen;π FirstKey := True;π if InsFlag thenπ SetCursor(BLOCKCUR)π elseπ SetCursor(LINECUR);π Repeatπ if CursPos < 1 thenπ if WalkOut thenπ beginπ CleanUp;π Exit;π endπ elseπ if BeepOnError thenπ beginπ NiceBeep;π CursPos := 1;π end;ππ if (CursPos > Length(Str) + 1) thenπ if WalkOut thenπ beginπ CleanUp;π Exit;π endπ elseπ if BeepOnError thenπ beginπ NiceBeep;π CursPos := Length(Str) + 1;π end;ππ if CursPos > MaxLen thenπ if WalkOut and (InKey = Right) thenπ beginπ CleanUp;π Exit;π endπ elseπ beginπ if BeepOnError thenπ NiceBeep;π CursPos := MaxLen;π end;ππ GotoXY(X, Y);π Write(Str + RepeatStr(BlankChar, MaxLen - Length(Str)));π GotoXY(X + CursPos - 1, Y);π InKey := GetKey;ππ if InKey in ExitKeys thenπ beginπ CleanUp;π Exit;π end;ππ Case InKey OFπ Left : Dec(CursPos);π Right : Inc(CursPos);π CtrlLeft, Home : CursPos := 1;π CtrlRight, endKey : CursPos := Length(Str) + 1;π Tab : Inc(CursPos,8);π ShiftTab : Dec(CursPos,8);ππ Ins :π beginπ InsFlag := not InsFlag;π if InsFlag thenπ SetCursor(BLOCKCUR)π elseπ SetCursor(LINECUR);π end;ππ Del :π if CursPos > Length(Str) thenπ beginπ if BeepOnError thenπ NiceBeep;π endπ elseπ Delete(Str, CursPos, 1);ππ BSpace :π if CursPos = 1 thenπ if Length(Str) = 1 thenπ Str := ''π elseπ beginπ if BeepOnError thenπ NiceBeep;π endπ elseπ beginπ Delete(Str, CursPos - 1, 1);π Dec(CursPos);π end;π elseπ beginπ (* Note that 'AllowedKeys' that also have aπ * meaning as a control key have already beenπ * processed, so they will not be handled here. *)π if InKey in AllowedKeys thenπ beginπ if ClearOnFirstChar and FirstKey thenπ beginπ Str := '';π CursPos := 1;π end;π if (CursPos = MaxLen) thenπ beginπ Str[CursPos] := InKey;π Str[0] := Chr(MaxLen);π endπ elseπ if InsFlag thenπ beginπ Insert(InKey,Str,CursPos);π if Length(Str) > MaxLen thenπ Str[0] := Chr(MaxLen);π endπ elseπ beginπ Str[CursPos] := InKey;π if CursPos > Length(Str) thenπ Str[0] := Chr(CursPos);π end;ππ Inc(CursPos);π endπ elseπ if BeepOnError thenπ NiceBeep;π end;π end;ππ FirstKey := False;π Until 0 = 1;πend;πππFunction WaitKey(LegalKeys : Keyset; Flush : Boolean) : Key;πVarπ K : Key;πbeginπ if Flush thenπ FlushKeybuf;π Repeatπ K := GetKey;π Until K in LegalKeys;π WaitKey := K;πend;πππbeginπ BlankChar := ' ';π WalkOut := False;π ClearOnFirstChar := False;π StartInFront := False;πend.π 54 11-02-9305:59ALL SWAG SUPPORT TEAM Nice Keyboard Handler IMPORT 21 ≈V UNIT KeyIntr; { support for INT 09 16 routines } { Turbo Pascal 5.5+ }ππINTERFACEππTypeπ InterruptProcedure = Procedure;ππConstπ BiosDataSegment = $40;ππProcedure DisableInterrupts; Inline($FA); { CLI }πProcedure EnableInterrupts; Inline($FB); { STI }πProcedure CallInterrupt(P : Pointer);ππFunction AltPressed : Boolean;πFunction ControlPressed : Boolean;πFunction ShiftPressed : Boolean;ππProcedure EOI; { end of interrupt to 8259 }πFunction ReadScanCode : Byte; { read keyboard }πProcedure ResetKeyboard; { prepare for next key }π { put key in buffer for INT 16 }πFunction StoreKey(Scan, Key : Byte) : Boolean;ππIMPLEMENTATIONππTypeπ TwoBytesPtr = ^TwoBytes;π TwoBytes = Record { one key in the keyboard buffer }π KeyCode,π ScanCode : Byte;π End;ππVarπ KeyState : Word Absolute BiosDataSegment : $17;π KeyBufferHead : Word Absolute BiosDataSegment : $1A;π KeyBufferTail : Word Absolute BiosDataSegment : $1C;π KeyBufferStart : Word Absolute BiosDataSegment : $80;π KeyBufferEnd : Word Absolute BiosDataSegment : $82;ππProcedure CallInterrupt(P : Pointer);πBeginπ Inline($9C); { PUSHF }π InterruptProcedure(P);πEnd;ππFunction AltPressed : Boolean;πBeginπ AltPressed := (KeyState and 8) <> 0;πEnd;ππFunction ControlPressed : Boolean;πBeginπ ControlPressed := (KeyState and 4) <> 0;πEnd;ππFunction ShiftPressed : Boolean;πBeginπ ShiftPressed := (KeyState and 3) <> 0;πEnd;ππProcedure EOI; { end of interrupt to 8259 interrupt controller }πBeginπ Port[$20] := $20;πEnd;ππFunction ReadScanCode : Byte;πVarπ N : Byte;πBeginπ N := Port[$60]; { $FF means keyboard overrun }π ReadScanCode := N;πEnd;ππProcedure ResetKeyboard; { prepare for next key }πVarπ N : Byte;πBeginπ N := Port[$61];π Port[$61] := (N or $80);π Port[$61] := N;πEnd;ππFunction StoreKey(Scan, Key : Byte) : Boolean;πVar { put key in buffer that INT 16 reads }π P : TwoBytesPtr;π N : Word;πBeginπ DisableInterrupts;ππ N := KeyBufferTail;π P := Ptr(BiosDataSegment, N);ππ Inc(N, 2);π If(N = KeyBufferEnd) then { end of the circular buffer }π N := KeyBufferStart;π If(N = KeyBufferHead) then { buffer full }π Beginπ EnableInterrupts;π StoreKey := False;π Endπ Elseπ Beginπ P^.KeyCode := Key;π P^.ScanCode := Scan; { store key in circular buffer }π KeyBufferTail := N; { advance tail pointer }π EnableInterrupts;π StoreKey := True;π End;πEnd;πππEND.ππππ 55 11-02-9310:27ALL LOU DUCHEZ Disable Ctrl-Break IMPORT 17 ├■ (*πLOU DUCHEZππ>> How can i disable the Pascal interrupt key Ctrl-Break?ππ>Try CheckBreak := False;ππ> Isn't there another way to do this that works better? Just wondering... :)ππWell, here's some code I came up With. What it does is "cheat": itπdetects if you're pressing "C" While "Ctrl" is down. if so, it changesπ"Ctrl" to "undepressed". As For "Ctrl-Break", I just changed theπbuilt-in "Ctrl-Break" interrupt to an "empty" routine (i.e., it doesπNOTHING). And it's a TSR, too; to "un-TSR" the code, remove theπ"{$M ...}" at the beginning and the "keep(0)" at the end, then justπincorporate the code into your Programs. More comments as I go:π*)ππ{$M $0400, $0000, $0000}π{$F+}ππProgram nobreak;πUsesπ Dos;ππConstπ ctrlByte = $04; { Memory location $0040:$0017 governs the statUses ofπ the Ctrl key, Alt, Shifts, etc. the "$04" bitπ handles "Ctrl". }ππVarπ old09h : Procedure; { original keyboard handler }π ctrldown,π cdown : Boolean;π keyboardstat : Byte Absolute $0040:$0017; { the aforementioned location }ππProcedure new1bh; interrupt; { new Ctrl-Break handler: does NOTHING }πbeginπend;ππProcedure new09h; interrupt; { new keyboard handler: it checks if you'veπ pressed "C" or "Brk"; if you have, it changesπ "Ctrl" to "undepressed. Then it calls theπ "old" keyboard handler. }πbeginπ if port[$60] and $1d = $1d thenπ ctrldown := (port[$60] < 128);π if port[$60] and $2e = $2e thenπ cdown := (port[$60] < 128);π if cdown and ctrldown thenπ keyboardstat := keyboardstat and not ctrlByte;π Asmπ pushfπ end;π old09h;πend;ππbeginπ getintvec($09, @old09h);π setintvec($09, @new09h); { set up new keyboard handler }π setintvec($1b, @new1bh); { set up new "break" handler }π ctrldown := False;π cdown := False;π keep(0);πend.π 56 11-21-9309:36ALL MARK OUELLET Flush/Stuff Keyboard IMPORT 6 âÆ {From: MARK OUELLET}π{ FLUSH/STUFF Keyboard w/INT21}ππPROGRAM StuffKbdTest;πuses dos;ππ procedure FlushKbd; Assembler;ππ asmπ Mov AX, $0C00;π Int 21h;π end;ππ procedure StuffKbd(S:string);ππ varπ Regs : registers;π x : byte;π BufferFull : boolean;ππ beginπ FlushKbd;π Inc(S[0]);π S[byte(S[0])] := #13;π x := 1;π repeatπ Regs.AH := $05;π Regs.CL := Byte(S[x]);π Intr($16, Regs);π BufferFull := boolean(Regs.AL);π inc(x);π until BufferFull or (x>byte(S[0]));π end;ππ beginπ StuffKbd('Dir C:\');π end.π 57 11-21-9309:36ALL EDWIN CALIMBO Another QUICK kbd Clear IMPORT 8 ) {πEDWIN CALIMBOππ║ I need to know how I can clear the keyboard buffer.π║ The reason I need to do this is that in a loop I'm reading inπ║ one Character and then calling a Procedure which returns to theπ║ loop For the next Character to be read. But sometimes it takes theπ║ next Character in the buffer that my have been a result of just holdingπ║ down a key For to long.πππ You can clear any keys in the keyboard buffer by using the following loop:π}π While KeyPressed Doπ ch := ReadKey;π{π Another way to clear the keyboard buffer is to set the keyboard headπ equal to the keyboard tail and the keyboard buffer as a circular buffer.π You can set the tail equal to the head this way:π}π MemW[$0000:$041C] := MemW[$0000:$041A]; { flush keyboard buffer }π 58 11-26-9317:14ALL SWAG SUPPORT TEAM Nice Keyboard unit IMPORT 103 = πUnit keybx;π π interfaceπ π uses errors;π π π const Right_shift = $0001;π Left_shift = $0002;π Ctrl = $0004;π Alt = $0008;π Scroll_locked = $0010;π Num_locked = $0020;π Caps_locked = $0040;π Insert_locked = $0080;π π Right_ctrl = $0100;π left_alt = $0200;π sysreq = $0400;π Pause_locked = $0800;π Scroll_pressed = $1000;π Num_pressed = $2000;π Caps_pressed = $4000;π Ins_pressed = $8000;π π Space = $3920;π π Enter = $1C0D;π Ctrl_Enter = $1C0A;π Shift_Enter = $1C0D;π Alt_Enter = $1C00;π π gray_Enter = $E00D;π Ctrl_Gray_Enter = $E00A;π Shift_Gray_Enter= $E00D;π Alt_Gray_Enter = $A600;ππ gray_Plus = $4E2B;π Ctrl_gray_plus = $9000;π Shift_gray_plus = $4E2B;π alt_gray_plus = $4E00;π π gray_Minus = $4A2D;π Ctrl_gray_minus = $8E00;π Shift_gray_minus= $4A2D;π alt_gray_minus = $4A00;π π _Esc = $011B;π Ctrl_Esc = $011B;π Shift_Esc = $011B;π Alt_Esc = $0100;π π Backspace = $0E08;π Ctrl_Backspace = $0E7F;π Shift_Backspace = $0E08;π Alt_Backspace = $0E00;ππ π _Tab = $0F09;π Ctrl_Tab = $9400;π Shift_Tab = $0F00;π Alt_Tab = $A500;π π _Up = $4800;π _Down = $5000;π _Left = $4B00;π _Right = $4D00;π _Home = $4700;π _End = $4F00;π _PgUp = $4900;π _PgDn = $5100;π _Five = $4C00;π _Ins = $5200;π _del = $5300;π π Ctrl_Up = $8D00;π Ctrl_Down = $9100;π Ctrl_Left = $7300;π Ctrl_Right = $7400;π Ctrl_Home = $7700;π Ctrl_End = $7500;π Ctrl_PgUp = $8400;π Ctrl_PgDn = $7600;π Ctrl_Five = $8F00;π Ctrl_Del = $9300;π Ctrl_Ins = $9200;π π π shift_Up = $4838;π shift_Down = $5032;π shift_Left = $4B34;π shift_Right = $4D36;π shift_Home = $4737;π shift_End = $4F31;π shift_PgUp = $4939;π shift_PgDn = $5133;π shift_Five = $4C35;π shift_ins = $5230;π shift_del = $532E;π π gray_Up = $48E0;π gray_Down = $50E0;π gray_Left = $4BE0;π gray_Right = $4DE0;π gray_Home = $47E0;π gray_End = $4FE0;π gray_PgUp = $49E0;π gray_PgDn = $51E0;π gray_ins = $52E0;π gray_del = $53E0;π π Ctrl_gray_Up = $8DE0;π Ctrl_gray_Down = $91E0;π Ctrl_gray_Left = $73E0;π Ctrl_gray_Right = $74E0;π Ctrl_gray_Home = $77E0;π Ctrl_gray_End = $75E0;π Ctrl_gray_PgUp = $84E0;π Ctrl_gray_PgDn = $76E0;π Ctrl_Gray_Ins = $92E0;π Ctrl_Gray_del = $93E0;π π shift_gray_Up = $48E0;π shift_gray_Down = $50E0;π shift_gray_Left = $4BE0;π shift_gray_Right= $4DE0;π shift_gray_Home = $47E0;π shift_gray_End = $4FE0;π shift_gray_PgUp = $49E0;π shift_gray_PgDn = $51E0;π Shift_gray_Ins = $52E0;π Shift_gray_del = $53E0;π π Alt_gray_Up = $9800;π Alt_gray_Down = $A000;π Alt_gray_Left = $9B00;π Alt_gray_Right = $9D00;π Alt_gray_Home = $9700;π Alt_gray_End = $9F00;π Alt_gray_PgUp = $9900;π Alt_gray_PgDn = $A100;π Alt_gray_Ins = $A200;π Alt_gray_del = $A300;π π _f1 = $3B00;π _f2 = $3C00;π _f3 = $3D00;π _f4 = $3E00;π _f5 = $3F00;π _f6 = $4000;π _f7 = $4100;π _f8 = $4200;π _f9 = $4300;π _f10 = $4400;π _f11 = $8500;π _f12 = $8600;ππ Shift_f1 = $5400;π Shift_f2 = $5500;π Shift_f3 = $5600;π Shift_f4 = $5700;π Shift_f5 = $5800;π Shift_f6 = $5900;π Shift_f7 = $5A00;π Shift_f8 = $5B00;π Shift_f9 = $5C00;π Shift_f10 = $5D00;π Shift_f11 = $8700;π Shift_f12 = $8800;π π Ctrl_f1 = $5E00;π Ctrl_f2 = $5F00;π Ctrl_f3 = $6000;π Ctrl_f4 = $6100;π Ctrl_f5 = $6200;π Ctrl_f6 = $6300;π Ctrl_f7 = $6400;π Ctrl_f8 = $6500;π Ctrl_f9 = $6600;π Ctrl_f10 = $6700;π Ctrl_f11 = $8900;π Ctrl_f12 = $8A00;π π Alt_f1 = $6800;π Alt_f2 = $6900;π Alt_f3 = $6A00;π Alt_f4 = $6B00;π Alt_f5 = $6C00;π Alt_f6 = $6D00;π Alt_f7 = $6E00;π Alt_f8 = $6F00;π Alt_f9 = $7000;π Alt_f10 = $7100;π Alt_f11 = $8B00;π Alt_f12 = $8C00;π π Alt_a = $1E00;π Alt_b = $3000;π Alt_c = $2E00;π Alt_d = $2000;π Alt_e = $1200;π Alt_f = $2100;π Alt_g = $2200;π Alt_h = $2300;π Alt_i = $1700;π Alt_j = $2400;π Alt_k = $2500;π Alt_l = $2600;π Alt_m = $3200;π Alt_n = $3100;π Alt_o = $1800;π Alt_p = $1900;π Alt_q = $1000;π Alt_r = $1300;π Alt_s = $1F00;π Alt_t = $1400;π Alt_u = $1600;π Alt_v = $2F00;π Alt_w = $1100;π Alt_x = $2D00;π Alt_y = $1500;π Alt_z = $2C00;π π Ctrl_a = $1E01;π Ctrl_b = $3002;π Ctrl_c = $2E03;π Ctrl_d = $2004;π Ctrl_e = $1205;π Ctrl_f = $2106;π Ctrl_g = $2207;π Ctrl_h = $2308;π Ctrl_i = $1709;π Ctrl_j = $240A;π Ctrl_k = $250B;π Ctrl_l = $260C;π Ctrl_m = $320D;π Ctrl_n = $310E;π Ctrl_o = $180F;π Ctrl_p = $1910;π Ctrl_q = $1011;π Ctrl_r = $1312;π Ctrl_s = $1F13;π Ctrl_t = $1414;π Ctrl_u = $1615;π Ctrl_v = $2F16;π Ctrl_w = $1117;π Ctrl_x = $2D18;π Ctrl_y = $1519;π Ctrl_z = $2C1A;π π π Key_a = $1E61;π Key_b = $3062;π Key_c = $2E63;π Key_d = $2064;π Key_e = $1265;π Key_f = $2166;π Key_g = $2267;π Key_h = $2368;π Key_i = $1769;π Key_j = $246A;π Key_k = $256B;π Key_l = $266C;π Key_m = $326D;π Key_n = $316E;π Key_o = $186F;π Key_p = $1970;π Key_q = $1071;π Key_r = $1372;π Key_s = $1F73;π Key_t = $1474;π Key_u = $1675;π Key_v = $2F76;π Key_w = $1177;π Key_x = $2D78;π Key_y = $1579;π Key_z = $2C7A;π π Key_0 = $0B30;π Key_1 = $0231;π Key_2 = $0332;π Key_3 = $0433;π Key_4 = $0534;π Key_5 = $0635;π Key_6 = $0736;π Key_7 = $0837;π Key_8 = $0938;π Key_9 = $0A39;π π π Shift_Key_a = $1E41;π Shift_Key_b = $3042;π Shift_Key_c = $2E43;π Shift_Key_d = $2044;π Shift_Key_e = $1245;π Shift_Key_f = $2146;π Shift_Key_g = $2247;π Shift_Key_h = $2348;π Shift_Key_i = $1749;π Shift_Key_j = $244A;π Shift_Key_k = $254B;π Shift_Key_l = $264C;π Shift_Key_m = $324D;π Shift_Key_n = $314E;π Shift_Key_o = $184F;π Shift_Key_p = $1950;π Shift_Key_q = $1051;π Shift_Key_r = $1352;π Shift_Key_s = $1F53;π Shift_Key_t = $1454;π Shift_Key_u = $1655;π Shift_Key_v = $2F56;π Shift_Key_w = $1157;π Shift_Key_x = $2D58;π Shift_Key_y = $1559;π Shift_Key_z = $2C5A;ππ Shift_Key_0 = $0B29;π Shift_Key_1 = $0221;π Shift_Key_2 = $0340;π Shift_Key_3 = $0423;π Shift_Key_4 = $0524;π Shift_Key_5 = $0625;π Shift_Key_6 = $075E;π Shift_Key_7 = $0826;π Shift_Key_8 = $092A;π Shift_Key_9 = $0A28;π π No_Key_At_all = $FFFF;π No_Key = $FFFE;π Ctrl_Break = $0000;π π π function Readkey:char;π function keypressed:boolean;π π function Extended_Keypressed:boolean;π function Extended_Readkey:word;π procedure Extended_Writekey(scan_code:word);π function Extended_Browsekey:word;π procedure Flush_That_Key;π π function Ctrl_Break_pressed:boolean;π procedure Clear_Ctrl_Break;π π function get_shift_status:word;π function shift_status_is(mask:word):boolean;π function Get_char(w:word):char;π π π Var Touche_Residuelle:byte;π Last_key:word;π π π implementationπ π (*===========*)π function Get_char(w:word):char; assembler;π asmπ mov ax,wπ end;π π (*===========*)π function Readkey:char; assembler;π asmπ mov al,Touche_residuelleπ or al,alπ jz @iciπ mov touche_residuelle,0π jmp @exitπ @ici:π mov ah,$10π int $16π mov last_key,axπ or al,alπ jnz @exitπ mov Touche_residuelle,ahπ @exit:π end;π π π (*===========*)π function keypressed:boolean; assembler;π asmπ mov ah,$11π int $16π mov al,0π jz @exitπ mov al,1π @exit:π end;π π π (*===========*)π function get_shift_status:word; assembler;π asmπ xor ax,axπ mov es,axπ mov ax,es:[$417]π end;π π (*===========*)π function shift_status_is(mask:word):boolean; assembler;π asmπ xor ax,axπ mov es,axπ mov ax,es:[$417]π and ax,maskπ jz @exitπ mov al,1π @exit:π end;π π π (*===========*)π procedure Clear_Ctrl_Break; assembler;π asmπ xor ax,axπ mov es,axπ mov byte ptr es:[$471],0π end;π π π (*===========*)π function Ctrl_Break_pressed:boolean; assembler;π asmπ xor ax,axπ mov es,axπ mov al,es:[$471]π shr al,7π end;π π π (*===========*)π function extended_keypressed:boolean; assembler;π asmπ mov ah,$11π int $16π lahfπ and ah,$4π not ahπ mov al,ahπ end;π π (*===========*)π function Extended_Browsekey:word; assembler;π asmπ mov ah,$11;π int $16π jnz @exitπ xor ax,axπ @exit:π end;π π (*===========*)π function extended_readkey:word; assembler;π asmπ mov ah,$10π int $16π mov last_key,axπ end;π π (*===========*)π procedure flush_that_key; assembler;π asmπ mov ah,$10π int $16π end;π π (*===========*)π procedure extended_writekey(scan_code:word); assembler;π asmπ mov ah,5π mov cx,scan_codeπ int $16π end;π π π π beginπ Touche_residuelle:=0;π Last_key:=no_key_at_all;π Clear_Ctrl_Break;π end.ππ 59 11-26-9317:21ALL SWAG SUPPORT TEAM Musical Keyboard Handler IMPORT 18 ñ {πYou'll have to write a new Keyboard hardware interrupt handler, I did thatπ(quite a while ago) for this little program. It generates a different beepπsound for every key pressed. The comments are in Dutch, but if you can readπAfrikaans you might be able to understand them. I think the code is self-πexplanatory anyway.π}ππprogram MusicKey; { herziene versie }ππuses crt, dos;ππconst kbd_data = $60; { Keyboard data poort }π kbd_ctrl = $61; { Keyboard control poort }π int_ctrl = $20; { Interrupt control poort }π eoi = $20; { End-of-interrupt constante }π release = $80; { Key released bit }π enable_kbd = $80; { Enable keyboard bit }ππconst Press : Byte = 0; { Scancode van ingedrukte toets }πvar SaveInt09 : Pointer; { Om originele intvector in te bewaren }ππProcedure NewKbdInt; interrupt; { Interrupt service routine, }πvar b:Byte; { aangeroepen door kbd hardware }πbeginπ b:=Port[kbd_data]; { Lees scancode van poort }π if b = Press + Release then Press:=0 { Laatst ingedrukte toets los? }π else if b < Release then Press:=b; { Toets ingedrukt? Press:=b }π b:=Port[kbd_ctrl]; { Interrupt netjes afwerken }π Port[kbd_ctrl]:=b or enable_kbd;π Port[kbd_ctrl]:=b;π Port[int_ctrl]:=eoi;πend;ππbeginπ GetIntVec($9,SaveInt09); { Bewaar originele vector }π SetIntVec($9,@NewKbdInt); { Installeer onze routine }π{***}π Writeln(^J^J^M,'Escape = Exit');π repeatπ Write(^M,'Gelezen scancode: ',Press:2); { Druk scancode af }π if Press > 1 then Sound(100 * Press) { Laat toontje horen }π else NoSound; { Of niet (Press = 0) }π until Press = 1; { Escape : Press = 1 }π{***}π SetIntVec($9,SaveInt09); { Herstel originele vector }πend.π 60 01-27-9412:10ALL FRED JOHNSON Keyboard Handler IMPORT 8 ╖O {π>Can anyone shed some light on how to add characters to the keyboardπ>buffers so i can echo commands right after my program exits?π}ππunit kb;ππinterfaceππtypeππ string16 = string[16];π{πProcedure Name: StuffKBD();πDescription : Places a string of 16 chars or less into theπ keyboard buffer.πReturns : NothingπCalls : Int 16hπ}πprocedure StuffKBD(sCommand : string16);ππimplementationππprocedure StuffKBD(sCommand : string16);πvarπ iStuff : integer;π ucMove : BYTE;πbeginπ for iStuff := 1 to length(sCommand) doπ beginπ ucMove := byte(sCommand[iStuff]);π asmπ mov ah, $5;π mov ch, $0;π mov cl, ucMove;π int $16;π end;π end;πend;ππend.ππprogram kbstuff;πusesπ kb;ππbeginπ StuffKBD('kbstuff');π {You can even add StuffKBD(#13);}πend.ππ 61 01-27-9412:11ALL GREG VIGNEAULT Keyboard Characters IMPORT 16 ╗Θ {π> Can you help me with an explaination as the the function of theπ> various control codes. Please help me fill in this list:ππ ASCII TABLE...ππ Dec Hex Binary Ctrl Name of characterπ --- --- --------- -- --------------------------------------π 0 00h 0000 0000 ^@ NUL nullπ 1 01h 0000 0001 ^A SOH start of headerπ 2 02h 0000 0010 ^B STX start of textπ 3 03h 0000 0011 ^C ETX end of textπ 4 04h 0000 0100 ^D EOT end of transmissionπ 5 05h 0000 0101 ^E ENQ inquiryπ 6 06h 0000 0110 ^F ACK acknowledgementπ 7 07h 0000 0111 ^G BEL bellπ 8 08h 0000 1000 ^H BS backspaceπ 9 09h 0000 1001 ^I HT horizontal tab (Can't display)π 10 0Ah 0000 1010 ^J LF line feed (Can't display)π 11 0Bh 0000 1011 ^K VT vertical tabπ 12 0Ch 0000 1100 ^L FF form feedπ 13 0Dh 0000 1101 ^M CR carriage return (Can't display)π 14 0Eh 0000 1110 ^N SO shift outπ 15 0Fh 0000 1111 ^O SI shift inπ 16 10h 0001 0000 ^P DLE data link escapeπ 17 11h 0001 0001 ^Q DC1 device control 1 (XON)π 18 12h 0001 0010 ^R DC2 device control 2π 19 13h 0001 0011 ^S DC3 device control 3 (XOFF)π 20 14h 0001 0100 ^T DC4 device control 4π 21 15h 0001 0101 ^U NAK negative acknowledgementπ 22 16h 0001 0110 ^V SYN synchronous idleπ 23 17h 0001 0111 ^W ETB end of transmission blockπ 24 18h 0001 1000 ^X CAN cancelπ 25 19h 0001 1001 ^Y EM end of mediumπ 26 1Ah 0001 1010 ^Z SUB substituteπ 27 1Bh 0001 1011 ^[ ESC escapeπ 28 1Ch 0001 1100 ^\ FS file separatorπ 29 1Dh 0001 1101 ^] GS group separatorπ 30 1Eh 0001 1110 ^^ RS record separatorπ 31 1Fh 0001 1111 ^_ US unit separatorπ 32 20h 0010 0000 SP spaceππ 62 01-27-9412:20ALL DROR LEON Keyboard Port IMPORT 6 3 {π> Hello all, I am looking for a scancode for the tab key. I am desperate!π> Please, Any code would be apreciated! Help! Netmail if you wish (1:241/99)ππI saw Richard Brown wrote you a reply as a testing program, but it works forπASCII codes not SCAN codes so :π }πVarπ old : Byte;πBeginπ WriteLn ('Press any key to begin and ESCAPE to exit.');π ReadLn;π old:=$FF;π While Port[$60]<>1+$80 Do {Until ESCAPE is released, 1 is ESC scan-code}π Beginπ If (old<>Port[$60]) And (Port[$60]<$80) Thenπ Beginπ old:=Port[$60];π Writeln('Scan code ',old,' pressed - release code is ',old+$80);π End;π End;πEnd.ππ 63 01-27-9412:20ALL WAYNE BOYD Scan Keys IMPORT 26 »╛ unit ScanCode;ππ{ This UNIT is created by Wayne Boyd, aka Vipramukhya Swami, BBS phoneπ (604)431-6260, Fidonet node 1:153/763. It's function is to facilitateπ the use of Function keys and Alt keys in a program. It includes F1π through F10, Shift-F1 through Shift-F10, Ctrl-F1 through Ctrl-F10,π and Alt-F1 through Alt-F10. It also includes all of the alt keys, allπ of the Ctrl keys and many other keys as well. This UNIT and source codeπ are copyrighted material and may not be used for commercial useπ without express written permission from the author. Use at your ownπ risk. I take absolutely no responsibility for it, and there are noπ guarantees that it will do anything more than take up space on yourπ disk. }πππinterfaceππCONSTππ F1 = 59; CtrlF1 = 94; AltF1 = 104; Homekey = 71;π F2 = 60; CtrlF2 = 95; AltF2 = 105; Endkey = 79;π F3 = 61; CtrlF3 = 96; AltF3 = 106; PgUp = 73;π F4 = 62; CtrlF4 = 97; AltF4 = 107; PgDn = 81;π F5 = 63; CtrlF5 = 98; AltF5 = 108; UpArrow = 72;π F6 = 64; CtrlF6 = 99; AltF6 = 109; RtArrow = 77;π F7 = 65; CtrlF7 = 100; AltF7 = 110; DnArrow = 80;π F8 = 66; CtrlF8 = 101; AltF8 = 111; LfArrow = 75;π F9 = 67; CtrlF9 = 102; AltF9 = 112; InsertKey = 82;π F10 = 68; CtrlF10 = 103; AltF10 = 113; DeleteKey = 83;ππ AltQ = 16; AltA = 30; AltZ = 44; Alt1 = 120; ShftF1 = 84;π AltW = 17; AltS = 31; AltX = 45; Alt2 = 121; ShftF2 = 85;π AltE = 18; AltD = 32; AltC = 46; Alt3 = 122; ShftF3 = 86;π AltR = 19; AltF = 33; AltV = 47; Alt4 = 123; ShftF4 = 87;π AltT = 20; AltG = 34; AltB = 48; Alt5 = 124; ShftF5 = 88;π AltY = 21; AltH = 35; AltN = 49; Alt6 = 125; ShftF6 = 89;π AltU = 22; AltJ = 36; AltM = 50; Alt7 = 126; ShftF7 = 90;π AltI = 23; AltK = 37; Alt8 = 127; ShftF8 = 91;π AltO = 24; AltL = 38; Alt9 = 128; ShftF9 = 92;π AltP = 25; CtrlLf = 115; Alt0 = 129; ShftF10= 93;π CtrlRt = 116;ππ CtrlA = #1; CtrlK = #11; CtrlU = #21; CtrlB = #2; CtrlL = #12;π CtrlV = #22; CtrlC = #3; CtrlM = #13; CtrlW = #23; CtrlD = #4;π CtrlN = #14; CtrlX = #24; CtrlE = #5; CtrlO = #15; CtrlY = #25;π CtrlF = #6; CtrlP = #16; CtrlZ = #26; CtrlG = #7; CtrlQ = #17;π CtrlS = #19; CtrlH = #8; CtrlR = #18; CtrlI = #9; CtrlJ = #10;π CtrlT = #20; BSpace = #8; EscapeKey = #27; EnterKey = #13; NullKey = #0;ππimplementationππend.ππProgram Sample;ππusesπ scancode,π crt;ππprocedure GetKey;πvarπ ch : char;πbeginπ repeatπ ch := upcase(readkey); { check key }π if ch = NullKey then { NullKey = #0 }π beginπ case ord(readkey) of { check key again }π F1 : Dothis; { put your procedures here }π F2 : DoThat;π altx : AltXPressed;π end; {case}π endπ elseπ case ch ofπ CtrlY : CtrlYPressed; { put your procedures here }π CtrlT : CtrlTPressed;π BSpace : BackSpacePressed;π EnterKey : EnterKeyPressed;π EscapeKey : quitprogram;π end;π until ch = EscapeKey;πend;ππbeginπ GetKey;πend.π 64 01-27-9413:32ALL GREG ESTABROOKS Keyboard I/O IMPORT 75 ⌠| UNIT KeyIO; { Key I/O Unit, Last Updated Dec 08/93 }π { Copyright (C) 1993 Greg Estabrooks }π { Requires TP 6.0+ to compile. }πINTERFACEπ{***********************************************************************}πCONST { Define some keys to make later detection easy.}π Enter = #13; Esc = #27; HomeKey = #0#71;π EndKey = #0#79; PgUp = #0#73; PgDn = #0#81;π InsKey = #0#82; DelKey = #0#83; BackSpace = #8;π Space = #32;ππ UpArrow = #0#72; DnArrow = #0#80; LfArrow = #0#75;π RtArrow = #0#77;ππ Alt_A = #0#30; Alt_B = #0#48; Alt_C = #0#46; Alt_D = #0#32;π Alt_E = #0#18; Alt_F = #0#33; Alt_G = #0#34; Alt_H = #0#35;π Alt_I = #0#23; Alt_J = #0#36; Alt_K = #0#37; Alt_L = #0#38;π Alt_M = #0#50; Alt_N = #0#49; Alt_O = #0#24; Alt_P = #0#25;π Alt_Q = #0#16; Alt_R = #0#19; Alt_S = #0#31; Alt_T = #0#20;π Alt_U = #0#22; Alt_V = #0#47; Alt_W = #0#17; Alt_X = #0#45;π Alt_Y = #0#21; Alt_Z = #0#44;ππ Alt_1 = #0#120; Alt_2 = #0#121; Alt_3 = #0#122; Alt_4 = #0#123;π Alt_5 = #0#124; Alt_6 = #0#125; Alt_7 = #0#126; Alt_8 = #0#127;π Alt_9 = #0#128; Alt_0 = #0#129;ππ Alt_F1 =#0#104; Alt_F2 =#0#105; Alt_F3 =#0#106; Alt_F4 =#0#107;π Alt_F5 =#0#108; Alt_F6 =#0#109; Alt_F7 =#0#110; Alt_F8 =#0#111;π Alt_F9 =#0#112; Alt_F10=#0#113; Alt_F11=#0#139;π Alt_F12=#0#140;ππ F1 = #0#59; F2 = #0#60; F3 = #0#61; F4 = #0#62; F5 = #0#63;π F6 = #0#64; F7 = #0#65; F8 = #0#66; F9 = #0#67; F10= #0#68;π F11= #0#133; F12= #0#134;ππ Shift_F11 = #0#135; Shift_F12 = #0#136;π Ctrl_F11 = #0#137; Ctrl_F12 = #0#138;πTYPEπ Str02 = STRING[2];πVARπ KeyHPtr :WORD Absolute $40:$1A; { Ptr to front of key buf. }π KeyTPtr :WORD Absolute $40:$1C; { Ptr to end of key buf. }ππFUNCTION CapsOn :BOOLEAN;π { Routine to determine if Caps Lock is on. }πFUNCTION NumLockOn :BOOLEAN;π { Routine to determine if Num Lock is on. }πFUNCTION InsertOn :BOOLEAN;π { Routine to determine if Insert is on. }πFUNCTION AltPressed :BOOLEAN;π { Routine to determine if ALT key is being held down. }πFUNCTION CtrlPressed :BOOLEAN;π { Routine to determine if Ctrl key is being held down.}πFUNCTION LeftShift :BOOLEAN;π { Routine to determine if L_Shift is being held down. }πFUNCTION RightShift :BOOLEAN;π { Routine to determine if R_Shift is being held down. }πFUNCTION ScrollOn :BOOLEAN;π { Routine to determine if Scroll Lock is on. }πPROCEDURE NumLock( Enable :BOOLEAN );π { Routine to Set/Unset the Numlock key. }πPROCEDURE CapsLock( Enable :BOOLEAN );π { Routine to Set/Unset the Capslock key. }πPROCEDURE ScrollLock( Enable :BOOLEAN );π { Routine to Set/Unset the Scrolllock key. }πFUNCTION EnhancedKeyBoard :BOOLEAN;π { Test Bit 4 of byte at 0040:0096 to check for enhanced}π { Keyboard. }πFUNCTION EKeyPressed :BOOLEAN;π { Function to determine if a key was pressed. The }π { routine in the CRT Unit to do this didn't detect F11 }π { or F12 keys. }πFUNCTION GetKey :STR02;π { Routine to Read Key Presses. Including F11 and F12. }πPROCEDURE ClearKeyBuffer;π { Routine to Clear Keyboard buffer. }πPROCEDURE PauseKey;π { Routine to wait for a keypress and then continue. }ππIMPLEMENTATIONπ{***********************************************************************}πFUNCTION CapsOn :BOOLEAN;π { Routine to determine if Caps Lock is on. }πBEGIN { Test the keyboard status bit for Caps.}π CapsOn := (Mem[$0040:$0017] AND $40) <> 0;πEND;{CapsOn}ππFUNCTION NumLockOn :BOOLEAN;π { Routine to determine if Num Lock is on. }πBEGIN { Test keyboard status bit for NumLock. }π NumLockon := (Mem[$0040:$0017] AND $20) <>0πEND;{NumLockOn}ππFUNCTION InsertOn :BOOLEAN;π { Routine to determine if Insert is on. }πBEGIN { Test keyboard status bit for insert. }π InsertOn := (Mem[$0040:$0017] AND $80) <> 0;πEND;{InsertOn}ππFUNCTION AltPressed :BOOLEAN;π { Routine to determine if ALT key is being held down. }πBEGIN { Test keyboard status bit for ALT. }π AltPressed := (Mem[$0040:$0017] AND $08) <> 0;πEND;{AltPressed}ππFUNCTION CtrlPressed :BOOLEAN;π { Routine to determine if Ctrl key is being held down.}πBEGIN { Test keyboard status bit for Ctrl. }π CtrlPressed := (Mem[$0040:$0017] AND $04) <> 0;πEND;{CtrlPressed}ππFUNCTION LeftShift :BOOLEAN;π { Routine to determine if L_Shift is being held down. }πBEGIN { Test keyboard status bit for L_Shift. }π LeftShift := (Mem[$0040:$0017] AND $02) <> 0;πEND;{LeftShift}ππFUNCTION RightShift :BOOLEAN;π { Routine to determine if R_Shift is being held down. }πBEGIN { Test keyboard status bit for R_Shift. }π RightShift := (Mem[$0040:$0017] AND $1) <> 0;πEND;{RightShift}ππFUNCTION ScrollOn :BOOLEAN;π { Routine to determine if Scroll Lock is on. }πBEGIN { Test keyboard status bit for S_Lock. }π ScrollOn := (Mem[$0040:$0017] AND $10) <> 0;πEND;{ScrollOn}ππPROCEDURE NumLock( Enable :BOOLEAN );π { Routine to Set/Unset the Numlock key. }πBEGINπ IF Enable THEN { Turn on Bit 5 }π Mem[$40:$17] := Mem[$40:$17] OR $20π ELSE { Turn it Off 5 }π Mem[$40:$17] := Mem[$40:$17] AND $DF;πEND;{NumLock}ππPROCEDURE CapsLock( Enable :BOOLEAN );π { Routine to Set/Unset the Capslock key. }πBEGINπ IF Enable THEN { Turn on Bit }π Mem[$40:$17] := Mem[$40:$17] OR $40π ELSE { Turn it Off }π Mem[$40:$17] := Mem[$40:$17] AND $BF;πEND;{CapsLock}ππPROCEDURE ScrollLock( Enable :BOOLEAN );π { Routine to Set/Unset the Scrolllock key. }πBEGINπ IF Enable THEN { Turn on Bit }π Mem[$40:$17] := Mem[$40:$17] OR $10π ELSE { Turn it Off }π Mem[$40:$17] := Mem[$40:$17] AND $EF;πEND;{ScrollLock}ππFUNCTION EnhancedKeyBoard :BOOLEAN;π { Test Bit 4 of byte at 0040:0096 to check for enhanced}π { Keyboard. }πBEGINπ EnhancedKeyBoard := (Mem[$40:$96] AND $10) = $10;πEND;{EnhancedKeyBoard}ππFUNCTION EKeyPressed :BOOLEAN; ASSEMBLER;π { Function to determine if a key was pressed. The }π { routine in the CRT Unit to do this didn't detect F11 }π { or F12 keys. }πASMπ Mov AH,$11 { Function to check for Enhanced key. }π Int $16 { Call keyboard INT. }π Jz @NoKey { If ZF not set then nothing pressed. }π Mov AL,1 { Otherwise return TRUE. }π Jmp @Exit { Now goto Exit. }π@NoKey:π Mov AL,0 { Return a FALSE result. }π@Exit:πEND;{EKeyPressed}ππFUNCTION GetKey :STR02;π { Routine to Read Key Presses. Including F11 and F12 }πVARπ TKey :STR02; { Hold key press info. }πBEGINπ ASMπ Call EnhancedKeyBoard { Test for an Enhanced keyboard. }π Cmp AL,1 { If AL=1 THEN Enhanced Keyboard= TRUE. }π Je @Enhanced { If it was TRUE then Get Enhanced key. }π Mov AH,0 { If not TRUE get normal key. }π Jmp @ReadKeybπ@Enhanced:π Mov AH,$10 { Function to get key from enhanced board.}π@ReadKeyb:π Int $16 { Call Int keyboard INT. }π Mov TKey[1].BYTE,AL { Load both Ascii code and scan code }π Mov TKey[2].BYTE,AH { into TKey. }π END;π IF (TKey[1] = #224) AND EnhancedKeyBoard THENπ BEGINπ IF KeyHPtr = $1E THENπ TKey := #0 + CHR(Mem[$40:$3D])π ELSEπ TKey := #0 + CHR(Mem[$40:KeyHPtr-1]);π END;π IF TKey[1] <> #0 THEN { If it wasn't an extended key then }π TKey := TKey[1]; { return only Ascii code. }π GeTKey := TKey; { Return proper key result to user. }πEND;{GetKey}ππPROCEDURE ClearKeyBuffer;π { Routine to Clear Keyboard buffer. }πVARπ DKey :Str02; { Hold unwanted keystrokes. }πBEGINπ WHILE EKeyPressed DOπ DKey := GetKey; { Read in unwanted key press. }πEND;{ClearKeyBuffer}ππPROCEDURE PauseKey;π { Routine to wait for a keypress and then continue. }πVARπ Ch :STR02; { Holds dummy key press. }πBEGINπ ClearKeyBuffer; { Clear buffer of any previous keys. }π Ch := GetKey; { Call for a key. }πEND;{PauseKey}ππBEGINπEND.π{***********************************************************************} 65 01-27-9413:32ALL GREG VIGNEAULT Detecting special keys IMPORT 27
α (*******************************************************************)π PROGRAM xKeys; { test detecting shift/alt/ctrl/sysreq keys }π { Turbo/Quick Pascal Oct.1992 Greg Vigneault }π USES Crt; { import for ClrScr and KeyPressed }π{-------------------------------------------------------------------}π TYPE LockKey = ( RShift,LShift,Ctrl,Alt,Scroll,NumLock,Caps,Insert,π RightAlt,LeftAlt,RightCtrl,LeftCtrl,SysReq );π VAR KeyByte1 : BYTE Absolute $40:$17; { data maintained by BIOS }π KeyByte2 : BYTE Absolute $40:$18;π KeyByte3 : BYTE Absolute $40:$96;π{-------------------------------------------------------------------}π FUNCTION KeyOn( xkey : LockKey ) : BOOLEAN; { TRUE if LockKey on }π BEGINπ CASE xkey OFπ RShift..Insert : KeyOn:=BOOLEAN( KeyByte1 SHR ORD(xkey) AND 1);π RightAlt : KeyOn:=BOOLEAN( KeyByte3 SHR 3 AND 1 );π LeftAlt : KeyOn:=BOOLEAN( KeyByte2 SHR 1 AND 1 );π RightCtrl : KeyOn:=BOOLEAN( KeyByte3 SHR 2 AND 1 );π LeftCtrl : KeyOn:=BOOLEAN( KeyByte2 AND 1 );π SysReq : KeyOn:=BOOLEAN( KeyByte2 SHR 2 AND 1 );π END; {case}π END;π{-------------------------------------------------------------------}π FUNCTION Keyboard101 : BOOLEAN; { TRUE for 101/102-key kybd }π BEGIN KeyBoard101 := BOOLEAN( KeyByte3 SHR 4 AND 1 ); END;π{-------------------------------------------------------------------}π VAR xkey : LockKey;π BEGINπ REPEAT gotoxy(1,1); WriteLn('Press any of...');ππ Write('Shifts: ');π IF KeyOn(LShift) OR KeyOn(RShift) { either shift down? }π THEN BEGINπ IF KeyOn(LShift) THEN Write('LEFT ');π IF KeyOn(RShift) THEN Write('RIGHT');π WriteLn;π ENDπ ELSE WriteLn('none'); { neither shift }ππ Write('Controls: ');π IF KeyOn(Ctrl) { either ctrl down? }π THEN BEGINπ IF KeyOn(LeftCtrl) THEN Write('LEFT ');π IF KeyOn(RightCtrl) THEN Write('RIGHT');π WriteLn;π ENDπ ELSE WriteLn('none'); { neither ctrl }ππ Write('Alt keys: ');π IF KeyOn(Alt) { either Alt down? }π THEN BEGINπ IF KeyOn(LeftAlt) THEN Write('LEFT ');π IF KeyON(RightAlt) THEN Write('RIGHT');π WriteLn;π ENDπ ELSE WriteLn('none'); { neither alt }ππ FOR xkey := Scroll TO Insert { check other keys }π DO BEGINπ CASE xkey OFπ Scroll : Write('Scroll: ');π NumLock : Write('NumLock: ');π Caps : Write('CapsLock: ');π Insert : Write('Insert: ');π END; {case}π IF KeyOn(xkey) THEN WriteLn('ON') ELSE WriteLn('OFF');π END;ππ IF KeyBoard101π THEN BEGINπ Write('SysReq: ');π IF KeyOn(SysReq) THEN WriteLn('ON') ELSE WriteLn('OFF');π END;ππ UNTIL KeyPressed;ππ END {xKeys}.π(*******************************************************************)π 66 01-27-9413:32ALL GREG ESTABROOKS Detect Status Keys IMPORT 21 fj {***********************************************************************}πPROGRAM KeyStatDemo; { Dec 09/93, Greg Estabrooks. }πUSES CRT; { Import Clrscr,Writeln,GotXY. }ππFUNCTION CapsOn :BOOLEAN;π { Routine to determine if Caps Lock is on. }πBEGIN { Test the keyboard status bit for Caps.}π CapsOn := (Mem[$0040:$0017] AND $40) <> 0;πEND;{CapsOn}ππFUNCTION NumLockOn :BOOLEAN;π { Routine to determine if Num Lock is on. }πBEGIN { Test keyboard status bit for NumLock. }π NumLockon := (Mem[$0040:$0017] AND $20) <>0πEND;{NumLockOn}ππFUNCTION ScrollOn :BOOLEAN;π { Routine to determine if Scroll Lock is on. }πBEGIN { Test keyboard status bit for S_Lock. }π ScrollOn := (Mem[$0040:$0017] AND $10) <> 0;πEND;{ScrollOn}ππFUNCTION AltPressed :BOOLEAN;π { Routine to determine if ALT key is being held down. }πBEGIN { Test keyboard status bit for ALT. }π AltPressed := (Mem[$0040:$0017] AND $08) <> 0;πEND;{AltPressed}ππFUNCTION CtrlPressed :BOOLEAN;π { Routine to determine if Ctrl key is being held down.}πBEGIN { Test keyboard status bit for Ctrl. }π CtrlPressed := (Mem[$0040:$0017] AND $04) <> 0;πEND;{CtrlPressed}ππFUNCTION LeftShift :BOOLEAN;π { Routine to determine if L_Shift is being held down. }πBEGIN { Test keyboard status bit for L_Shift. }π LeftShift := (Mem[$0040:$0017] AND $02) <> 0;πEND;{LeftShift}ππFUNCTION RightShift :BOOLEAN;π { Routine to determine if R_Shift is being held down. }πBEGIN { Test keyboard status bit for R_Shift. }π RightShift := (Mem[$0040:$0017] AND $1) <> 0;πEND;{RightShift}ππBEGINπ Clrscr; { Clear the screen of clutter. }π REPEATπ GotoXY(1,1); { Move Back to top of screen. }π Writeln('CapsLock : ',Capson,' ');π Writeln('NumLock : ',NumLockOn,' ');π Writeln('Scroll Lock: ',ScrollOn,' ');π Writeln('Alt Key : ',AltPressed,' ');π Writeln('Ctrl Key : ',CtrlPressed,' ');π Writeln('Right Shift: ',RightShift,' ');π Writeln('Left Shift : ',LeftShift,' ');π UNTIL KeyPressed; { Loop until a key is pressed. }πEND.{KeyStatDemo}π{********************************************************************} 67 01-27-9417:33ALL COLIN CYR Intercept Ctrl-Alt-Del IMPORT 22 ≤7 {πFrom: COLIN CYRπSubj: Ctrl-Alt-Del...π}ππUNIT CADThief;ππ{Intercept Control+Alternate+Delete keypresses}ππINTERFACEππUSES Crt,Dos;ππFUNCTION GetCAD : boolean;πFUNCTION HandleCADs: boolean;ππIMPLEMENTATIONππVARπ OldInt09,OldExitProc: pointer;π KeyStat: ^byte;π CADStatus: boolean;ππPROCEDURE GoOldInt(OldIntVector: pointer);πINLINE(π $5B/ {POP BX - Get Segment}π $58/ {POP AX - Get Offset}π $89/ {MOV SP,BP}π $EC/π $5D/ {POP BP}π $07/ {POP ES}π $1F/ {POP DS}π $5F/ {POP DI}π $5E/ {POP SI}π $5A/ {POP DX}π $59/ {POP CX}π $87/ {XCHG SP,BP}π $EC/π $87/ {XCHG [BP],BX}π $5E/π $00/π $87/ {XCHG [BP+2],AX}π $46/π $02/π $87/ {XCHG SP,BP}π $EC/π $CB); {RETF}ππPROCEDURE SetCAD(Status: boolean);π BEGINπ CADStatus := Status {Set flag}π END;ππFUNCTION GetCAD: boolean;π BEGINπ GetCAD := CADStatus;π END;ππ{$F+}πPROCEDURE NewExitProc;π{$F-}π BEGINπ ExitProc := OldExitProc;π SetIntVec($09,OldInt09);π CheckBreak := TRUEπ END;ππ{$F+}πPROCEDURE NewInt09(AX,BX,CX,DX,SI,DI,DS,ES,BP: Word); INTERRUPT;π{$F-}π VARπ I,J : integer;π CONSTπ KsDelCode = $53;π BEGINπ I := Port[$60]; {Get Scan Code}π if ((I and $7F) = KsDelCode) and {DEL key?}π ((KeyStat^ and $0C) = $0C) {CTL + ALT ?}π THENπ BEGINπ SetCAD(TRUE);π J := Port[$61]; {Save Kbd Status}π Port[$61] := J and $80; {Reset Kbd Int}π Port[$61] := J and $7F;π Port[$20] := $20;π Sound(880);Delay(100);Sound(1220);Delay(250);NoSound;π ENDπ ELSEπ GoOldInt(OldInt09)π END;ππFUNCTION HandleCADs: boolean;ππVARπ XPos,YPos: byte;π A : char;π Regs : Registers;ππBEGINπ WITH Regs DO {Flush keyboard buffer}π BEGINπ AH := $0C;π AL := 0;π MsDOS(Regs)π END;π XPos :=WhereX; {Save old cursor position}π YPos := WhereY;π GotoXY(1,1);π WriteLn('Ctrl+Alt+Del pressed');π Delay(250);Sound(1600);Delay(250);NoSound;π GotoXY(1,1);WriteLn(' ');π GotoXY(1,1);Write('Are you sure you want to quit? ');π A := ReadKey;Write(A);π GotoXY(1,1);Write(' ');π IF UpCase(A) = 'Y' THENπ HandleCADs := TRUEπ ELSEπ HandleCADs := FALSE;π GotoXY(XPos,YPos);SetCAD(FALSE)πEND;ππPROCEDURE InstallCADHndlr;ππ BEGINπ OldExitProc := ExitProc;π ExitProc := @NewExitProc;π GetIntVec($09,OldInt09);π SetIntVec($09,@NewInt09);π SetCBreak(FALSE);π CheckBreak := FALSE;π KeyStat := Ptr($40,$17);π END;ππBEGINπ InstallCADHndlr;π SetCAD(FALSE)πEND.π 68 01-27-9413:30ALL GREG VIGNEAULT Disable Ctrl-Alt-Del IMPORT 32
α (*******************************************************************)π PROGRAM CtrlCAD; { CTRLCAD.PAS Disable Ctrl-Alt-Del }π { Oct.1992 Greg Vigneault }ππ USES Crt, { import ClrScr, KeyPressed, ReadKey }π Dos; { import GetIntVec, SetIntVec }ππ VAR old09Vector : POINTER; { to save/restore original ISR }π ch : CHAR;π presses : WORD;ππ { the following mask & count Ctrl-Alt-Del|Ins|Enter keystrokes }π {$L CTRLCAD.OBJ} { assembly, near calls }π PROCEDURE InitTrapCAD( oldVector : POINTER ); EXTERNAL;π PROCEDURE TrapCAD; Interrupt; EXTERNAL;π FUNCTION TriedCAD : WORD; EXTERNAL;π PROCEDURE ForgetCAD; EXTERNAL;π PROCEDURE WarmBoot; EXTERNAL;π PROCEDURE ColdBoot; EXTERNAL;ππ BEGINπ (* NEVER allow Ctrl-Break while TrapCAD is active ... *)π CheckBreak := FALSE; { disable Ctrl-Break }ππ GetIntVec( 9, old09Vector ); { get current keyboard ISR }π InitTrapCAD( old09Vector ); { pass vector to TrapCAD }π SetIntVec( 9, @TrapCAD ); { enable TrapCAD ISR }ππ ForgetCAD; { reset TriedCAD count to 0 }π presses := 99; { any unlikely value }ππ { we'll just count the Ctrl-Alt-Del taps ... }π REPEATπ IF (presses <> TriedCAD) { update only when changed }π THEN BEGINπ presses := TriedCAD;π ClrScr;π Write('Ctrl-Alt-Del pressed ',presses,' times ');π Write('[Press ESC to exit]');π END;π IF KeyPressed THEN ch := ReadKey;π UNTIL (ch = #27);ππ WriteLn; WriteLn;π REPEATπ Write('Would you like to warm boot the system? [Y/N] ',#7);π ReadLn( ch ); ch := UpCase( ch );π UNTIL ch IN ['Y','N'];π IF ch = 'Y' THEN WarmBoot; { emulate Ctrl-Alt-Del }ππ SetIntVec( 9, old09Vector ); { unload TrapCAD }π WriteLn; WriteLn('Ctrl-Alt-Del is now re-enabled!');π CheckBreak := TRUE; { restore Ctrl-Break }πEND.π(*******************************************************************)ππ Put all of this remaining message into a text file named CTRLCAD.SCR,π then type "DEBUG < CTRLCAD.SCR" (no quotes) to create CTRLCAD.ARC,π and extract CTRLCAD.OBJ using PKUNPAK or PAK ...π======================= Start of DEBUG script =========================π nCTRLCAD.ARCπ e100 FC BB 03 00 BF A5 01 BE 85 01 8A EF AD 86 CC AA FE C0 E2 FB 4B 75π e116 F5 B9 FF FD BA 00 02 52 B4 3F CD 21 5F 72 66 8B F7 50 8B C8 B0 2Aπ e12C F2 AE 75 5B B0 0D F2 AE 87 F7 BB 00 01 B2 04 AC 3C 2A 72 FB 74 4Cπ e142 57 BF A3 01 B9 40 00 8A E1 F2 AE 5F 75 3B FE C1 2A E1 88 27 43 FEπ e158 CA 75 E0 56 BE 00 01 AD 86 C4 8B D0 AD 86 C4 5E B1 02 D2 E0 D3 E0π e16E D2 E2 D3 EA D0 E1 D1 EA D1 D8 E2 FA 86 C2 AA 8A C4 AA 8A C2 AA EBπ e184 B1 30 0A 41 1A 61 1A BF 00 02 58 F7 D8 99 33 DB 8B CA 8B D0 B8 01π e19A 42 57 CD 21 59 80 ED 02 CC 2B 2Dπ g=100π w200π q GXD v3.3a: XX34-to-DEBUG script code by Greg Vigneaultππ*XX3401-000345-041092--72--85-16010-E---CTRLCAD.ARC--1-OF--1π4UV1J37AEo329Yx0GU-SCU2++2EN28fLRqA-+++AU-c+K104XVkqMw8EQF3YGVAyZUs++2-Uπm-AWFMVUYcXY2k+-+U9IUEH+mQE+-uV60E7ZG-+WDmMWI7YYcogWSKFON272m7AbJ-H7j-72πGVCTE+hBH41YWNEXFOXQx1BlEF6bGOWcN5Zn6c-nW+VA3-IU4eVF++7ALAHBle6X+ZmU-S1qπ0+4t2qQ+kkh+aBUVPy1YYNDa1-cu649Ym021l-2LIplM8SmaH7UuPCWk+12YX-i3MHXhUy7-πfmBgc0sE6A4+-sAu1gW-sH431UESIiWotY+5kEQgbJnwQn3Fi647g20M+z4vonA+Y+ms01Jlπa3uykrPFY9-ik8szTok1At56Utmvkvo0yDTD4eQQ+6UVG-hUHbk6xCj2ho1zHbkmxBZ5H-fxπlPR5UQE6Ua+ax4o0+0O801+F5Fc+π***** END OF XX-BLOCK *****ππ======================== End of DEBUG script ==========================π 69 01-27-9411:58ALL TOBIN FRICKE Ctrl-Break Disabler IMPORT 12 ╔Ü {π-> I'm having alot of trouble trying to stop people breaking out of myπ-> programs. I've been trying to figure out how to stop theπ-> <ctrl>-<break>, <ctrl>-<c> , but with no luck... Can't seem to findπ-> anything in the help menu's....π-> ---ππIf you are using CRT, use CHECKBREAK:=FALSE. Also, you can disble itπpermenantly like this:π}πProgram TTXBREAK_Which_Means_TobinTech_ControlBreak_Disabler_Program;πππUses DOS,CRT;ππ{$M 2000,0,0}π{$R-,S-,I-,F+,V-,B-}ππConst ControlCInt=$23;π ControlBreakInt=$1B;πππVarπ OldControlCVec:Pointer;π OldControlBreakVec:Pointer;ππProcedure STI;πInline($FB);ππProcedure CLI;πInline($FA);ππProcedure CallOldInt(Sub:Pointer);πbeginπ Inline($9C/ { PUSHF }π $FF/$5E/$06);πend;ππProcedure BlockInterrupt; Interrupt;π {BlockInterrupt is a generic procedure for blocking an interrupt}πbeginπ STI;πend;πππbeginπ Writeln('TobinTech Control-C disable program ');π GetIntVec(ControlCInt, OldControlCVec);π SetIntVec(ControlCInt, @BlockInterrupt);π Writeln(' > CONTROL-C disabled. ');π GetIntVec(ControlBreakInt, OldControlBreakVec);π SetIntVec(ControlBreakInt, @BlockInterrupt);π Writeln(' > CONTROL-BREAK disabled. ');π Writeln(' Terminating, but Staying Resident in memory...');π Keep(0);πEnd.π 70 02-03-9416:08ALL J.E. CLARY Access Keyboard Status ByIMPORT 62 u8 {========================================================================}π { }π { If you find these procedures/functions useful, please help support the }π { SHAREWARE system by sending a small donation ( up to $5 ) to help with }π { my college education. Reguardless of a donation, use these routines in }π { good health (and with a clear concious), I hope you find them useful. }π { }π { }π { Send Any Replies To: EUROPA Software }π { 314 Pleasant Meadows Dr. }π { Gaffney, SC 29340 }π { }π { Program: KB_v02 Last Revised: 11/21/89 }π { }π { Author: J.E. Clary }π { }π { Using ALL of these routines increases the .EXE by only 336 bytes. }π { }π { Implementation: Turbo Pascal v.4.0 & v.5.0 }π { }π { Purpose: }π { }π { This UNIT is to provide direct access to the Keyboard status byte. }π { It is intended to use while running under MS-DOS. The unit will not }π { function properly, if at all, when running under OS/2. This is because }π { low-memory access is denied under OS/2 to protect the Operating System.}π { If you need these functions under OS/2 they are easily accesible by }π { calling OS Interrupt 9, which returns status bytes 40:17h and 40:18h }π { 'leagally'. The UNIT is written to carry as little excess baggage as }π { possible ( only 16 bytes in constants and work variables ) and execute }π { as fast as possible. This is achieved by directly addressing the key- }π { board status byte instead of calling the Operating System. }π { }π {========================= DISCALIMER ===============================}π { }π { }π { These routines are provided AS IS. EUROPA Software, nor any of its }π { employees shall be held liable for any incidental or consequential }π { damage attributed to the use, or inability to use this product. }π { }π { }π {========================================================================}ππunit KB_v02;ππ INTERFACEππ const Right_Shift = 0; { Key_To_Check Constants }π Left_Shift = 1;π Control_Key = 2;π Alt_key = 3;ππ Scroll_Lock_Key = 4; { Key_To_Set Constants }π Number_Lock_Key = 5;π Caps_Lock_Key = 6;ππ State_Off = 0; { Action Constants }π State_On = 1;π State_Toggle = 2;πππ function Is_Key_Pressed( Key_To_Check : byte ) : boolean;ππ procedure Set_Keyboard_State( Key_To_Set, Action : byte );π procedure Save_Keyboard_Status;π procedure Restore_Keyboard_Status;π procedure Clear_Type_Ahead_Buffer;ππππ IMPLEMENTATIONπππ var Hold_Keyboard_Status, Or_Mask, And_Mask : byte;ππ kb_stat : byte absolute $0:$417; { Keyboard Status Byte }π tail_buf : byte absolute $0:$41C; { Tail of Circular KB Buffer }π head_buf : byte absolute $0:$41A; { Head of Circular KB Buffer }πππ procedure Clear_Type_Ahead_Buffer;ππ beginππ tail_buf := head_buf;ππ end;ππππ procedure Save_Keyboard_Status;ππ beginππ Hold_Keyboard_Status := kb_stat;ππ end;ππππ procedure Restore_Keyboard_Status;ππ beginππ kb_stat := Hold_Keyboard_Status;ππ end;ππππ function Is_Key_Pressed( Key_To_Check : byte ) : boolean;ππ beginππ Or_Mask := (1 SHL Key_To_Check);π Is_Key_Pressed := ((kb_stat AND Or_Mask) = Or_Mask);ππ end;ππππ procedure Set_Keyboard_State( Key_to_Set, Action : byte );ππ beginππ Or_Mask := 1 SHL Key_To_Set;π And_Mask := (NOT Or_Mask);ππ case Action ofππ 0: kb_stat := kb_stat AND And_Mask; { Off }π 1: kb_stat := kb_stat OR Or_Mask; { On }ππ 2: if ( kb_stat AND Or_Mask) = Or_Mask then { Toggle }π kb_stat := (kb_stat AND And_Mask)π else kb_stat := (kb_stat OR Or_Mask);ππ end;ππ end;ππππ begin { UNIT Initialization Code }ππ Hold_Keyboard_Status := 0;ππ end.ππ{ -------------------------- DEMO ----------------------------}ππprogram test_KB;ππ { Demonstates the use of the KB_v02 Unit. }ππ uses crt, KB_v02;ππ const on = 'Key is Pressed ';π off = 'Key isn''t Pressed';π EveryMsg = 'Any Key to Force ';π MidMsg = ' Lock Key to ';ππ lock_keys : array[1..3] of byte =ππ ( Number_Lock_Key, Caps_Lock_Key, Scroll_Lock_Key );ππ key_states : array[1..3] of byte =ππ ( State_On, State_Off, State_Toggle );πππ key_names : array[1..3] of string = ('Number','Caps','Scroll');π state_names : array[1..3] of string = ('On','Off','Toggle');ππππ var i,j : byte;ππ procedure BurnKey;ππ var ch : char;ππ beginππ ch := readkey;π if ch = #0 then ch := readkey;ππ end;ππ procedure writeAT( x,y : byte; st : string );ππ beginππ gotoxy( x,y );π write( st );ππ end;πππ beginππ clrscr;π writeln( 'DEMO of Is_Keypressed Function' );π writeln;π writeln( ' Any Normal Key to continue ' );ππ writeAT( 10, 10, 'Alt Key Status' );π writeAT( 10, 12, 'CTRL Key Status' );π writeAT( 10, 14, 'Left Shift Status' );π writeAT( 10, 16, 'Right Shift Status' );πππ repeatππ if Is_Key_Pressed( Alt_Key ) then writeAT( 30,10, on )π else writeAT( 30,10, off );ππ if Is_Key_Pressed( Control_Key ) then writeAT( 30,12, on )π else writeAT( 30,12, off );ππ if Is_Key_Pressed( Left_Shift ) then writeAT( 30,14, on )π else writeAT( 30,14, off );ππ if Is_Key_Pressed( Right_Shift ) then writeAT( 30,16, on )π else writeAT( 30,16, off );ππ delay(100);ππ until keypressed;ππ clrscr;ππ burnkey;π writeln('Keyboard Status Saved' );π writeln;ππ Save_Keyboard_Status;ππ for i := 1 to 3 do beginππ for j := 1 to 3 do beginππ writeln( EveryMsg, key_names[i], MidMsg, state_names[j] );π burnkey;π Set_Keyboard_State( Lock_Keys[i], key_States[j] );ππ end;ππ writeln;ππ end;ππ writeln;π writeln( 'End of Demo.' );π writeln( 'Any Key to Restore Original Lock Status and Exit.' );ππ BurnKey;ππ Restore_Keyboard_Status;ππ end.ππ 71 02-03-9416:08ALL MAYNARD PHILBROOK Pushing Chars into bufferIMPORT 7 ═W {πFrom: MAYNARD PHILBROOKπSubj: Re: keyboard bufferπ---------------------------------------------------------------------------π TH> How do you write TO the keyboard buffer.π TH> I need a routine that will put a string into the keyboard buffer thenπ TH> exit to the calling program leaving the key buffer full.π TH> This is to simulate a macro function for a menu program.π}π function PushIntoKeyBoard( c:char; ScanCode:Byte):boolean;π Beginπ asmπ Mov Ah, 05hπ Mov Ch, ScanCode;π Int $16;π Mov @result, Al; { Results }π End;π Result := Not(Result);π End;ππ{returns true if Buffer took it other wise it mite be full or Not Supported}π 72 02-03-9416:08ALL IAN LIN Asm access to Keyboard IMPORT 7
{πFrom: IAN LINπSubj: keyboard bufferπ---------------------------------------------------------------------------π TH> How do you write TO the keyboard buffer.ππThese are all procedures. You could easily rewrite them to be functions orπwrite functions that call these and use them.ππHigh byte is scan code, low byte is character.π}ππProcedure putkey(key:word);π assembler; {PUTKEY}π asm; mov ah,5; mov cx,key; int 16h;πend;πππ{To find out what ones belong to each key (E is for enhanced; the other willπfilter enhanced keys): }ππProcedure egetkey(Var key:word);πVar tmp:word;πBeginπ asm; mov ah,10h; int 16h; mov tmp,ax; end;π key:=tmp;πend;ππProcedure getkey(Var key:word);πVar tmp:word;πBeginπ asm; xor ah,ah; int 16h; mov tmp,ax; end;π key:=tmp;πend;π 73 02-03-9416:15ALL BERNIE PALLEK Checking Keys begin Held IMPORT 15 ╕y πUNIT MultiKey;ππINTERFACEππVARπ KeyStat : Array[1..127] OF ShortInt;π { 0 (not physically down)π 1 (that sucker's down)π -1 (it's being held, don't repeat) }ππPROCEDURE EnableMultiKey;πPROCEDURE DisableMultiKey;ππIMPLEMENTATIONππUSES Dos;ππVARπ OldKbdInt : Pointer;π OldCtrlBreakInt : Pointer;π OldKeyExitProc : Pointer;ππPROCEDURE ClearKeyValues;πVARπ keyclearcounter : Byte;πBEGINπ FOR keyclearcounter := 1 TO 127 DO KeyStat[keyclearcounter] := 0;πEND;ππPROCEDURE NewKeyExitProc; Far;πBEGINπ SetIntVec($09, OldKbdInt);π SetIntVec($1B, OldCtrlBreakInt);π ExitProc := OldKeyExitProc;πEND;ππPROCEDURE NewCtrlBreakInt; Interrupt;π{ it is important that the new Ctrl-Break handler does *nothing* }πBEGINπEND;ππPROCEDURE NewKbdInt; Interrupt;πVARπ p60 : Byte;πBEGINπ p60 := Port[$60];π Port[$61] := Port[$61] OR 128; {/ keyboard \}π Port[$61] := Port[$61] AND (NOT 128); {\ acknowledge /}π IF (p60 > 0) THEN BEGINπ IF (p60 > 127) THENπ KeyStat[p60 AND 127] := 0π ELSEπ IF (KeyStat[p60] = 0) THEN Inc(KeyStat[p60]);π END;π ASM CLI; END; {disable hardware ints}π MemW[$0040:$001A] := MemW[$0040:$001C]; {clear buffer}π ASM STI; END; {restore hardware ints}π Port[$20] := $20; { send EOI to PIC }πEND;ππPROCEDURE EnableMultiKey;πBEGINπ SetIntVec($09, Addr(NewKbdInt));πEND;ππPROCEDURE DisableMultiKey;πBEGINπ SetIntVec($09, OldKbdInt);πEND;πππBEGIN { unit initialization }π GetIntVec($1B, OldCtrlBreakInt);π SetIntVec($1B, Addr(NewCtrlBreakInt));π ClearKeyValues;π OldKeyExitProc := ExitProc;π ExitProc := Addr(NewKeyExitProc);π GetIntVec($09, OldKbdInt);π EnableMultiKey;πEND.ππ 74 02-03-9416:44ALL LOU DUCHEZ Multiple Key Input IMPORT 59 (*π>Can someone help me out? I need to able to read keyboard input likeπ>having the spacebar helddown then having the Right arrow used?ππHOW TO ENABLE YOUR KEYBOARD TO READ MULTIPLE KEYS SIMULTANEOUSLYππ- by Lou DuChezππManuals will tell you that you can read port 60h to determine if aπkey is being pressed/released. What they don't tell you is, theπkeyboard interrupt (09h) will instantly process the port and resetπit to zero as soon as any keyboard activity occurs; so by the time youπget to look at it, port 60h invariably contains no data for you to use.πTo use port 60h, then, you'll need to alter the keyboard interrupt soπthat the port's data gets stored to variables you can use.ππThe routine in this post will let you read multiple keys simultaneously.πI will do this by making an array [0..127] of boolean called KeyDown:πit records the status of each key on your keyboard with "true" meaningπ"down." The lower seven bits of port 60h tell you which key is beingπreported on (i.e., the "scan code" of the key); the high bit indicates aπ"press" if it's 0 and a "release" it it's 1. So when you press orπrelease a key, my new keyboard interrupt routine will determine which keyπis being altered, and set the proper element of KeyDown to the right value.ππYou will probably want to compile your program as "far" ({$F+}), or makeπa unit out of these routines. You will need these global variableπdeclarations:π______ππ*)πvar keydown: array[0..127] of boolean; { see the above }π oldkbdint: procedure; { points to the "normal" keyboard handler }π(*π______ππNext, put these lines of code in your program, maybe in the "main" part:π______ππ*)πgetintvec($09, @oldkbdint); { record location of old keyboard int }πsetintvec($09, @newkbdint); { this line installs the new interrupt }π(*π______ππWe need to recall the location of the "normal" keyboard handler for twoπreasons: because we'll need to restore it when the program terminates, andπbecause the "new" handler will need to call it. (The "old" handler performsπcertain housekeeping duties that we still need.) This is the new keyboardπinterrupt handler:π______π*)ππprocedure newkbdint; interrupt;πbeginπ keydown[port[$60] mod 128] := (port[$60] < 128); { record current status }π asm pushf; end; { must precede call to old int }π oldkbdint; { call old interrupt }π asm cli; end; { disable hardware interrupts }π memw[$0040:$001a] := memw[$0040:$001c]; { clear the keyboard buffer }π asm sti; end; { enable hardware interrupts }π end;π(*π______ππExplanations:ππThe "KeyDown" line checks the indicated key for a press or release. Ifπthe port is returning something less than 128 (i.e., high bit of "0"),πthe key is not down. The "ASM PUSHF; END" line "pushes" all theπ"flags" onto the stack and is necessary before calling the originalπinterrupt routine on the next line. The "ASM CLI; END" line performsπan assembler instruction to prevent hardware interrupts just longπenough for the next line to clear the keyboard buffer; then the "ASMπSTI; END" line re-enables hardware interrupts. (About the keyboardπbuffer: it's a ring buffer, where a block of usually 32 bytes is usedπto store unprocessed keystrokes. It's a "ring" because there areπpointers to the "first unread" character and the "last unread"πcharacter. The "Memw" line sets the pointers equal to each other, thusπ"clearing" the buffer.)ππFinally, when you're done with your new keyboard interrupt, restore theπ"normal" keyboard handler with this line:π*)πsetintvec($09, @oldkbdint);π(*πAnd that should do it. See the next message for the complete program ...ππHOW TO ENABLE YOUR KEYBOARD TO READ MULTIPLE KEYS SIMULTANEOUSLYππFrom the top, your program should look like:π______π*)ππ{$F+}πProgram KeyboardThingie;πUses Dos; { needed for all the interrupt stuff }ππvar keydown: array[0..127] of boolean;π oldkbdint: procedure;ππprocedure newkbdint; interrupt;πbeginπ keydown[port[$60] mod 128] := (port[$60] < 128); { record current status }π asm pushf; end; { must precede call to old int }π oldkbdint; { call old interrupt }π asm cli; end; { disable hardware interrupts }π memw[$0040:$001a] := memw[$0040:$001c]; { clear the keyboard buffer }π asm sti; end; { enable hardware interrupts }π end;ππbegin { the main program }π fillchar(keydown, 128, #0); { sets array to all "false" }π getintvec($09, @oldkbdint);π setintvec($09, @newkbdint);π {π Put your own code here to actually do something. The following line ofπ code will report all keys that are currently "down"; to use it you'll needπ to declare "i" as a byte variable:ππ while not keydown[68] doπ for i := 0 to 127 do if keydown[i] then write(i:4);π }π setintvec($09, @oldkbdint);π end.π(*π______ππSomething to watch out for: this routine does nothing about "Ctrl-Break."πIf someone hits "Ctrl-Break" while the alternate keyboard handler isπworking, the program will terminate. Which means that the block of memoryπholding the "new" handler will be open to reuse by other programs. Whichπmeans that your system will crash. So to prevent this, you should alsoπmake a new "Ctrl-Break" handler. The approach is much like the above,πbut with two differences: the "Ctrl-Break" interrupt is interrupt 1Bh,πand you'll want your new handler to do absolutely nothing. NOTHING.πAs in, no lines of code between "begin" and "end."ππFinally, to use all this, you'll need to know the "scan codes". Noticeπthat a typical key can generate two different characters (like "1" andπ"!"); the two characters have the same scan code because the same keyπproduces both. Here are the scan codes:π______ππ"1" - "=" : $02 - $0Dπ"Q" - "}" : $10 - $1Bπ"A" - '"' (the "quote" key) : $1E - $28π"Z" - "?" : $2C - $35πF1 - F10 : $3B - $44ππ"space" : $39 "~" : $29 "|" : $2bπ"escape" : $01 "backspace" : $0E "control" : $1Dπ"left shift" : $2A "caps lock" : $3A "scroll lock" : $46π"tab" : $0F "enter" : $1C "right shift" : $36π"printscreen": $37 "alt" : $38 "home" : $47π"up" : $48 "page up" : $49 "minus" (pad) : $4Aπ"left arrow" : $4B "middle" key: $4C "rightarrow": $4Dπ"plus" (pad) : $4E "end": $4F "down": $50π"page down" : $51 "insert" : $52 "delete" : $53π"num lock" : $45 F11 : $D9 F12 : $DAπ______ππUse them however you want. I tend to set up the non-character codesπ(like the arrows and "enter" key) as constants. For the "character"πcodes (like '1' and 'K'), I set up an array called ScanOf: it's anπarray[' '..'~'] of byte that I use to get the scan codes of charactersπwith. For example, at the start of my unit that contains all this, Iπload in ScanOf['3'] with $04, meaning that character '3' correspondsπto scan code $04. Then, if I need to see if the '3' key is down,πI check:ππKeyDown[ScanOf['3']]π^^^^^^^ ^^^^^π | converts character to scan code (i.e., which "key")π +--- checks the specified keyππ"True" means "it's down." But do what you want.π---π*) 75 02-05-9407:56ALL PHIL NICKELL Keypress - NO Ctrl-Break IMPORT 13 {ππI have a program that needed to disable Ctl-Break. The program uses theπCRT unit, and the program also used the Readkey() function and theπKeypressed() function. In order to keep Ctl-Brk from 'working' I had toπreplace *both* the Readkey and Keypressed functions with my own, becauseπthose functions, in the TP units, respond to Ctl-Break. I Also had toπset CheckBreak to false early in the main program routine.ππThe following _Keypressed() function uses bios interrupt 16h to testπto see if a key was pressed and a keystroke is in the keyboard buffer.πIt is used just like the TP Keypressed function, and does not processπ(responed to) ctl-break. ( if _keypressed then ... ) }ππfunction _keypressed: Boolean; Assembler;π asmπ push ds { save TP DS reg }π push sp { save stack ptr }π mov ah, 1 { int 16h fcn 1 }π int 16h { ret zero flag clr if keypressed }π mov al, 0 { assume false }π jz @1 { keypressed ? }π mov al, 1 { set true }π @1:π pop spπ pop dsπ end;π{πThe following _readkey function uses dos interrupt 21h function 7 to getπa character from the keyboard buffer. It does not echo the characterπand does not process (respond to) ctl-break. It is used just like theπTP readkey function. ( c := _readkey; ) }ππfunction _readkey: Char;π var regs:registers;π beginπ regs.ah := 7;π msdos(regs);π _Readkey := char(regs.al);π end;π 76 02-05-9407:57ALL GABRIEL LAGOS Stuffing Keyboard Buffer IMPORT 23 {π I found the following code in my Utils unit and repackaged into a newπ unit. It compiles and works on my PC, but as Im sure everyone willπ agree, this programming style is rather dirty! It assumes the keyboardπ buffer is in the same location in memory on every pc. I really shouldπ be using an interrupt but never got around to it.π Remember that you have a limit of only 16 characters in the buffer.ππ Anywayz hope it helps...ππ {-----------------------------------CUT HERE------------------------}ππUNIT KeyStuff;ππInterfaceππVarπ keyrec : array [1..16] ofπ recordπ ch ,π scan : char;π end absolute $0000:1054;π KeyPtr1: byte absolute 0000:1050;π KeyPtr2: byte absolute 0000:1052;ππ Procedure AdvanceKeyTail;π Procedure AdvanceKeyHead;π procedure FlushBuffer;π procedure StuffBufferKey(ch,Scan : char);π procedure StuffBuffer(W:word);π procedure StuffBufferStr(Str:string);π function tail:byte;π Function head:byte;ππImplementationπuses dos;ππProcedure AdvanceKeyTail;π{Moves the keyboard tail ptr forward}πbeginπ inc(KeyPtr1,2);π if keyptr1 > 60 then keyptr1 := 30;πend;ππProcedure AdvanceKeyHead;π{Moves the keyboard Head ptr forward.πTurbo's KeyPressed function will now return True}πbeginπ inc(KeyPtr2,2);π if keyptr2 > 60 then keyptr2 := 30;πend;ππprocedure FlushBuffer;π{Clear Keyboard Buffer}πvar Regs: registers;πbeginπ with Regs doπ beginπ Ax := ($0c shl 8) or 6;π Dx := $00ff;π end;π Intr($21,Regs);πend;ππprocedure StuffBufferKey(ch,Scan : char);π{Puts keyboard scan code directly into the bufferπExamples. #65,#0 = Simulate an 'A' being pressedπ #0,#59 = Simulate the F1 key being pressedπ}πbeginπ keyrec[head].ch := ch;π keyrec[head].scan := scan;π AdvanceKeyhead;πend;ππprocedure StuffBuffer(W:word);π{Put Word directly into the buffer}πbeginπ keyrec[head].ch := chr(lo(w));π keyrec[head].scan := chr(hi(w));π AdvanceKeyhead;πend;ππprocedure StuffBufferStr(Str:string);π{Stuffs a string into the buffer. Remember the max of 16 chars.}πvar I,L : byte;πbeginπ if Str <> '' thenπ beginπ I := 1;π L := length(Str);π while I <= L doπ beginπ StuffBuffer(ord(Str[I]));π inc(I);π end;π end;πend;ππfunction Tail:byte;π{Returns number between 1 and 16 showing where tail is}πbeginπ tail := KeyPtr1 div 2 - 14;πend;ππFunction Head:byte;π{Returns number between 1 and 16 showing where head is}πbeginπ head := KeyPtr2 div 2 - 14;πend;ππend.ππ {-----------------------------------CUT HERE------------------------}ππ*********************πExample of use...π*********************ππUses Keystuff;ππbeginπ StuffBufferStr('Hello There!'#13);π Write('>');π Readln;π halt;πend.π 77 05-25-9408:13ALL DAVID KANDRAT pgdn/pgup SWAG9405 15 π{πHere is an (TP 5.5) atom that will help you grab "extended"πkeyboard scancodes. I think the problem you're having has toπdo with the fact that you can't trap hot keys inside ReadLn,πyes? You need to build a set of routines that supportπa-key-at-a-time input into a string, echoing the keystrokesπto the screen as you go. This "atom" just handles keystrokes-πthe string handling is probably _WAY_ too long to list here.π}ππProgram _;ππUses Crt;ππType KeyType = (Ascii,ExtendedKey,Escape);ππVarπKtGlb : KeyType;πChGlb : Char;ππProcedure GetExtKey( Var Ch:Char; Var Kt:KeyType; );πBeginπ Repeatπ Until KeyPressed;π Kt := Ascii;π Ch := ReadKey;π If (Ch=#0) Thenπ Beginπ Ch := ReadKey;π If (Ord(Ch)=27) Then Kt := Escape Else Kt := ExtendedKey;π End;πEnd;ππProcedure MainπBeginπ Write('Press a key.');π ChGlb := #0;π KtGlb := Ascii;π Repeatπ GotoXY(13,1);π GetExtKey(ChGlb,KtGlb);π GotoXY(1,2);π ClrEol;π GotoXY(1,2);π Case KtGlb Ofπ Ascii : Write('Ascii, ');π ExtendedKey : Write('Extended, ');π Escape : Write('Escape, ')π End;π Write('Scancode = ',Ord(Ch));π Until (Kt=Escape);π WriteLn;π WriteLn;πEnd;ππBeginπ ClrScr;π Main;πEnd.ππThis should help you capture _any_ extended scan code from the keyboard.πPgUp, PgDn, Ctrl-PgUp, Alt-Shft-F5, etc... Chapter Seventeen of "TurboπPascal 5.5, The Complete Reference" by O'Brien (Borland/Osborne/McGraw-πHill ISBN 0-07-881501-0) covers the issue of buffered string input prettyπwell.ππAnd as for your next berrage of questions, "Turbo Pascal AdvancedπTechniques" by Ohlsen & Stoker (Que Corp. ISBN 0-88022-432-0) coversπDOS windowing very nicely. (Also many other goodies).ππHope it helped a little.πDavid Kandratπ 78 05-26-9406:11ALL JEFF FANJOY Key Input Unit IMPORT 100 UNIT KeyInput;ππINTERFACEππUSES CRT, {Import Sound function}π CURSOR; {Import ChangeCursor}ππCONSTπ StandardInput = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUV'π +'WXYZ1234567890~!@#$%^&*()-+\[]{};:`''".,/<> =_?|';π HighBitInput = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUV'π +'WXYZ1234567890~!@#$%^&*()-+\[]{};:`''".,/<> =_?|'π +'ÇüéâäàåçêëèïîìÄÅÉæÆôöòûùÿÖÜ¢£¥₧ƒáíóúñѪº¿⌐¬½¼¡«'π +'»░▒▓│┤╡╢║╕╣║╗╝╜╛┐└┴┬├─┼╞╟╚╔╩╦╠═╬╧╨╤╥╙╘╒╓╫╪┘┌█▄▌▐'π +'▀αßΓπΣσµτΦΘΩδ∞φε∩≡±≥≤⌠⌡÷≈°∙·√ⁿ²■';π FilenameInput = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUV'π +'WXYZ1234567890~!@#$%^&()-_{}.';π FilespecInput = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUV'π +'WXYZ1234567890~!@#$%^&()-_{}.?*';π FilepathInput = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUV'π +'WXYZ1234567890~!@#$%^&()-_{}.?*:\';π NumberInput = '123456790.-+';ππ BackSpace = #8;π Space = ' ';πππTYPEπ TInput = (Standard,HighBit,Filename,Filespec,Filepath,Number);πππVARπ MaskCh: Char; {must be set before using}πππPROCEDURE GetInput(VAR InStr; (* Variable being edited *)π WhatWas: String; (* "Old" Value -- being edited *)π InputType: TInput; (* Input type -- from TInput *)π Len, (* Maximum Characters *)π XPos, (* X Start Position *)π YPos, (* Y Start Position *)π Attr, (* Text Attribute while editing *)π HighLightAttr: Byte; (* Attribute of Highlighted Text *)π BackCh: Char; (* Background Character *)π MaskInput, (* Masked Input? -- Set "MaskCh" *)π Caps: Boolean); (* Force CAPS? *)πππIMPLEMENTATIONπππPROCEDURE MY_Delay(MS: Word); Assembler;π (* My Delay procedure, used instead of TP6.0's Delay procedure *)ππASMπ MOV Ax, 1000;π MUL MS;π MOV Cx, Dx;π MOV Dx, Ax;π MOV Ah, $86;π INT $15;πEND;πππPROCEDURE GetInput(VAR InStr;π WhatWas: String;π InputType: TInput;π Len,π XPos,π YPos,π Attr,π HighLightAttr: Byte;π BackCh: Char;π MaskInput,π Caps: Boolean);ππTYPEπ TInsert = (On,Off); (* Insert On/Off Type *)ππVARπ Temp: String; (* Temporary String Holder *)π Ch: Char; (* Reads Characters *)π A, B, U: Byte; (* Counters *)π ValidKey, (* Whether is valid key *)π FirstChar, (* Whether is first char entered *)π InsertOn, (* Insert or overstrike mode *)π NoAdd: Boolean; (* Whether to add key to string *)π NewString: String ABSOLUTE InStr; (* String being edited *)πππ PROCEDURE Ding;π (* Makes sound to tell user invalid key was pressed *)ππ BEGINπ Sound(300);π MY_Delay(30);π NoSound;π END;πππ PROCEDURE ToggleInsert(Ins: TInsert);π (* Toggles Insert/Overstrike Mode via TInsert type *)ππ BEGINπ IF Ins = On THENπ BEGINπ InsertOn := TRUE;π ChangeCursor(NormCursor);π ENDπ ELSEπ BEGINπ InsertOn := FALSE;π ChangeCursor(BlockCursor);π END;π END;πππ PROCEDURE FlushKBuff;π (* Flush keyboard buffer *)π VAR Flush: Char;ππ BEGINπ WHILE KeyPressed DO Flush := Readkey;π END;πππBEGINπ ChangeCursor(NormCursor); (* Default to normal cursor *)π InsertOn := TRUE; (* Default to Insert Mode *)π FirstChar := TRUE; (* Set to first character being entered *)π NewString := ''; (* Null NewString *)π Temp := ''; (* Null Temporary String *)π GotoXY(XPos,YPos);π TextAttr := Attr;π FOR U := 1 TO Len DO Write(BackCh);π GotoXY(XPos,YPos);π FlushKBuff;π Ch := #0;π TextAttr := HighLightAttr;π NewString := WhatWas;π IF MaskInput THEN FOR U := 1 TO Length(NewString) DO Write(MaskCh)π ELSE Write(NewString);π B := Length(WhatWas);π A := B;π (* "A" Counter = How many characters are in string *)π (* "B" Counter = Current cursor placement in string *)π TextAttr := Attr;π WHILE (Ch <> #13) AND (Ch <> #27) DOπ BEGINπ NoAdd := FALSE; (* Default to add key to string *)π ValidKey := FALSE; (* Default to invalid key unless proven valid *)π IF Caps THEN Ch := UpCase(ReadKey)π ELSE Ch := ReadKey;π CASE InputType OF (* Check if Ch is in the input list *)π Standard: IF (POS(Ch,StandardInput) > 0) ORπ (Ch IN [#13,#27,#0,#8,#25]) THEN ValidKey := TRUE;π HighBit : IF (POS(Ch,HighBitInput) > 0) ORπ (Ch IN [#13,#27,#0,#8,#25]) THEN ValidKey := TRUE;π Filename: IF (POS(Ch,FilenameInput) > 0) ORπ (Ch IN [#13,#27,#0,#8,#25]) THEN ValidKey := TRUE;π Filespec: IF (POS(Ch,FilespecInput) > 0) ORπ (Ch IN [#13,#27,#0,#8,#25]) THEN ValidKey := TRUE;π Filepath: IF (POS(Ch,FilepathInput) > 0) ORπ (Ch IN [#13,#27,#0,#8,#25]) THEN ValidKey := TRUE;π Number : IF (POS(Ch,NumberInput) > 0) ORπ (Ch IN [#13,#27,#0,#8,#25]) THEN ValidKey := TRUE;π END;π IF ValidKey THENπ BEGINπ CASE Ch OFπ #0 : BEGINπ NoAdd := TRUE;π IF FirstChar THENπ BEGINπ FirstChar := FALSE;π GotoXY(XPos,YPos);π IF MaskInput THEN FOR U := 1 TO Length(NewString) DO Write(MaskCh)π ELSE Write(NewString);π END;π Ch := UpCase(ReadKey);π CASE Ch OFπ #77: IF B <= Length(NewString)-1 THEN {Right Arrow}π BEGINπ GotoXY(XPos+B+1,YPos);π Inc(B);π ENDπ ELSE Ding;π #75: IF B >= 1 THEN {Left Arrow}π BEGINπ GotoXY(XPos+B-1,YPos);π Dec(B);π ENDπ ELSE Ding;π #71: BEGIN {Home}π GotoXY(XPos,YPos);π B := 0;π END;π #79: BEGIN {End}π GotoXY(XPos+Length(NewString),YPos);π B := Length(NewString);π END;π #82: IF InsertOn THEN ToggleInsert(Off) {Ins}π ELSE ToggleInsert(On);π #83: BEGIN {Del}π IF (B < Length(NewString)) AND (B >= 0) THENπ BEGINπ Delete(NewString,B+1,1);π FOR U := B TO Length(NewString) DOπ IF MaskInput THENπ BEGINπ IF U <> B THEN Temp := Temp + MaskChπ ELSE Temp := '';π ENDπ ELSEπ BEGINπ IF U <> B THEN Temp := Temp + NewString[U]π ELSE Temp := '';π END;π GotoXY(XPos+B,YPos);π Write(Temp);π Write(BackCh);π GotoXY(XPos+B,YPos);π Dec(A);π END;π END;π ELSE Ding;π END;π FlushKBuff;π END;π #8 : IF B >= 1 THEN {Backspace}π BEGINπ IF FirstChar THENπ BEGINπ FirstChar := FALSE;π GotoXY(XPos,YPos);π IF MaskInput THEN FOR U := 1 TO Length(NewString) DO Write(MaskCh)π ELSE Write(NewString);π END;π Delete(NewString,B,1);π Write(Backspace,BackCh,Backspace);π Dec(B);π Dec(A);π GotoXY(XPos+B,YPos);π FOR U := B TO Length(NewString) DOπ IF MaskInput THENπ BEGINπ IF B <> U THEN Temp := Temp + MaskChπ ELSE Temp := '';π ENDπ ELSEπ BEGINπ IF B <> U THEN Temp := Temp + NewString[U]π ELSE Temp := '';π END;π Write(Temp);π FOR U := Length(NewString)+1 TO Len DO Write(BackCh);π GotoXY(XPos+B,YPos);π NoAdd := TRUE;π ENDπ ELSE Ding;π #27: BEGIN {Esc}π NoAdd := TRUE;π NewString := WhatWas;π END;π #25: BEGIN {CTRL+Y}π NoAdd := TRUE;π NewString := '';π GotoXY(XPos,YPos);π FOR U := 1 TO Len DO Write(BackCh);π FirstChar := FALSE;π GotoXY(XPos,YPos);π B := 0;π A := 0;π END;π #13: NoAdd := TRUE;π END;π IF (((A < Len) OR ((A < Len+1) AND NOT(InsertOn))) AND (NoAdd = FALSE)π AND (Ch <> #8)) OR ((FirstChar) AND (NOT(NoAdd)) AND (Ch <> #8)) THENπ BEGINπ IF FirstChar THENπ BEGINπ NewString := '';π GotoXY(XPos,YPos);π B := 0;π A := 0;π FOR U := 1 TO Len Do Write(BackCh);π GotoXY(XPos,YPos);π FirstChar := FALSE;π END;π IF InsertOn THENπ BEGINπ Inc(B);π Inc(A);π Insert(Ch,NewString,B);π FOR U := B TO Length(NewString) DOπ IF MaskInput THENπ BEGINπ IF B <> U THEN Temp := Temp + MaskChπ ELSE Temp := '';π ENDπ ELSEπ BEGINπ IF B <> U THEN Temp := Temp + NewString[U]π ELSE Temp := '';π END;π GotoXY(XPos+B-1,YPos);π IF MaskInput THEN Write(MaskCh)π ELSE Write(Ch);π Write(Temp);π GotoXY(XPos+B,YPos);π ENDπ ELSEπ BEGINπ IF Length(NewString) < Len THENπ BEGINπ IF B >= Length(NewString) THEN Inc(A);π Inc(B);π Delete(NewString,B,1);π Insert(Ch,NewString,B);π IF MaskInput THEN Write(MaskCh)π ELSE Write(Ch);π ENDπ ELSE IF (A = Len) AND (B < Len) THENπ BEGINπ Inc(B);π Delete(NewString,B,1);π Insert(Ch,NewString,B);π IF MaskInput THEN Write(MaskCh)π ELSE Write(Ch);π END;π END;π END;π ENDπ ELSE Ding;π END;π FlushKBuff;π ChangeCursor(NormCursor);πEND;πππEND.ππ 79 08-24-9413:27ALL ROBBIE FLYNN Caps SWAG9408 j|M[ 13 {πhereya go. I've found that these come in pretty handy. You can makeπsome cool things with them too. I also have the code to detect ifπthe lights are on/off also if you want it.π}πuses crt; Procedure TurnCapsOn;Assembler;πASMππ SUB AX,AXπ MOV ES,AXπ MOV AL,64π OR ES:[417h],ALπ RETπEND;ππProcedure TurnNumOn;Assembler;πASMππ SUB AX,AXπ MOV ES,AXπ MOV AL,32π OR ES:[417h],ALπ RETπEND;ππProcedure TurnScrollOn;Assembler;πASMππ SUB AX,AXπ MOV ES,AXπ MOV AL,16π OR ES:[417h],ALπ RETπEND;ππProcedure TurnCapsOff;Assembler;πASMππ SUB AX,AXπ MOV ES,AXπ MOV AL,10111111bπ AND ES:[417h],ALπ RETπEND;ππProcedure TurnNumOff;Assembler;πASMππ SUB AX,AXπ MOV ES,AXπ MOV AL,11011111bπ AND ES:[417h],ALπ RETπEND;ππProcedure TurnScrollOff;Assembler;πASMππ SUB AX,AXπ MOV ES,AXπ MOV AL,11101111bπ AND ES:[417h],ALπ RETπEND;ππvarπ x : integer;π{Watch your lights} beginπ x:=0;π repeatπ inc(x);π if x mod 3 = 0 thenπ Begin TurnNumOn;TurnCapsOff;TurnScrollOff;π End;π If X mod 3 = 1 thenπ Beginπ TurnNumOff;TurnCapsOn;TurnScrollOff;π End;π If X Mod 3 = 2 thenπ Beginπ TurnNumOff;TurnCapsOff;TurnScrollOn;π End;π Delay(115);π until keypressed;πend.π 80 08-24-9413:38ALL FLORIAN ANSORGE Keyboard lights SWAG9408 <B6╡ 9 {π ER> Anyway, Does anyone knows who to make the num/caps/scroll leds on theπ ER> keyboard 'flicker' or just light up?π}ππPROGRAM FlashLED;ππUSES DOS, Crt;ππCONSTπ LOCKSOFF = $8F; { Mask off all LEDs }π SCRLOCK = 16;π NUMLOCK = 32;π CAPLOCK = 64;ππVARπ KeyLocks : BYTE ABSOLUTE $0040:$0017; { LED bits at this FAR address }π SaveLock : BYTE; { Used to save LED status bits }ππ{ To make DOS cause LED update }πPROCEDURE DummyDosCall; ASSEMBLER;πasmπ mov ah, 11π int $21πEnd;ππVARπ Shift : BYTE; { Used in bit shifting of LEDs }ππBEGINπ { Store current state }π SaveLock := KeyLocks;π Shift := 1;ππ Repeatπ { Turn on the LED bit according to Shift }π KeyLocks := (SCRLOCK SHL Shift);ππ { Set Shift to indicate the LED to the right }π Shift := (Shift + 1) MOD 3;ππ { Allow DOS to update the LEDs }π DummyDosCall;ππ { Simple pause }π Delay( 200 );π Until KeyPressed;ππ { Restore original keyboard state }π KeyLocks := SaveLock;πEND.π 81 08-24-9413:44ALL ALEX GRISCHENKO Keyboard Unit SWAG9408 u■4ï 105 π{$X+,S-,R-,I-,L-,O-,B-,D-}π{*****************************************}π{* Keyboard unit for BP 7.0 *}π{* Direct INT 9h support *}π{* Written by Alex Grischenko *}π{* Modified by Olaf Bartelt for DPMI *}π{* (C) AntSoft Lab , 1994 *}π{* Version 1.0 30-06-94 *}π{*****************************************}ππUnit Keyboard;ππinterfaceππtypeπ DoubleKey = objectπ Left,Right : boolean;π function Both : boolean;π function Any : boolean;π end;ππ LockKey = recordπ Pressed,Locked : boolean;π end;ππ KeyEvent = recordπ case Integer ofπ 0: (KeyCode : Word);π 1: (CharCode: Char; ScanCode: Byte);π end;πππconstπ SEG0000 : WORD = $0000;ππ k_LShift = $2A00;π k_RShift = $3600;π k_LAlt = $3800;π k_RAlt = $3800 or $8000;π k_LCtrl = $1D00;π k_RCtrl = $1D00 or $8000;ππ k_PrtScr = $F900;π k_SysReg = $F800;π k_Pause = $F700;π k_Break = $F600;π k_CapsLock = $3A00;π k_NumLock = $4500;π k_ScrollLock = $4600;ππ k_AltCtrlDel = $F200;ππ WasKeybEvent : boolean = false; { Was event from keyboard }π Pressed : boolean = false; { TRUE - key pressed, FALSE - released }ππ ESC : boolean = false;π Alt : DoubleKey = ( Left : false; Right : false );π Ctrl : DoubleKey = ( Left : false; Right : false );π Shift : DoubleKey = ( Left : false; Right : false );π PrtScr : boolean = false;π CapsLock : LockKey = ( Pressed : false; Locked : false );π NumLock : LockKey = ( Pressed : false; Locked : false );π ScrollLock: LockKey = ( Pressed : false; Locked : false );π Pause : boolean = false;π CtrlBreak : boolean = false;ππ AltCtrlDel: boolean = false;ππprocedure InitKeyboard; { Initalize driver }πprocedure DoneKeyboard; { Uninstall driver }πfunction ReadKeyboard : byte; { Read current scancode from keyboardπ ( }πfunction KeyPressed : boolean; { Keys was pressed? }πfunction ReadKey : char; { For using instead CRT.ReadKey }πfunction ReadChar : char; { Converts scancode to ASC-key }πprocedure GetKeyEvent(var KEvent : KeyEvent);ππprocedure NullProc;π{procedure KeybLights(On : boolean; Light : byte);}ππconstπ AltCtrlDelproc : procedure = NullProc;π { Alt-Ctrl-Del Handler }ππimplementationππfunction DoubleKey.Both : boolean;πbeginπ Both:=Right and Left;πend;ππfunction DoubleKey.Any : boolean;πbeginπ Any:=Right or Left;πend;ππconstπ Key : byte = 0;π KeyboardSet : boolean = false;ππ KeyCodes : array [1..$58] of word = (ππ{******** 85 - key **********}π {ESC 1 2 3 4 5 6 7 8 9 0 - = BkSp}π 27, 49,50,51,52,53,54,55,56,57,48,45,61, 8,ππ {TAB Q W E R T Y U I O P [ ] Enter}π 9, 81,87,69,82,84,89,85,73,79,80,91,93, 13,ππ {LCtrl A S D F G H J K L ; ' `}π k_LCtrl,65,83,68,70,71,72,74,75,76,59,39,96,ππ {LShift \ Z X C V B N M , . / RShift}π k_LShift,92,90,88,67,86,66,78,77,44,46,47, k_RShift,ππ { * LAlt Space CapsLock}π 42, k_LAlt, 32, k_CapsLock,ππ {F1 F2 F3 F4 F5 F6 F7 F8 F9 F10}π $3B00,$3C00,$3D00,$3E00,$3f00,$4000,$4100,$4200,$4300,$4400,ππ { NumLock ScrollLock}π k_NumLock, k_ScrollLock,ππ {Home Up PgUp K - Left K 5 Right K +}π $4700,$4800,$4900,$4A2D,$4b00,$4c00,$4d00,$4e2b,ππ { End Down PgDn Ins Del}π $4f00,$5000,$5100,$5200,$5300,ππ{******** 101 - key **********}π {AltPrtScr F11 F12}π $5400, 0, 0, $5700, $5800);ππ ExtCode : byte = 0;π ExtExtCode : byte = 0;π Extent : boolean = false;ππvarπ oldint9seg,oldint9ofs : word;π Lights : byte ;π{ Queue : array[0..30] of byte;π} QHead,QTail : word;πππ{ - Wait keyboard }πprocedure WaitKeyb; near; assembler;πasmπ push axπ@@Wait:π in al,64hπ test al,02hπ loopnz @@Waitπ pop axπend;ππ{ - Send byte to keyboard port }πprocedure SendIt; near; assembler;πasmπ cliπ call WaitKeybπ out 64h,alπ stiπend;ππprocedure SetLights; near; assembler;πasmπ(*π push axπ mov al,0EDhπ{ call SendIt}π out 60h,alπ mov cx,200hπ@loop:π loop @loopπ mov al,Lightsπ{ call SendIt }π out 60h,alπ pop axπ*)πend;πππprocedure MyInt9(Flags, CS, IP, AX, BX,πCX, DX, SI, DI, DS, ES, BP: Word); interrupt;πlabel IntEnd,SendEOI;πbeginπ asmπ mov ax, seg @dataπ mov ds,axππ mov al,0adh { Disable keyboard }π call senditπ cliππ call WaitKeyb { Wait }ππ in al,60h { Get keycode }π stiπ mov key,al;ππpush axπmov al,0AEhπcall senditπmov al,20hπout 20h,alπpop axππ@@keyEvent:π mov WasKeybEvent,1 { Set event flag }ππ mov ah,alπ and ah,0F0h { Was extented keystroke ? }ππ cmp ah,0E0hπ jne @NormalCodeπ(* jne @CheckAA { no, check next ext. code AAh }ππ cmp ExtCode,0AAh { Was sequence E0 AA E0 ? }π jne @ExtCode { No, set as firts extent code }ππ mov Extent,0 { yes, clear exten flags }π mov ExtCode,0π{ mov al,91 { Return as Shift key pressed }π jmp IntEndπ*)π @ExtCode:π mov Extent,1 { yes, set flag and store extented code }π mov ExtCode,alπ mov WasKeybEvent,0π jmp IntEnd { finish interrupt }ππ @NormalCode:π mov ah,alπ and al,7Fh { mask low 7 bits }ππ cmp al,60hπ jb @@IsKeyππ cmp al,0A0hπ jb IntEndππ@@IsKey:π and ah,80h { check pressing }π je @@Pressedππ mov Pressed,0 { if higher bit set to 1, then key released }π jmp @@1ππ @@Pressed:π mov Pressed,1ππ @@1:π mov key,al { store key }π mov ah,Pressedππ{------------------------}π cmp al,1π jne @PrtScrπ mov ESC,ahπ jmp IntEndππ@PrtScr:π cmp al,37hπ jne @next0π cmp ExtCode,0E0hπ jne IntEndπ mov PrtScr,ahππ@next0:π cmp al,2ahπ jne @next1π cmp ExtCode,0E0hπ jne @ShiftLπ@ExtShift:π xor ax,axπ mov WasKeybEvent,alπ mov ExtCode,alπ mov key,alπ jmp IntEndπ@ShiftL:π mov Shift.Left,ahπ jmp IntEndππ@next1:π cmp al,36hπ jne @next2π cmp ExtCode,0E0hπ je @ExtShiftπ mov Shift.Right,ahπ jmp IntEndππ@next2:π cmp al,38hπ jne @next3π cmp ExtCode,0E0hπ je @RAltπ mov Alt.Left,ahπ jmp IntEndπ @Ralt:π mov Alt.Right,ahπ jmp @@ResetExtπππ@next3:π cmp al,1Dhπ jne @next4π cmp ExtCode,0E0hπ je @RCtrlπ mov Ctrl.Left,ahπ jmp IntEndπ @RCtrl:π mov Ctrl.Right,ahπ jmp @@ResetExtππ@next4:π cmp al,3ahπ jne @next5π mov CapsLock.Pressed,ahπ cmp ah,1π je IntEndπ xor CapsLock.Locked,1π xor Lights,4π mov ax,0AEhπ{ call SendIt}π call SetLightsπ jmp SendEOIππ@next5:π cmp al,45hπ jne @next6π mov NumLock.Pressed,ahπ cmp ah,1π je IntEndπ xor NumLock.Locked,1π xor Lights,2π mov ax,0AEhπ{ call SendIt }π call SetLightsπ jmp SendEOIππ@next6:π cmp al,46hπ jne @next7π mov ScrollLock.Pressed,ahπ cmp ah,1π je IntEndπ xor ScrollLock.Locked,1π xor Lights,1π mov ax,0AEhπ { call SendIt}π call SetLightsπ jmp SendEOIππ@@ResetExt:π xor ax,axπ mov ExtCode,alπ mov Extent,alπ jmp IntEndππ@next7:π cmp al,53hπ jne IntEndπ end;ππ AltCtrlDel:=pressed and Alt.Any and Ctrl.Any;ππ if AltCtrlDel then AltCtrlDelProc;ππIntEnd:πasmπ{ Interrupt end }{π mov al,0aehπ call sendit }πSendEOI: {π mov al,20hπ out 20h,al }π end;πend;πππprocedure InitKeyboard; assembler;πasmπ cmp KeyboardSet,0π jne @@Quitππ@ClearBufferLoop:π mov ah,1π int 16hπ jz @NoKeybπ xor ax,axπ int 16hπ jmp @ClearBufferLoopππ@NoKeyb:π mov ax,3509hπ int 21hπ mov oldint9seg,esπ mov oldint9ofs,bxππ push dsππ push csπ pop dsπ mov ax,2509hπ mov dx,offset MyInt9π int 21hπ pop dsππ cliπ xor ax,axπ mov QHead,axπ mov QTail,axπ mov Key,alππ xor ax,axπ mov es,SEG0000π mov al,byte ptr es:[417h]π mov cl,4π shr al,clπ mov Lights,alππ mov KeyboardSet,1π stiπ@@Quit:πend;ππprocedure DoneKeyboard; assembler;πasmπ cmp KeyboardSet,0π je @@Quitπ xor ax,axπ mov es,SEG0000π mov ax,word ptr es:[417h]π mov bl,Lightsπ mov cl,4π shl bl,clπ and al,10001111b { Set Lights status }π or al,blπ and ax,111110011110000bπ mov word ptr es:[417h],axπππ push dsπ mov dx,oldint9ofsπ mov ax,oldint9segπ mov ds,axπ mov ax,2509hπ int 21hπ pop dsπ@@Quit:πend;ππfunction ReadKeyboard : byte; Assembler;πasmπ xor ax,axπ mov al,Key;π mov Key,ah;π mov WasKeybEvent,ahπend;ππfunction KeyPressed : boolean;πbeginπ KeyPressed:=WasKeybEvent and Pressed;πend;ππfunction ReadKey : char;πbeginπ if KeyboardSet thenπ beginππ endπ else beginπ Writeln(#7'KEYBOARD.TPU Error : use InitKeyboard first!');π halt;π end;πend;ππfunction ReadChar : char; assembler;πconstπ scancode : char = #0;πasmπ cmp ScanCode,0 { if were extented keystrokes }π je @@NoScanCodeππ mov al,ScanCode { then return scan code }π mov ScanCode,0π jmp @@Quitππ@@NoScanCode:π mov al,0π cmp Key,0π je @@Quitππ mov bh,alπ mov bl,Keyπ dec blπ shl bx,1π mov ax,[offset KeyCodes + bx]ππ cmp al,0π jne @@Quitππ mov ScanCode,ahπ@@Quit:π mov key,0πend;ππprocedure GetKeyEvent( var KEvent : KeyEvent); assembler;πasmπ les di,KEventπ mov word ptr es:[di],0π cmp WasKeybEvent,0π je @Quitππ xor bx,bxπ mov bl,keyπ dec bxπ shl bx,1π mov ax,[offset KeyCodes + bx]ππ cmp al,0π je @Storeππ mov ah,keyπ@Store:π mov word ptr es:[di],axπ mov WasKeybEvent,0π mov Key,0π@Quit:πend;ππ{-------------------------------}πprocedure KeybLights(On : boolean; Light : byte);πvar L : byte;πbeginπ if (Light>7) then exit;π asmπ mov al,0EDhπ out 60h,alπ mov cx,2000hπ @loop:π loop @loopπ end;π if On then L := Lights or Lightπ else L := Lights and not Light;π port[$60]:=L;πend;ππ{-------------------------------}πprocedure NullProc;πbeginπend;ππvar OldExitProc : pointer;ππprocedure ExitProcedure; far;πbeginπ DoneKeyboard;π ExitProc:=OldExitProc;πend;ππFUNCTION get_selector(segment : WORD) : WORD;πVAR selector : WORD;πBEGINπ {$IFDEF DPMI}π ASMπ MOV AX, $0002π MOV BX, segmentπ INT $31π JNC @@1π MOV AX, segmentπ@@1:π MOV selector, AXπ END;π {$ELSE}π selector := segment;π {$ENDIF}ππ get_selector := selector;πEND;ππbeginπ SEG0000 := get_selector($0000);π OldExitProc:=ExitProc;π ExitProc:=@ExitProcedure;πend.ππ{ --------------------------- DEMO ------------------------------ }ππprogram KeybDemo;π{ Copyright (c) 1994 by Andrew Eigus Fidonet: 2:5100/33 }ππuses Crt, Keyboard;ππconstπ Status : array[Boolean] of String[11] = ('Not pressed', 'Pressed ');π Lock : array[Boolean] of String[10] = ('Not locked', 'Locked ');ππvarπ key : KeyEvent;π ch : char;π CursorShape : word;ππProcedure SetCursor(CursorOnOff : boolean); assembler;πAsmπ CMP CursorOnOff,Trueπ JNE @@2π CMP BYTE PTR [LastMode],Monoπ JE @@1π MOV CX,0607hπ JMP @@4π@@1:π MOV CX,0B0Chπ JMP @@4π@@2:π CMP BYTE PTR [LastMode],Monoπ JE @@3π MOV CX,2000hπ JMP @@4π@@3:π XOR CX,CXπ@@4:π MOV AH,01hπ XOR BH,BHπ INT 10hπEnd; { SetCursor }ππprocedure AltCtrlDelp; far;πbeginπ Writeln(#13#10#10'That was it. Not bad, eh?');π SetCursor(True);π Halt(1)πend;ππProcedure WriteXY(X, Y : byte; S : string);πBeginπ GotoXY(X, Y);π Write(S)πEnd; { WriteXY }ππFunction Hex(W : Word) : string;πconst hexChars: array [0..$F] of Char = '0123456789ABCDEF';πBeginπ Hex[0] := #4;π Hex[1] := hexChars[Hi(W) shr 4];π Hex[2] := hexChars[Hi(W) and $F];π Hex[3] := hexChars[Lo(W) shr 4];π Hex[4] := hexChars[Lo(W) and $F]πEnd; { Hex }ππBeginπ InitKeyboard;π AltCtrlDelproc:=AltCtrlDelp;π SetCursor(False);π TextAttr := LightGray;π ClrScr;π WriteLn('Keyboard unit demo by Andrew Eigus (c) 1994 Fidonet: 2:5100/33');π WriteLn('Hit any key to scan or Ctrl-Alt-Del to quit.');π repeatπ GetKeyEvent(Key);ππ WriteXY(1, 5, 'Left Shift state : ' + Status[Shift.Left]);π WriteXY(35, 5, 'Right Shift state : ' + Status[Shift.Right]);π WriteXY(1, 6, 'Left Alt state : ' + Status[Alt.Left]);π WriteXY(35, 6, 'Right Alt state : ' + Status[Alt.Right]);π WriteXY(1, 7, 'Left Ctrl state : ' + Status[Ctrl.Left]);π WriteXY(35, 7, 'Right Ctrl state : ' + Status[Ctrl.Right]);π WriteXY(1, 9, 'Scroll Lock state : ' + Status[ScrollLock.Pressed]);π WriteXY(35, 9, 'Scroll Lock toggle : ' + Lock[ScrollLock.Locked]);π WriteXY(1, 10, 'Num Lock state : ' + Status[NumLock.Pressed]);π WriteXY(35, 10, 'Num Lock toggle : ' + Lock[NumLock.Locked]);π WriteXY(1, 11, 'Caps Lock state : ' + Status[CapsLock.Pressed]);π WriteXY(35, 11, 'Caps Lock toggle : ' + Lock[CapsLock.Locked]);π WriteXY(1, 13, 'PrtScr key state : ' + Status[PrtScr]);π if Key.ScanCode and $F0 = $E0 thenπ WriteXY(1, 15, 'Key code : ' + Hex(Key.ScanCode))π elseπ beginπ WriteXY(1, 16, 'Scan code : ' +π Hex(Key.ScanCode and $7F) + ',' + Hex(Key.ScanCode and $7F));π WriteXY(35, 16, 'Key state : ' + Status[Pressed])π end;ππ WriteXY(1, 17, 'Key ASCII code : "' +π Key.CharCode + '",' + Hex(Byte(Key.CharCode)));ππ repeat until WasKeybEventπ until FalseπEnd.ππ 82 08-24-9413:45ALL DAVID DUNSON LiteShow (LED) SWAG9408 ¢c≈ 7 {π ER> Anyway, Does anyone knows who to make the num/caps/scrollπ ER> leds on the keyboard 'flicker' or just light up? (You couldπ ER> create pretty cool effects like a 'walking light' on onesπ ER> keyboard..:) I checked the SWAGfiles but was not able toπ ER> find anything there..π}πProgram LiteShow;πUses Crt;ππVarπ i : Byte;ππProcedure SetLED(LED: Byte); Assembler;πASMπ MOV AL, $EDπ OUT $60, ALπ MOV CX, $200π@@1:π LOOP @@1π MOV AL, LEDπ OUT $60, ALπEnd;ππBeginπ i := 1;π While not KeyPressed doπ Beginπ SetLED(i);π i := i SHL 1;π If i = 8 then i := 1;π Delay(200);π End;π While KeyPressed do ReadKey;πEnd.π 83 08-24-9417:53ALL VARIOUS Set Typo rate and Delay SWAG9408 C½ 12 {π IL> INT 16 - KEYBOARD - SET TYPEMATIC RATE AND DELAYππI wrote a little utility a long time ago, that you might find a bit handy...πI'm sure I have the code around here somewhere (rummage..) Ah here :ππfor the typematic, delay is in increments of 250, and rate is in decrementsπof one...πSean Graham.....π}ππprocedure cursor(t, b: byte); assembler; { Set cursor attribs }πasmπ mov ax, $0100π mov ch, tπ mov cl, bπ int $10πend;ππprocedure v50; assembler; { Go to 50 line mode }πasmπ mov ax,1202hπ mov bl,30hπ int 10hπ mov ax,3π int 10hπ mov ax,1112hπ xor bl, blπ int 10hπend;ππprocedure v25; assembler; { Go to 25 line mode }πasmπ mov ax,$0003π int $10πend;ππprocedure typematic(rate, delay: byte); assembler;πasmπ mov ah, 3π mov al, 5 {Set Typematic Rate And Delay }π mov bh, rate {00h = 30/sec to 1fh = 2/sec }π mov bl, delay {00h = 250ms to 03h = 1000ms }π int $16πend;πππ {Int $16 Function $03; { Set type matic Rate }π {MAYNARD PHILBROOK,Re Keyboard Speed Adjust}ππ Procedure SetTypeRate(Kdelay, Krate:Byte);π Beginπ asmπ Mov AX,$0305; { on a PC jr, AL reg has extra Functions }π Mov BH, Kdelay;π Mov BL, Krate;π Int $16;π End;π End;π 84 08-25-9409:05ALL TIMO SALMI CTRL-BREAK/C disabling SWAG9408 £ < 27 (*π:Could someone please tell me how to disable CTRL-BREAK/C in my program so theπ:user cannot exit without using my "exit" option? The DOS BREAK=OFF justππThe mother of all TP FAQs :-)ππ-From: garbo.uwasa.fi:/pc/ts/tsfaqp20.zip Frequently Asked TP Questionsπ-Subject: Disabling or capturing the break keyππ1. *****π Q: I don't want the Break key to be able to interrupt my TPπprograms. How is this done?π Q2: I want to be able to capture the Break key in my TP program.πHow is this done?π Q3: How do I detect if a certain key has been pressed?ππ A: This very frequently asked question is basically a case of RTFMπ(read the f*ing manual). But this feature is, admittedly, not veryπprominently displayed in the Turbo Pascal reference. (As a generalπrule we should not use the newsgroups as a replacement for ourπpossibly missing manuals, but enough of this line.)π There is a CheckBreak variable in the Crt unit, which is true byπdefault. To turn it off useπ uses Crt;π :π CheckBreak := false;π :πBesides turning off break checking this enables you to capture theπpressing of the break key as you would capture pressing ctrl-c. Inπother words you can use e.g.π :πprocedure TEST;πvar key : char;πbeginπ repeatπ if KeyPressed thenπ beginπ key := ReadKey;π case key ofπ #3 : begin writeln ('Break'); exit; end; {ctrl-c or break}π else write (ord(key), ' ');π end; {case}π end; {if}π until false;πend;π :πIMPORTANT: Don't test the ctrl-break feature just from within the TPπIDE, because it has ctlr-break handler ("intercepter") of its ownπand may confuse you into thinking that ctrl-break cannot beπcircumvented by the method given above.π The above example has a double purpose. It also shows theπrudiments how you can detect if a certain key has been pressed. Thisπenables you to give input without echoing it to the screen, which isπa later FAQ in this collection.π This is, however, not all there can be to break checking, sinceπthe capturing is possible only at input time. It is also possible toπwrite a break handler to interrupt a TP program at any time. Forπmore details see Ohlsen & Stoker, Turbo Pascal Advanced Techniques,πChapter 7. (For the bibliography, see FAQPASB.TXT in this same FAQπcollection).ππ A2: Here is an example code for disabling Ctrl-Break and Ctrl-Cπwith interruptsπ*)π uses Dos;π var OldIntr1B : pointer; { Ctrl-Break address }π OldIntr23 : pointer; { Ctrl-C interrupt handler }π answer : string; { For readln test }π {$F+}π procedure NewIntr1B (flags,cs,ip,ax,bx,cx,dx,si,di,ds,es,bp : word);π Interrupt;π {$F-} begin end;π {$F+}π procedure NewIntr23 (flags,cs,ip,ax,bx,cx,dx,si,di,ds,es,bp : word);π Interrupt;π {$F-} begin end;π beginπ GetIntVec ($1B, OldIntr1B);π SetIntVec ($1B, @NewIntr1B); { Disable Ctrl-Break }π GetIntVec ($23, OldIntr23);π SetIntVec ($23, @NewIntr23); { Disable Ctrl-C }π writeln ('Try breaking, disabled');π readln (answer);π SetIntVec ($1B, OldIntr1B); { Enable Ctrl-Break }π SetIntVec ($23, OldIntr23); { Enable Ctrl-C }π writeln ('Try breaking, enabled');π readln (answer);π writeln ('Done');π end.π 85 08-25-9409:12ALL KEV1N@AOL.COM Stuffing Keyboard SWAG9408 e£ 19 {π> How do I stuff a string into the keyboard buffer?ππI've got two things for you:ππ1: Turbo Power's Object Professional's OpCRT unit has the followingπuseful routines:πprocedure StuffKey(W : Word);π {-Stuff one key into the keyboard buffer}ππprocedure StuffString(S : string);π {-Stuff the contents of S into the keyboard buffer}ππ{π2: If you don't have Object Professional (it's $895.00 but worth it)πBefore I noticed that OpCRT would do what I needed, I sat down andπwrote the following code. It's rough, but gives a pretty good ideaπof how the keyboard buffer works, and there's a chance that you canπuse it to create your own Stufferπ}πprogram ViewKbdBufr;ππ(********************************************************************π***π Written By Kevin R. Pierce - June 25, 1994π*********************************************************************π**)ππUsesπ OpString, {This is where HexB is. You can write your own easyπenough}π CRT;ππvarπ Buffer_Head : Byte absolute $0040:$001A;π Buffer_Tail : Byte absolute $0040:$001C;π Buffer_Start: Byte absolute $0040:$0080;π Buffer_End : Byte absolute $0040:$0082;ππ varπ t : byte;ππbeginπ clrscr;π repeatπ gotoxy(1,1);π writeln('Buffer Head = ',HexB(Buffer_Head));π writeln('Buffer Tail = ',HexB(Buffer_Tail));π writeln('Buffer Start = ',HexB(Buffer_Start));π writeln('Buffer End = ',HexB(Buffer_End));π writeln;π if Buffer_Tail >Buffer_Head then {simple list}π beginπ for t:=Buffer_Head to Buffer_Tail doπ write(Byte(Ptr(Seg0040,t)^):4);π endπ else {loop back to START}π if Buffer_Head<>Buffer_Tail thenπ beginπ for t:=Buffer_Head to Buffer_End doπ write(Byte(Ptr(Seg0040,t)^):4);π for t:=Buffer_Start to Buffer_Tail doπ write(Byte(Ptr(Seg0040,t)^):4);π end;π clreol;π writeln;π writeln(Byte(Ptr(Seg0040,Buffer_Head)^):3);π writeln(Byte(Ptr(Seg0040,Buffer_Tail)^):3);π writeln(Byte(Ptr(Seg0040,Buffer_Start)^):3);π writeln(Byte(Ptr(Seg0040,Buffer_End)^):3);ππ writeln;π for t:=ofs(Buffer_Head) to ofs(Buffer_Tail) doπ write(Byte(Ptr(seg(Buffer_Head),t)^):3);ππ until FALSE;π{endless Loop - Use Ctrl-Break to stop (you might have to reboot ifπyou run BP under Windows.}ππend.π