TITLE SCROLLK.COM -- DOS RESIDENT SCROLL LOCK CONTROL PAGE 60,132 COMMENT* This program provides scrolling control of the video display with the Scroll Lock key. Assemble, Link, and convert the EXE file to a COM program. Run the program once on system boot-up then the Scroll Lock key can be used to toggle scrolling on and off. If scroll lock is ON, the screen will pause after 23 continuous lines are displayed. Press the Left shift key to scroll another 23 lines or the Right shift key to scroll one line; or press Scroll Lock again to turn OFF the lock and the screen will scroll uninterrupted.* ;----------------------------------------------------------------------------; ;This program intercepts calls to the VIDEO_IO routines. Commands to scroll ;the screen will be intercepted; all others passed through. This routine is ;attached to DOS. ; ;Program by John Socha, 'Softalk', May 1983, pp. 38-49 ; ;keyed in by Lee M Buck, Arlington VA ; ;----------------------------------------------------------------------------; ;----------------------------------------------------------------------------; ;Interrupt vectors for video and keyboard routines ;----------------------------------------------------------------------------; 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 - bits 7 to 0 ;<--- --- --- --- --- --- --- ---> ; ^INS_STATE ^NUM_STATE ^ALT_SHIFT ^LEFT_SHIFT ; ^CAPS_STATE ^SCROLL_STATE ^CTL_STATE ^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 COM file BEGIN: JMP INIT_VECTORS ;Initialize INT 10H and attach to DOS ;----------------------------------------------------------------------------; ;These memory locations store the addresses of the ROM routines for video and ;keyboard I/O routines ;----------------------------------------------------------------------------; ROM_VIDEO_IO DD ;Address of the ROM routines ROM_KEYBOARD_IO DD SCROLL_COUNT DB 0 ;Lines scrolled since last pause LAST_LOCK_STATE DB 0 ;0 if scrl lock off last time checked MAX_LINES DB 23 ;Scroll by 23 lines, leaving one old ;line at top before pausing LAST_LINE DB ;Last line cursor was on ;----------------------------------------------------------------------------; ;This routine intercepts all calls to the VIDEO_IO routine in 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 23 lines (MAX_LINES). ; If so, loop until either shift key pressed. ; Left shift allows scroll of whole window ; Right shift scrolls 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 ;Isolate 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 to MOV SCROLL_COUNT,BL ;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 ;This is a pseudo INT 10H call to BIOS MOV LAST_LINE,DH ;to find old cursor position and save POP AX ;in LAST_LINE. (see Tech. Ref. A-43) 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 CURSOR 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 need to 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, wait until a shift key is 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 for left or right shift key push 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 pressed CMP BL,1 ;Right shift key pressed? JE SCROLL_LINE ;Yes, allow scroll of one line ;No, must be left 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 ;Perform a pseudo INT 10H call to BIOS POP DS IRET ;interrupt Return INTERCEPT_VIDEO ENDP ;----------------------------------------------------------------------------; ;This routine intercepts all calls to KEYBOARD_IO ;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 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 JNZ KB1 ;Nope, branch to keyboard I/O 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 one INTERCEPT_KEYBOARD ENDP ;----------------------------------------------------------------------------; ;This section of code saves the old interrupt vectors for the keyboard and ;video I/O routines. These vectors are replaced by the addresses of ;INTERCEPT_VIDEO and INTERCEPT_KEYBOARD PROCS above. ;----------------------------------------------------------------------------; 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 ROM routine address 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 PROC above. MOV VIDEO_INT[2],CS MOV AX,KEYBOARD_INT ;Save the ROM routine address 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 PROC 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