home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Professional
/
OS2PRO194.ISO
/
os2
/
sysutils
/
errorlev
/
keywait
/
keywait.os2
< prev
Wrap
Text File
|
1989-09-10
|
6KB
|
257 lines
;-------------------------------------------------------------------------------
;
; keywait.asm
; ===========
;
; Waits a few seconds for a keystroke. If ESC is pressed then sets
; errorlevel to 27. If a function key F1-F10 is pressed then sets
; errorlevel to a value in the range 1-10 corresponding to the function
; key. If time expires or any other key is pressed then errorlevel
; is set to zero. Can be useful in .CMD files.
;
; A public domain program by Jon Saxton. Please distribute source
; code and not just the object code.
;
;-------------------------------------------------------------------------------
include os2.inc
COLON equ ':'
CR equ 0Dh
LF equ 0Ah
ETX equ 03h
ESCk equ 1Bh
SPACE equ ' '
TAB equ 9
F1 equ 59
F10 equ 68
THREAD_STACK_SIZE equ 512
THREAD_STACK_OFFSET equ THREAD_STACK_SIZE-2
.model small
.data
keyData KBDKEYINFO <>
ticks dw 10 ;Default number of seconds
stkPtr dd ?
org stkPtr
stkOff dw ?
stkSeg dw ?
tid dw ?
kid dw ?
keyboardInput dd ? ; Keyboard input semaphore
timeExpired dd ? ; Timer semaphore
semaphoreList dw 2 ; Number of elements
dw 0
dw offset keyboardInput
dw seg keyboardInput
dw 0
dw offset timeExpired
dw seg timeExpired
key dw 0
blankRet db CR
blanks db ' '
timerHandle dd ?
timerSemHandle dd ?
timerSemName db '\SEM\TICKER',0
eventNumber dw -1
kiMessage db 'Key pressed: exit code '
toMessage db 'Timed out: exit code '
msgLen equ $-toMessage
pointers dw kiMessage,toMessage
.code
.286C
start:
mov es,ax ; Point at environment segment
mov di,bx ; Point at command name
xor ax,ax
repne scasb ; Skip to end of command name
mov cx,0
skipLeadingBlanks:
mov al,es:[di] ; Get command-line character
inc di ; Point at the next one
or al,al ; Check if anything there
jz setTicks
cmp al,SPACE ; Skip leading white space
je skipLeadingBlanks
cmp al,TAB
je skipLeadingBlanks
convertNumber:
xor ah,ah
cmp al,'0'
jb setTicks
cmp al,'9'
ja setTicks
sub al,'0'
add cx,cx ;*2
mov dx,cx
add cx,cx ;*4
add cx,cx ;*8
add cx,dx ;*10
add cx,ax
mov al,es:[di]
inc di
jmp convertNumber
setTicks:
mov ax,cx
or ax,ax
jz default
cmp ax,100
ja default
mov ticks,ax
default:
; At this point we have analysed the command line and interpreted a single
; number as the number of seconds to wait for a keystroke. If the number
; of seconds was not specified or is unreasonably large then it has been
; forced to a value of 10.
;
; The next step is to initiate the timer and keyboard threads. This is
; real OS/2 stuff.
@DosSemSet keyboardInput ; Set the semaphores which are going
@DosSemSet timeExpired ; to be used by the two threads
@DosAllocSeg THREAD_STACK_SIZE,stkSeg,0 ; Get a stack
or ax,ax ; Check that it worked
jz first
jmp error100
first:
mov ax,THREAD_STACK_OFFSET ; Create the timer thread
mov stkOff,ax
@DosCreateThread ticker,tid,[stkPtr]
@DosAllocSeg THREAD_STACK_SIZE,stkSeg,0 ; Get a stack
or ax,ax ; Check that it worked
jz second
jmp error100
second:
@DosCreateThread keyin,kid,[stkPtr] ; Create the keyin thread
; Now wait for one of the two threads to signal an event
@DosMuxSemWait eventNumber,semaphoreList,-1
mov bx,eventNumber
add bx,bx
mov ax,pointers[bx]
push ds
push ax
push msgLen
push 0
call far ptr VioWrtTTy
mov si,offset blanks
mov ax,' '
mov [si],ax
mov ax,key
call decimal
@VioWrtTTy blanks,3,0
@DosExit 1,[key]
error100:
@DosExit 1,100
;-----------------------------------------------------------------------------
;
; Keyboard input handler. Waits for a keystroke and returns a value
; in the range 1-10 if a function key was pressed, 27 if the ESC key
; was pressed, 0 if anything else was pressed.
;
;-----------------------------------------------------------------------------
keyin proc
@KbdCharIn keyData,0,0 ; Get character
mov al,keyData.kbci_chChar
or al,al ; Extended key code?
jnz simple ; No, check for ESC etc
mov al,keyData.kbci_chScan ; Fetch second byte
cmp al,F1 ; Check for F1 - F10
jb sig0
cmp al,F10
ja sig0
sub al,F1-1
jmp sig
simple:
cmp al,ESCk ; ESC causes return value
jz sig ; to be set to 27
sig0:
xor al,al
sig:
mov byte ptr key,al
@DosSemClear keyboardInput
@DosExit 0,0
keyin endp
;------------------------------------------------------------------------------
;
; Countdown timer. Displays the number of ticks remaining. Stops
; at zero.
;
;------------------------------------------------------------------------------
ticker proc
@DosCreateSem 1,timerSemHandle,timerSemName
@DosSemSet [timerSemHandle]
@DosTimerStart 1000,[timerSemHandle],timerHandle
tick:
@DosSemWait [timerSemHandle],-1
@DosSemSet [timerSemHandle]
mov si,offset blankRet+1
mov ax,' '
mov word ptr [si],ax
mov ax,ticks
dec ax
mov ticks,ax
pushf
call decimal ; seconds remaining
@VioWrtTTY blankRet,4,0
popf
jnz tick
@DosSemClear timeExpired
; @DosTimerStop [timerHandle]
@DosExit 0,0
ticker endp
;-----------------------------------------------------------------------------
;
; DECIMAL
;
; Converts an unsigned decimal number from AX into ASCII in the
; buffer addressed by SI.
;
; Destroys contents of AX, CX, DX
;
;-----------------------------------------------------------------------------
decimal proc
xor dx,dx ; Clear high-order 16 bits of dividend
mov cx,10 ; Load divisor
div cx ; Quotient to AX, remainder to DX
or ax,ax ; Test quotient
jz remain ; If zero then just display the remainder
push dx ; Otherwise save the remainder while we
call decimal ; deal with the quotient
pop dx ; Recover the remainder
remain:
add dl,'0' ; Convert remainder to a decimal digit
mov [si],dl
inc si
ret
decimal endp
.stack 160
end start