PAGE 60,132 TITLE SCROLLCK - Use Scroll Lock key on keyboard ;------------------------------------------------------------------------ ; This program intervcepts calls to the VIDEO_IO routines. Commands to ; scroll the screen will be intercepted; all others passed through. This ; routine is attached to DOS. ;------------------------------------------------------------------------ VECTORS SEGMENT AT 0 ORG 10H*4 VIDEO_INT LABEL DWORD ORG 16H*4 KEYBOARD_INT LABEL DWORD VECTORS ENDS ;------------------------------------------------------------------------ ; ROM BIOS data area for keyboard ; ; Contents of KB_FLAG; ;<--- --- --- --- --- --- --- --- --- --- ---> ; ^INS_STATE ^NUM_STATE ^ALT_SHIFT ^LEFT_SHIFT ; ^CAPS_STATE ^SCROLL_STATE ^CTL_SHIFT ^RIGHT_SHIFT ;------------------------------------------------------------------------ ROM_BIOS_DATA SEGMENT AT 40H ORG 17H KB_FLAG DB ? ;Bit 4 set for scroll lock ROM_BIOS_DATA ENDS ;------------------------------- ;Initialize vectors and attach to DOS ;------------------------------- CSEG SEGMENT PARA ASSUME CS:CSEG ORG 100H ;Set starting point for a COM file BEGIN: JMP INIT_VECTORS ;Initialize INT 10H vector and attach to DOS ;------------------------------------------------------------------------ ;These memory locations store the addresses of the ROM routines for video and keybd IO ;------------------------------------------------------------------------ ROM_VIDEO_IO DD ;Address of the ROM routines ROM_KEYBOARD_IO DD SCROLL_COUNT DB 0 ;Number of lines scrolled since last pause LAST_LOCK_STATE DB 0 ;0 if scroll lock off last time checked MAX_LINES DB 23 ;at the top of the screen LAST_LINE DB ;Last line the cursor was on ;------------------------------------------------------------------------ ;This routine intercepts all calls to the VIDEO_IO routine in the ROM. ;Scroll Lock: ; OFF This routine passes control directly to the ROM BIOS ; routine. ; ON Functions other than SCROLL UP or SCROLL DOWN are ; passed directly to the ROM routines. Otherwise, this ; routine increments the scroll count and checks to see ; if it exceeds the page size of 28 lines. If so, loop ; until either shift key pressed. ; left shift allows scroll of whole window ; right shift of one line. ;------------------------------------------------------------------------ INTERCEPT_VIDEO PROC FAR ASSUME CS:CSEG STI ;Turn on interrupts again PUSH DS ;Save registers used PUSH BX PUSH AX ASSUME DS:ROM_BIOS_DATA MOV BX,ROM_BIOS_DATA MOV DS,BX MOV AL,KB_FLAG ;Check state of scroll lock key AND AL,10H ;Pick off scroll lock bit ASSUME DS:CSEG MOV BX,CS ;Data segment for variables (above) MOV DS,BX CMP AL,LAST_LOCK_STATE JE UN_CHANGED ;Scroll lock key hasn't changed MOV BL,MAX_LINES ;Scroll-lock key has changed, set MOV SCROLL_COUNT,BL ;to MAX_LINES to stop scrolling MOV LAST_LOCK_STATE,AL ;Save the new scroll lock state PUSH CX ;Now read current cursor position and PUSH DX ;save in LAST_LINE so SCROLLK won't PUSH AX ;freeze in the middle of a line MOV AH,3 MOV BH,0 PUSHF CALL ROM_VIDEO_IO ;Find old cursor position MOV LAST_LINE,DH ;and save in LAST_LINE POP AX POP DX POP CX UN_CHANGED: XCHG AX,BX ;Recover function (AH) and retain scroll lock POP AX OR BL,BL ;Is scroll lock on? JZ TO_VIDEO_IO ;No, jump to the ROM video_IO routine ;--------------------------------- ;Scroll Lock on ;--------------------------------- CMP AH,2 ;Check for SET CUROR POSITION function JNE NOPE CMP DH,LAST_LINE ;Is the cursor being moved to the next line? MOV LAST_LINE,DH ;Save new cursor line JLE TO_VIDEO_IO ;No, jump to ROM routine JMP SHORT CHECK_LOCK ;Yes, see if we need lock NOPE: CMP AH,6 ;Scroll up? JNE TO_VIDEO_IO ;No, go to ROM routines CHECK_LOCK: INC SCROLL_COUNT ;Take care of scroll lock MOV BH,MAX_LINES CMP SCROLL_COUNT,BH ;Have we scrolled more than MAX_LINES JL TO_VIDEO_IO ;Nope, it's ok to scroll ;Yes, can't scroll until one of shift keys hit MOV BL,BH ;Set SCROLL_COUNT to MAX_LINES-1 DEC BL ;so we can print one more line MOV SCROLL_COUNT,BL ASSUME DS:ROM_BIOS_DATA MOV BX,ROM_BIOS_DATA MOV DS,BX LOOP: MOV BL,KB_FLAG ;Wait until left or right shift key pressed TEST BL,10H ;Is scroll lock still on? JZ TO_VIDEO_IO AND BL,3 ;Pick off shift key info JZ LOOP ;Stay in loop until shift key pushed down CMP BL,1 ;Right shift key hit? JE SCROLL_LINE ;Yes, allow scroll of one line ;No, must be right shift key, so reset scroll count XOR BX,BX MOV SCROLL_COUNT,BL SCROLL_LINE: TO_VIDEO_IO: POP BX ;Restore BX register PUSHF CALL ROM_VIDEO_IO POP DS IRET ;Return INTERCEPT_VIDEO ENDP ;------------------------------------------------------------------------ ;If the keyboard function calls for a read (AH = 0) then reset the scroll count ;------------------------------------------------------------------------ INTERCEPT_KEYBOARD PROC FAR ASSUME CS:CSEG,DS:CSEG STI ;Turn interrupts back on PUSH DS ;Save registers used by this routine PUSH BX MOV BX,CS ;Set up data segment for variables MOV DS,BX OR AH,AH ;Check to see if AH = 0 - read character JNZ KB1 ;Nope, just branch off to keyboard IO XOR BX,BX ;Yes, set scroll count to 0 MOV SCROLL_COUNT,BL KB1: POP BX ;Restore BX register ASSUME DS:NOTHING POP DS JMP ROM_KEYBOARD_IO ;Jump to keyboard routine and return directly ;to the routine that called this routine INTERCEPT_KEYBOARD ENDP ;------------------------------------------------------------------------ ;This section of code saves the old interrupt vectors for the keyboard and video IO routines. ;These vectors are replaced by the addresses of INTERCEPT_VIDEO_ and ;INTERCEPT_KEYBOARD ;------------------------------------------------------------------------ INIT_VECTORS PROC NEAR ASSUME CS:CSEG,DS:CSEG MOV AH,3 ;Set LAST_LINE to cursor line number XOR BH,BH INT 10H MOV LAST_LINE,DH ASSUME CS:CSEG,DS:VECTORS MOV AX,VECTORS MOV DS,AX MOV AX,VIDEO_INT ;Save the address of the ROM routines MOV ROM_VIDEO_IO,AX MOV AX,VIDEO_INT[2] MOV ROM_VIDEO_IO[2],AX MOV AX,OFFSET INTERCEPT_VIDEO ;Set video INT 10H to point to MOV VIDEO_INT,AX ;INTERCEPT_VIDEO above MOV VIDEO_INT[2],CS MOV AX,KEYBOARD_INT ;Save the address of the ROM routines MOV ROM_KEYBOARD_IO,AX MOV AX,KEYBOARD_INT[2] MOV ROM_KEYBOARD_IO[2],AX MOV AX,OFFSET INTERCEPT_KEYBOARD ;Set keyboard INT 16H to point MOV KEYBOARD_INT,AX ;to INTERCEPT_KEYBOARD above MOV KEYBOARD_INT[2],CS MOV DX,OFFSET INIT_VECTORS ;End of resident portion INT 27H ;Terminate but stay resident INIT_VECTORS ENDP CSEG ENDS END BEGIN