home *** CD-ROM | disk | FTP | other *** search
- ;
- ; KEYSTRIN.ASM
- ;
- ; A DYNLINK LIBRARY KBD REPLACEMENT SUBSYSTEM ALLOWING COMMAND RECALL,
- ; LINE EDITING, AND ALIAS REPLACEMENT.
- ;
-
- TITLE KEYSTRIN
-
- .286P
-
- EXTRN DOSDEVIOCTL:FAR, DOSOPEN:FAR, DOSCLOSE:FAR, DOSBEEP:FAR
- EXTRN DOSWRITE:FAR, DOSGETINFOSEG:FAR, KBDGETSTATUS:FAR
- EXTRN VIOWRTTTY:FAR, VIOGETCURPOS:FAR, VIOSETCURPOS:FAR
- EXTRN VIOGETCURTYPE:FAR, VIOSETCURTYPE:FAR, VIOWRTNCHAR:FAR
- EXTRN VIOWRTCHARSTR:FAR
-
- ;
- LBUFF SEGMENT WORD PUBLIC 'KBUFFER'
-
- KEYLEN EQU 2048
- SYNLEN EQU 2048
-
- KEYBUFF DB KEYLEN DUP(0) ; BUFFER FOR COMMAND RECALL
- KEYTAIL DW 0 ; POINTER TO END OF BUFFER
- CURRPTR DW 0 ; POINTER TO CURRENT COMMAND
- FUNCBUFF DB 256 DUP(0) ; BUFFER FOR FUNCTION KEY RECALL
- FUNCPTR DW 0 ; POINTER TO CHAR IN FUNCBUFF
- FUNCMAX DW 0 ; END OF FUNCBUFF
- WORKBUFF DB 256 DUP(0) ; WORK BUFFER
- WORKPTR DW 0 ; POINTER TO WORKBUFF
- WORKTAIL DW 0 ; POINTER TO END OF WORKBUFF
- WORKMAX DW 0 ; MAX SIZE FOR WORKBUFF
- XMITBUFF DB 256 DUP(0) ; BUFFER FOR RETURN FROM CALL
- EDIT_FLAG DW 0 ; ALLOW COMMAND EDITING
- CHANGE_FLAG DW 0 ; FLAG FOR LINE CHANGE
- INIT_CUR_ROW DW 0 ; INITIAL CURSOR ROW
- INIT_CUR_COL DW 0 ; INITIAL CURSOR COLUMN
- CURR_CUR_ROW DW 0 ; CURRENT CURSOR ROW
- CURR_CUR_COL DW 0 ; CURRENT CURSOR COLUMN
- LAST_LENGTH DW 0 ; LENGTH OF LAST DISPLAYED COMMAND
- THIS_LENGTH DW 0 ; LENGTH OF THIS COMMAND
- INSERT_STATE DW 0 ; STATE OF INSERT
- KEYDEVBUF DB 20 DUP(?) ; BUFFER FOR KEYBOARD REQUEST
- KEYDEVPRM DW 1 ; PARAMETER FOR KEYBOARD CALL
- KEYNAME DB 'KBD$',0 ; NAME OF KEYBOARD
- KEYACT DW ? ; KEYBOARD ACTION
- KEYHAND DW 0 ; KEYBOARD HANDLE
- BLANK DB ' ' ; BLANK (SPACE) CHARACTER
- O_CUR_SLINE DW 0 ; OLD CURSOR START LINE
- O_CUR_ELINE DW 0 ; OLD CURSOR END LINE
- O_CUR_WIDTH DW 0 ; OLD CURSOR WIDTH
- O_CUR_ATTR DW 0 ; OLD CURSOR ATTRIBUTE
- CUR_SLINE DW 0 ; CURSOR START LINE
- CUR_ELINE DW 0 ; CURSOR END LINE
- CUR_WIDTH DW 0 ; CURSOR WIDTH
- CUR_ATTR DW 0 ; CURSOR ATTRIBUTE
- KBD_STATE EQU $
- KBD_ST_SIZE DW 0 ; SIZE OF KBD STATE
- KBD_ST_MASK DW 0 ; KBD STATE MASK
- KBD_ST_TAC DW 0 ; KBD TURNAROUND CHARACTER
- KBD_ST_INTFL DW 0 ; KBD INT FL
- KBD_ST_SHIFT DW 0 ; KBD SHIFT STATE
-
- SPECTABL DW DO_F1 ; 0X3B
- DW DO_F2 ; 0X3C
- DW DO_F3 ; 0X3D
- DW KEYLOOP ; 0X3E
- DW KEYLOOP ; 0X3F
- DW KEYLOOP ; 0X40
- DW KEYLOOP ; 0X41
- DW KEYLOOP ; 0X42
- DW KEYLOOP ; 0X43
- DW KEYLOOP ; 0X44
- DW KEYLOOP ; 0X45
- DW KEYLOOP ; 0X46
- SPECTABL1 DW DO_HOME ; 0X47
- DW DO_UP ; 0X48
- DW KEYLOOP ; 0X49
- DW KEYLOOP ; 0X4A
- DW DO_LEFT ; 0X4B
- DW KEYLOOP ; 0X4C
- DW DO_RIGHT ; 0X4D
- DW KEYLOOP ; 0X4E
- DW DO_END ; 0X4F
- DW DO_DOWN ; 0X50
- DW KEYLOOP ; 0X51
- DW DO_INS ; 0X52
- DW DO_DEL ; 0X53
-
- LBUFF ENDS
-
- SBUFF SEGMENT WORD PUBLIC 'SYN'
- SYNBUFF DB SYNLEN DUP(0) ; ALIAS BUFFER
- SYNHEAD DW 0 ; BUFFER HEAD
- SYNTAIL DW 0 ; BUFFER TAIL
- PRINT_LINE DB 256 DUP(0) ; BUFFER FOR PRINT LINE
- WRITTEN DW 0
- SBUFF ENDS
- ;
-
- ASSUME CS:KEYREP, DS:LBUFF, ES:SBUFF
- KEYREP SEGMENT BYTE PUBLIC 'CODE'
- ;
- START PROC FAR ; INITIALIZATION ROUTINE FOR DLL
- PUSH DS
- MOV AX,SEG LBUFF
- MOV DS,AX ; SET UP DATA SEGMENT
-
- PUSH DS
- PUSH OFFSET KEYNAME ; FAR PTR TO NAME
- PUSH DS
- PUSH OFFSET KEYHAND ; FAR PTR TO HANDLE
- PUSH DS
- PUSH OFFSET KEYACT ; FAR PTR TO ACTION
- PUSH 0
- PUSH 0 ; LONG SIZE
- PUSH 0 ; NORMAL FILE
- PUSH 1 ; OPEN FLAG
- PUSH 1C0H ; OPEN MODE
- PUSH 0
- PUSH 0
- CALL DOSOPEN ; OPEN KEYBOARD
- CMP AX,0
- JNE BADOPEN
- MOV LAST_LENGTH,0
- MOV THIS_LENGTH,0
- POP DS
- MOV AX,1 ; SHOW SUCCESS
- RET
- BADOPEN:
- POP DS
- MOV AX,0 ; SHOW FAILURE
- RET
- START ENDP
-
- ;
- ; KEYSTRIN IS THE ACTUAL REPLACEMENT FUNCTION FOR THE KBDSTRINGIN
- ; SUBFUNCTION.
- ;
-
- PUBLIC KEYSTRIN
- KEYSTRIN PROC FAR
- PUSH BP
- MOV BP,SP
- ; ON ENTRY STACK LOOKS LIKE:
- ; [BP+0] - BP
- ; [BP+2] - OS2 FAR RETURN ADDR
- ; [BP+6] - CALLER'S DS
- ; [BP+8] - NEAR ENTRY POINT
- ; [BP+10] - FUNCTION NUMBER
- ; [BP+12] - FAR RETURN TO CALLER
- ; [BP+16] - KBDHANDLE
- ; [BP+18] - IOWAIT
- ; [BP+20] - LENGTH
- ; [BP+24] - POINTER TO CHAR BUFFER
- ;
-
- CMP WORD PTR [BP+10],05
- JE OURFUNC ; MAKE SURE THIS IS OUR FUNCTION
- JMP NOT_OURS
- ;
- OURFUNC:
- PUSH DI
- PUSH SI
- PUSH DS
- PUSH ES
- PUSH AX
- PUSH BX
- PUSH CX
- PUSH DX
- PUSHF
- MOV AX,SEG LBUFF ; SET UP DATA SEGMENT
- MOV DS,AX
-
- CMP WORD PTR [BP+18],0 ; IS THIS A WAIT CALL
- JE CHK_STATE ; YES, WE CAN HANDLE IT
- JMP NOT_OURS ; NO, PASS IT BACK ON TO KBD SYSTEM
- ;
- CHK_STATE:
- PUSH DS
- PUSH OFFSET KBD_STATE ; FAR PTR TO KBDSTATE
- PUSH 0
- CALL KBDGETSTATUS ; GET KBD STATE
- MOV AX,KBD_ST_MASK
- AND AX,100B ; WE ONLY HANDLE COOKED MODE
- CMP AX,0
- JE DO_FUNC
- JMP NOT_OURS ; LET SOMEONE ELSE DO THIS
- ;
- DO_FUNC: ; FINALLY WE CAN START
- MOV CHANGE_FLAG,0 ; MARK UNCHANGED
- PUSH DS
- PUSH OFFSET O_CUR_SLINE ; FAR PTR TO CURSOR TYPE
- PUSH 0
- CALL VIOGETCURTYPE ; GET CURSOR TYPE
- ;
- MOV AX,[BP+22] ; SEGMENT OF INPUT BUFFER LENGTH
- MOV ES,AX
- MOV BX,[BP+20] ; OFFSET OF INPUT BUFFER LENGTH
- MOV AX,ES:[BX] ; INPUT BUFFER LENGTH
- MOV WORKMAX,AX
- MOV AX,ES:[BX+2] ; EDITING FLAG
- MOV EDIT_FLAG,AX
- ;
- GET_CUR:
- PUSH DS
- PUSH OFFSET INIT_CUR_ROW ; FAR PTR TO CURSOR ROW
- PUSH DS
- PUSH OFFSET INIT_CUR_COL ; FAR PTR TO CURSOR COLUMN
- PUSH 0
- CALL VIOGETCURPOS ; GET INITIAL CURSOR POSITION
- ;
- MOV AX,INIT_CUR_ROW
- MOV CURR_CUR_ROW,AX
- MOV AX,INIT_CUR_COL
- MOV CURR_CUR_COL,AX
- XOR AX,AX
- MOV WORKPTR,AX
- INC AX
- MOV WORKTAIL,AX
-
- PUSH DS
- POP ES ; MAKE SEGMENTS THE SAME
- CLD ; SET DIRECTION JUST TO BE SAFE
- ;
- KEYLOOP: ; MAJOR WAIT FOR KEY LOOP
- CALL GETKEY
- CMP AX,0
- JE FUNC_OK
- JMP BAD_FUNC
- ;
- FUNC_OK:
- MOV SI,OFFSET KEYDEVBUF
- LODSW ; SCAN_CODE AND CHAR_CODE
- CMP AL,0 ; SPECIAL KEY?
- JNE AT_KEY
- JMP SPEC_KEY
- ;
- AT_KEY: CMP AL,0E0H ; 101 KEY SPECIAL KEY?
- JNE NORM_KEY ; NO
- JMP SPEC_KEY
- ;
- NORM_KEY:
- CMP AL,0DH ; THIS REALLY SHOULD BE TAC
- JNE IS_ESC
- JMP DO_CR
-
- IS_ESC: CMP AL,1BH
- JNE IS_BS
- JMP DO_ESC
-
- IS_BS: MOV CHANGE_FLAG,1 ; SHOW LINE HAS CHANGED
- CMP AL,08H
- JNE ASC_KEY
- JMP DO_BS
- ;
- ; AT ASK_KEY WE HAVE A NORMAL CHARACTER, CHECK INSERT MODE AND
- ; DO KEY HANDLING
- ;
- ASC_KEY:
- MOV CX,WORKTAIL
- CMP CX,WORKMAX ; DO WE HAVE MAX CHARACTERS?
- JNE ASC_KEY1 ; NO
- JMP TOO_MANY ; YES
- ;
- ASC_KEY1:
- CMP INSERT_STATE,0
- JE OVERWRITE
- JMP INSERT
-
- OVERWRITE:
- MOV DI,WORKPTR ; CURR CHARACTER
- ADD DI,OFFSET WORKBUFF
- STOSB ; SAVE CHARACTER
- SUB DI,OFFSET WORKBUFF
- MOV AX,1 ; UPDATE CURSOR BY 1 POSITION
- CALL DISPTAIL ; DISPLAY
- MOV WORKPTR,DI ; SAVE WORKPTR
- MOV FUNCPTR,DI ; SAVE FOR FUNCTION KEY RECALL
- CMP WORKTAIL,DI ; ARE WE INSIDE LINE OR AT END?
- JNE O1 ; INSIDE LINE, DO NOT EXTEND BUFFER
-
- INC WORKTAIL ; INC LINE LENGTH
- INC THIS_LENGTH
- MOV AX,THIS_LENGTH
- CMP AX,LAST_LENGTH
- JLE O1
- INC LAST_LENGTH
- ;
- O1: JMP KEYLOOP ; AND LOOP
- ;
- INSERT:
- PUSH AX ; SAVE CHARACTER
- MOV DI,WORKTAIL ; GET END OF BUFFER
- DEC DI ; LESS ONE
- MOV SI,DI ; TO SOURCE REGISTER
- DEC SI ; LESS ONE
- MOV CX,DI
- SUB CX,WORKPTR ; COUNT OF CHARACTERS TO MOVE
- ADD DI,OFFSET WORKBUFF
- ADD SI,OFFSET WORKBUFF
- PUSHF ; SAVE FLAGS (WE NEED TO CHANGE DIR)
- STD
- REP MOVSB ; MOVE CHARACTERS
- POPF ; RESTORE FLAGS (DIRECTION)
- MOV DI,WORKPTR ; GET CHAR PTR
- POP AX ; RESTORE CHARACTER
- ADD DI,OFFSET WORKBUFF
- STOSB ; STASH CHARACTER IN BUFFER
- MOV AX,1 ; UPDATE CURSOR BY 1 POSITION
- CALL DISPTAIL ; DO DISPLAY
- INC WORKPTR
- INC WORKTAIL ; EXTEND LINE LENGTH
- JMP KEYLOOP
- ;
- ; AT DO_ESC WE HAVE READ AN ESCAPE KEY, CLEAR THE INPUT LINE AND
- ; RESTORE CURSOR TO ORIGINAL POSITION.
- ;
- DO_ESC:
- PUSH DS
- PUSH OFFSET BLANK ; FAR PTR TO BLANK CHARACTER
- MOV AX,WORKTAIL
- DEC AX
- ADD AX,OFFSET WORKBUFF
- PUSH AX ; NUMBER OF CHARACTERS TO WRITE
- MOV AX,INIT_CUR_ROW
- PUSH AX
- MOV AX,INIT_CUR_COL
- PUSH AX
- PUSH 0
- CALL VIOWRTNCHAR ; WRITE N CHARACTERS
- MOV AX,INIT_CUR_ROW
- MOV CURR_CUR_ROW,AX ; RESET CURSOR POSITION
- PUSH AX
- MOV AX,INIT_CUR_COL
- MOV CURR_CUR_COL,AX
- PUSH AX
- PUSH 0
- CALL VIOSETCURPOS
- XOR AX,AX
- MOV WORKPTR,AX
- MOV FUNCPTR,AX
- INC AX
- MOV WORKTAIL,AX
- PUSH DS
- PUSH OFFSET O_CUR_SLINE ; FAR PTR TO CURSOR TYPE
- XOR AX,AX
- MOV INSERT_STATE,AX ; CLEAR INSERT MODE
- PUSH AX
- CALL VIOSETCURTYPE
- MOV THIS_LENGTH,0
- MOV CHANGE_FLAG,0
- MOV FUNCPTR,0
- JMP KEYLOOP
- ;
- ; AT DO_BS WE HANDLE A BACKSPACE CHARACTER
- ;
- DO_BS:
- MOV AX,WORKPTR
- CMP AX,0
- JNE BS1
- JMP KEYLOOP ; AT START OF LINE
- ;
- BS1:
- MOV CX,WORKTAIL
- DEC CX
- CMP CX,AX ; AT END OF LINE?
- JE BS2 ; YES, EASY CASE
- JMP BS3 ; NO, HARDER CASE
- ;
- BS2:
- DEC AX ; BACKUP WORKPTR
- MOV WORKPTR,AX
- MOV FUNCPTR,AX
- DEC WORKTAIL
- MOV DI,AX
- ADD DI,OFFSET WORKBUFF
- MOV AL,' '
- STOSB ; BLANK CHARACTER
- MOV AX,CURR_CUR_COL
- DEC AX
- CMP AX,-1 ; DID WE WRAP A LINE?
- JNE BS2A ; NO
- DEC CURR_CUR_ROW ; YES
- MOV AX,79
- BS2A:
- MOV CURR_CUR_COL,AX
- PUSH CURR_CUR_ROW
- PUSH CURR_CUR_COL
- PUSH 0
- CALL VIOSETCURPOS
- MOV AX,0 ; DO NOT UPDATE CURSOR POSITION
- CALL DISPTAIL
- DEC THIS_LENGTH
- JMP KEYLOOP
- ;
- BS3:
- DEC AX
- MOV WORKPTR,AX
- MOV FUNCPTR,AX
- MOV DI,AX ; DEST = WORKPTR
- INC AX
- MOV SI,AX ; SOURCE = WORKPTR + 1
- ADD DI,OFFSET WORKBUFF
- ADD SI,OFFSET WORKBUFF
- MOV CX,WORKTAIL
- DEC CX
- SUB CX,WORKPTR ; NUMBER OF CHARACTERS TO MOVE
- REP MOVSB
-
- DEC WORKTAIL
- MOV BX,WORKTAIL
- DEC BX
- MOV AL,' '
- MOV WORKBUFF[BX],AL
- MOV AX,CURR_CUR_COL
- DEC AX
- CMP AX,-1
- JNE BS3A
- DEC CURR_CUR_ROW
- MOV AX,79
- ;
- BS3A:
- MOV CURR_CUR_COL,AX
- PUSH CURR_CUR_ROW
- PUSH CURR_CUR_COL
- PUSH 0
- CALL VIOSETCURPOS
- MOV AX,0 ; DON'T UPDATE CURSOR POSITION
- CALL DISPTAIL
- JMP KEYLOOP
- ;
- ; AT DO_CR WE HAVE READ A FULL LINE. CLEAR UP OUT DATA AND PASS THE
- ; STRING BACK TO THE CALLING PROGRAM. MAKE CURRPTR POINT TO THE
- ; END OF THIS STRING (FOR RECALL).
- ;
- DO_CR:
- CMP CHANGE_FLAG,0
- JNE DO_CR1 ; LINE HAS CHANGED, SAVE FOR RECALL
- JMP SEND_BUFF
- ;
- DO_CR1:
- MOV AX,WORKTAIL
- CMP AX,4
- JGE IS_FIRST
- JMP SEND_BUFF1 ; DON'T SAVE LINES OF < 3 CHARS
- ;
- IS_FIRST:
- MOV DI,KEYTAIL
- INC DI
- AND DI,KEYLEN-1 ; DEST = END OF KEYBUFF
- MOV SI,OFFSET WORKBUFF
- MOV CX,WORKTAIL
- DEC CX ; NUMBER OF CHARS TO STORE
- ;
- MOVE_LOOP:
- PUSH DI
- ADD DI,OFFSET KEYBUFF
- MOVSB
- POP DI
- INC DI
- AND DI,KEYLEN-1 ; HANDLE BUFFER WRAP
- LOOP MOVE_LOOP
- ;
- ADD DI,OFFSET KEYBUFF
- MOV AL,0
- STOSB ; MAKE ASCIIZ
- SUB DI,OFFSET KEYBUFF
- MOV KEYTAIL,DI
- MOV CURRPTR,DI ; FOR COMMAND RECALL
- JMP SEND_BUFF1
- ;
- SEND_BUFF:
- MOV SI,CURRPTR
- ADD SI,OFFSET KEYBUFF
- SEND_BUFF0:
- LODSB
- CMP AL,0
- JNE SEND_BUFF0
- SUB SI,OFFSET KEYBUFF
- MOV CURRPTR,SI
- SEND_BUFF1:
- MOV AL,0DH
- MOV DI,WORKTAIL
- DEC DI
- MOV LAST_LENGTH,DI ; LENGTH OF LAST LINE
- ADD DI,OFFSET WORKBUFF
- STOSB ; STORE CR
- MOV AX,WORKTAIL
- ADD AX,INIT_CUR_COL
- CMP AX,80
- JL SEND_BUFF2
- SUB AX,80
- INC CURR_CUR_ROW
- SEND_BUFF2:
- MOV CURR_CUR_COL,AX
- PUSH CURR_CUR_ROW
- PUSH CURR_CUR_COL
- PUSH 0
- CALL VIOSETCURPOS
- MOV AX,DI
- DEC AX
- SUB DI,OFFSET WORKBUFF
- PUSH DS
- PUSH AX ; FAR PTR TO CR
- PUSH 1 ; NUMBER OF CHARACTERS TO WRITE
- XOR AX,AX
- MOV THIS_LENGTH,AX ; NEW LINE LENGTH
- PUSH AX ; REQUIRED ZERO
- CALL VIOWRTTTY ; DISPLAY CR
- PUSH ES
- CALL ALIAS ; CHECK FOR ALIAS SUBSTITUTION
- MOV SI,OFFSET WORKBUFF
- CMP AX,1
- JE SEND_BUFF3 ; NO SUBSTITUTION
- MOV SI,OFFSET XMITBUFF ; SUBSTITUTION MADE USE XMITBUFF
- SEND_BUFF3:
- MOV AX,WORD PTR [BP+26] ; SEGMENT OF RECEIVING BUFFER
- MOV ES,AX
- MOV DI,WORD PTR [BP+24] ; OFFSET OF RECEIVING BUFFER
- MOV CX,0 ; CLEAR COUNT
- SEND_BUFF4:
- LODSB ; GET CHAR
- CMP AL,0DH ; LAST CHAR?
- JE SEND_BUFF5
- STOSB ; SEND CHAR
- INC CX
- JMP SEND_BUFF4
- SEND_BUFF5:
- STOSB ; SEND CR
- MOV AX,[BP+22] ; SEGMENT OF RETURNED BUFFER LENGTH
- MOV ES,AX
- MOV BX,[BP+20] ; OFFSET OF RETURNED BUFFER LENGTH
- MOV ES:[BX+2],CX ; LENGTH (LESS CR)
- POP ES
- JMP KEYDONE ; DO CLEANUP
- ;
- ; AT SPEC_KEY WE HAVE READ A SPECIAL KEY
- ;
- SPEC_KEY:
- MOV AL,AH
- XOR AH,AH
- CMP AX,3BH
- JGE IN_TAB1
- JMP KEYLOOP ; UNUSED KEY
- ;
- IN_TAB1:
- CMP AX,47H
- JGE IN_TAB2
- JMP DO_TAB1 ; KEY IN TABLE 1
- ;
- IN_TAB2:
- CMP AX,54H
- JGE IS_CLFT
- JMP DO_TAB2 ; KEY IN TABLE 2
- IS_CLFT:
- CMP AX,73H
- JNE IS_CRT
- JMP DO_CLFT
- IS_CRT:
- CMP AX,74H
- JNE IS_CPUP
- JMP DO_CRT
- IS_CPUP:
- CMP AX,84H
- JNE IS_CPDN
- JMP DO_CPUP
- IS_CPDN:
- CMP AX,76H
- JNE NOT_IMP
- JMP DO_CPDN
- ;
- NOT_IMP:
- JMP KEYLOOP ; NOT AN ASSIGNED KEY
- ;
- DO_TAB1:
- SUB AX,3BH ; MAKE OFFSET INTO TABLE
- SHL AX,1 ; FOR WORD POINTERS
- MOV BX,AX
- MOV AX,SPECTABL[BX]
- JMP AX ; DISPATCH
- ;
- DO_TAB2:
- SUB AX,47H ; OFFSET INTO TABLE
- SHL AX,1
- MOV BX,AX
- MOV AX,SPECTABL1[BX]
- JMP AX ; DISPATCH
- ;
- ;
- ; DO_CLFT - MOVE ONE WORD LEFT
- ;
- DO_CLFT: ; MOVE ONE WORD CHARACTER LEFT
- MOV DL,' '
- MOV DH,'\'
- MOV AX,WORKPTR
- CMP AX,0
- JNE CLEFT1
- JMP KEYLOOP ; AT LEFT BORDER
- CLEFT1: ADD AX,OFFSET WORKBUFF
- MOV BX,AX
- ;
- CLEFT2: DEC BX ; LOOP TO FIND NON-DELIMITER
- CMP BX,OFFSET WORKBUFF ; AT BEGINNING OF LINE
- JE CLEFT6 ; YES
- CMP [BX],DL ; IS THIS A SPACE
- JE CLEFT2 ; YES LOOP
- CMP [BX],DH ; IS THIS A '\'
- JE CLEFT2
- ;
- CLEFT3: DEC BX ; FOUND A NON-DELIMITER NOW FIND THE
- CMP BX,OFFSET WORKBUFF ; NEXT DELIMITER
- JE CLEFT6 ; AT BEGINNING OF LINE
- CMP [BX],DL ; SPACE
- JE CLEFT4
- CMP [BX],DH ; '\'
- JNE CLEFT3
- ;
- CLEFT4: INC BX
- SUB BX,OFFSET WORKBUFF
- MOV CX,WORKPTR
- SUB CX,BX ; HOW FAR WE HAVE MOVED
- MOV WORKPTR,BX
- MOV FUNCPTR,BX
- MOV AX,CURR_CUR_COL
- SUB AX,CX ; PAST BEGINNING OF LINE
- CMP AX,0
- JGE CLEFT5
- ADD AX,80 ; TRICK COLUMN NUMBER
- MOV CURR_CUR_COL,AX
- MOV AX,CURR_CUR_ROW
- DEC AX ; ADJUST ROW
- MOV CURR_CUR_ROW,AX
- JMP CLEFT7
- ;
- CLEFT5: MOV CURR_CUR_COL,AX
- JMP CLEFT7
- ;
- CLEFT6: MOV BX,0
- MOV WORKPTR,BX
- MOV FUNCPTR,BX
- MOV AX,INIT_CUR_COL
- MOV CURR_CUR_COL,AX
- MOV AX,INIT_CUR_ROW
- MOV CURR_CUR_ROW,AX
- ;
- CLEFT7: PUSH CURR_CUR_ROW
- PUSH CURR_CUR_COL
- PUSH 0
- CALL VIOSETCURPOS
- JMP KEYLOOP
- ;
-
- ;
- ; AT DO_CRT WE WANT TO LOOK RIGHT UNTIL WE FIND A SPACE THEN KEEP LOOKING
- ; UNTIL WE FIND A NON-SPACE
- ;
- DO_CRT: MOV BX,WORKPTR
- MOV AX,WORKTAIL
- MOV DL,' '
- MOV DH,'\'
- DEC AX
- CMP AX,BX
- JNE CRT1
- JMP KEYLOOP ; AT END OF LINE
- ;
- CRT1: INC BX ; NEXT CHAR
- CMP AX,BX ; AT END?
- JNE CRT2 ; NO
- JMP CRT5 ; YES
- ;
- CRT2: CMP WORKBUFF[BX],DL ; IS THIS A DELIMITER
- JE CRT3
- CMP WORKBUFF[BX],DH ;
- JNE CRT1 ; NO, KEEP LOOKING
- ;
- CRT3: INC BX ; YES, PASS IT
- CMP AX,BX ; AT END?
- JNE CRT4 ; NO
- JMP CRT5 ; YES
- ;
- CRT4: CMP WORKBUFF[BX],DL ; IS THIS A SPACE
- JE CRT3 ; YES, KEEP ON TRUCKING
- CMP WORKBUFF[BX],DH
- JE CRT3
- ;
- CRT5: MOV CX,BX
- MOV BX,WORKPTR
- MOV WORKPTR,CX
- MOV FUNCPTR,CX
- SUB CX,BX ; LENGTH MOVED
- MOV AX,CURR_CUR_COL
- ADD AX,CX
- CMP AX,80
- JL CRT6
- SUB AX,80
- MOV CURR_CUR_COL,AX
- MOV AX,CURR_CUR_ROW
- INC AX
- MOV CURR_CUR_ROW,AX
- JMP CRT9
- ;
- CRT6: MOV CURR_CUR_COL,AX
- ;
- CRT9: PUSH CURR_CUR_ROW
- PUSH CURR_CUR_COL
- PUSH 0
- CALL VIOSETCURPOS
- JMP KEYLOOP
- ;
- ; AT DO_LEFT WE SIMPLY MOVE THE CURSOR ONE CHARACTER TO THE LEFT
- ;
- DO_LEFT:
- MOV AX,WORKPTR
- CMP AX,0
- JNE LEFT1
- JMP KEYLOOP ; AT BEGINNING OF LINE
- ;
- LEFT1: DEC AX
- MOV WORKPTR,AX
- MOV FUNCPTR,CX
- MOV AX,CURR_CUR_COL
- CMP AX,0
- JNE LEFT2
- MOV AX,80
- MOV BX,CURR_CUR_ROW
- DEC BX
- MOV CURR_CUR_ROW,BX
- ;
- LEFT2: DEC AX
- MOV CURR_CUR_COL,AX
- PUSH CURR_CUR_ROW
- PUSH CURR_CUR_COL
- PUSH 0
- CALL VIOSETCURPOS
- JMP KEYLOOP
- ;
- ; AT DO_RIGHT WE SIMPLY MOVE THE CURSOR ONE CHARACTER TO THE RIGHT
- ;
- DO_RIGHT:
- MOV AX,WORKPTR
- INC AX
- CMP AX,WORKTAIL
- JNE RIGHT1
- JMP KEYLOOP ; AT END OF LINE
- ;
- RIGHT1: MOV WORKPTR,AX
- MOV FUNCPTR,AX
- MOV AX,CURR_CUR_COL
- INC AX
- CMP AX,80
- JNE RIGHT2
- MOV AX,0
- MOV BX,CURR_CUR_ROW
- INC BX
- MOV CURR_CUR_ROW,BX
- ;
- RIGHT2: MOV CURR_CUR_COL,AX
- PUSH CURR_CUR_ROW
- PUSH CURR_CUR_COL
- PUSH 0
- CALL VIOSETCURPOS
- JMP KEYLOOP
- ;
- ; AT DO_HOME WE MOVE TO THE BEGINNING OF THE LINE
- ;
- DO_HOME:
- XOR AX,AX
- MOV WORKPTR,AX
- MOV FUNCPTR,AX
- MOV AX,INIT_CUR_COL
- MOV CURR_CUR_COL,AX
- MOV BX,INIT_CUR_ROW
- MOV CURR_CUR_ROW,BX
- PUSH BX
- PUSH AX
- PUSH 0
- CALL VIOSETCURPOS
- JMP KEYLOOP
- ;
- ; AT DO_END WE MOVE THE THE END OF THE LINE
- ;
- DO_END: MOV AX,WORKTAIL
- DEC AX
- CMP AX,WORKPTR
- JNE END1
- JMP KEYLOOP ; ALREADY AT END
- ;
- END1:
- CMP AX,0
- JNE END2
- JMP KEYLOOP ; NO LINE
- ;
- END2: MOV WORKPTR,AX
- MOV FUNCPTR,AX
- MOV BX,INIT_CUR_COL
- ADD AX,BX
- CMP AX,80
- JL END3
- SUB AX,80
- MOV BX,INIT_CUR_ROW
- INC BX
- MOV CURR_CUR_ROW,BX
- ;
- END3: MOV CURR_CUR_COL,AX
- PUSH CURR_CUR_ROW
- PUSH CURR_CUR_COL
- PUSH 0
- CALL VIOSETCURPOS
- JMP KEYLOOP
- ;
- ; AT DO_INS WE TOGGLE THE INSERT_STATE AND CHANGE CURSOR SHAPE
- ;
- DO_INS: PUSH DS
- PUSH OFFSET CUR_SLINE
- PUSH 0
- CALL VIOGETCURTYPE
- ;
- MOV AX,INSERT_STATE
- CMP AX,1
- JE INS1
- MOV AX,1 ; NOW INSERT
- MOV INSERT_STATE,AX
- MOV AX,CUR_SLINE
- SUB AX,2
- MOV CUR_SLINE,AX
- JMP INS2
- ;
- INS1: MOV AX,0 ; NOW OVERWRITE
- MOV INSERT_STATE,AX
- MOV BX,O_CUR_SLINE ; GET ORIG. CUR
- MOV AX,O_CUR_ELINE
- MOV CUR_SLINE,BX
- MOV CUR_ELINE,AX
- ;
- INS2: PUSH DS
- PUSH OFFSET CUR_SLINE
- PUSH 0
- CALL VIOSETCURTYPE
- JMP KEYLOOP
- ;
- ; AT DO_DEL WE WANT TO DELETE THE CHARACTER AT THE CURSOR
- ;
- DO_DEL: MOV AX,WORKPTR
- INC AX
- CMP AX,WORKTAIL
- JNE DEL1
- JMP KEYLOOP ; AT END OF LINE
- ;
- DEL1: MOV DI,WORKPTR
- MOV SI,DI
- INC SI
- ADD DI,OFFSET WORKBUFF
- ADD SI,OFFSET WORKBUFF
- MOV CX,WORKTAIL ; END OF BUFFER
- DEC CX ; LESS 1
- MOV WORKTAIL,CX
- SUB CX,WORKPTR ; LENGTH OF CHARACTERS TO MOVE
- PUSH CX ; WE WILL NEED THIS IN A SEC
- REP MOVSB ; MOVE LINE IN BUFFER
- ;
- POP CX ; RESTORE LENGTH
- MOV BX,WORKTAIL ; PAST END OF LINE
- DEC BX
- MOV AL,20H
- MOV WORKBUFF[BX],AL
- MOV AX,0
- CALL DISPTAIL
- JMP KEYLOOP
- ;
- INC CX ; NEED TO SHOW SPACE AT END OF LINE
- PUSH DS ; SEGMENT OF LINE TO REDISPLAY
- MOV AX,WORKPTR
- ADD AX,OFFSET WORKBUFF
- PUSH AX ; OFFSET OF LINE
- PUSH CX
- PUSH 0 ; VIO HANDLE
- CALL VIOWRTTTY
- ;
- DEC THIS_LENGTH
- PUSH CURR_CUR_ROW
- PUSH CURR_CUR_COL
- PUSH 0
- CALL VIOSETCURPOS
- JMP KEYLOOP
- ;
- ; AT DO_F1 WE WANT TO DUPLICATE THE OS/2 F1 KEY WHICH DISPLAYS THE PREVIOUS
- ; LINE ONE CHARACTER AT A TIME
- ;
- DO_F1: MOV BX,WORKPTR
- CMP BX,FUNCMAX
- JGE DO_F1A
- MOV AL,FUNCBUFF[BX] ; LOAD NEXT KEY
- CMP AL,0 ; IS IT END OF THE LINE
- JE DO_F1A ; YES, DO NOTHING ELSE
- INC BX ; NO, UPDATE FUNCPTR
- MOV FUNCPTR,BX
- JMP ASC_KEY ; AND PRETEND THE KEY CAME FROM USER
- ;
- DO_F1A: JMP KEYLOOP
-
- ;
- ; AT DO_F2 WE WANT TO COPY CHARACTERS FROM FUNCBUFF UNTIL WE FIND
- ; THE KEY WE ARE LOOKING FOR
- ;
- DO_F2: CALL GETKEY
- CMP AX,0
- JE DO_F2A
- JMP BAD_FUNC
- ;
- DO_F2A: MOV SI,OFFSET KEYDEVBUF
- LODSW ; KEY SCAN_CODE AND CHAR_CODE
- CMP AL,0
- JNE DO_F2B
- JMP KEYLOOP
- ;
- DO_F2B: MOV SI,FUNCPTR
- ADD SI,OFFSET FUNCBUFF
- MOV DI,WORKPTR
- ADD DI,OFFSET WORKBUFF
- MOV AH,AL ; SAVE TARGET CHARACTER
- MOV CX,0
- MOV BX,SI
- MOV DX,FUNCMAX
- ADD DX,OFFSET FUNCBUFF
- LODSB ; ALWAYS MATCH FIRST CHAR
- CMP AL,0
- JE DO_F2E ; UNLESS IT ZERO
- ;
- DO_F2C: CMP SI,DX
- JGE DO_F2E
- LODSB
- INC CX
- CMP AL,AH
- JE DO_F2D
- CMP AL,0
- JE DO_F2E ; DO NOT MOVE IF NOT FOUND
- JMP DO_F2C
- ;
- DO_F2D: MOV SI,BX
- MOV AX,CX ; CX CONTAINS COUNT TO MOVE
- PUSH AX
- REP MOVSB
- MOV AL,0
- STOSB
- DEC DI
- POP AX
- SUB DI,OFFSET WORKBUFF
- PUSH DI
- INC DI
- MOV WORKTAIL,DI
- SUB SI,OFFSET FUNCBUFF
- MOV FUNCPTR,SI
- CALL DISPTAIL
- POP DI
- MOV WORKPTR,DI
- DO_F2E: JMP KEYLOOP
- ;
- ; AT DO_F3 WE COPY THE REMAINDER OF FUNCBUFF INTO WORKBUFF
- ;
- DO_F3: MOV SI,FUNCPTR
- ADD SI,OFFSET FUNCBUFF
- MOV DI,WORKPTR
- ADD DI,OFFSET WORKBUFF
- MOV BX,FUNCMAX
- ADD BX,OFFSET FUNCBUFF
- MOV AL,[SI]
- CMP AL,0
- JNE DO_F3B
- JMP KEYLOOP
- ;
- DO_F3B: CMP SI,BX
- JGE DO_F3D
- LODSB
- CMP AL,0
- JE DO_F3C
- STOSB
- JMP DO_F3B
- ;
- DO_F3C: MOV ES:[DI],AL
- SUB SI,OFFSET FUNCBUFF
- DEC SI
- MOV FUNCPTR,SI
- SUB DI,OFFSET WORKBUFF
- PUSH DI
- MOV AX,DI
- SUB AX,WORKPTR
- INC DI
- MOV WORKTAIL,DI
- CALL DISPTAIL
- POP DI
- MOV WORKPTR,DI
- DO_F3D: JMP KEYLOOP
-
- ;
- ; AT DO_UP CURRPTR WILL EITHER POINT TO THE END (ZERO) OF THE LAST LINE
- ; ENTERED (FOR A NEW LINE), OR TO THE FIRST CHARACTER OF THE LAST
- ; LINE RECALLED. IN ORDER TO RECALL A LINE WE MUST BACK CURRPTR
- ; UP TO THE BEGINNING OF A LINE. WE DO THIS BY SCANNING BACKWARDS
- ; UNTIL WE FIND A NON-ZERO CHARACTER AND THEN
- ; CONTINUING UNTIL WE FIND THE NEXT ZERO CHARACTER.
- ; NOTE THAT DO_UP WILL LEAVE CURRPTR POINTING TO THE FIRST CHAR
- ; OF THE LINE WE JUST RECALLED.
- ; ALSO NOTE THAT AT DO_UP, WE DECREMENT CURRPTR BEFORE WE START
- ; WHEREAS IN DO_DOWN WE START SCANNING AT CURRPTR.
- ;
- DO_UP: MOV CHANGE_FLAG,0 ; CLEAR CHANGE FLAG
- MOV BX,CURRPTR
- ;
- UP_LOOP1:
- DEC BX
- CMP BX,-1
- JNE UP_LOOP2
- MOV BX,KEYLEN-1
- UP_LOOP2:
- MOV AL,KEYBUFF[BX]
- CMP AL,0
- JNE UP_LOOP3
- CMP BX,CURRPTR
- JNE UP_LOOP1
- JMP DO_ESC ; WE WENT THROUGH BUFFER, NO LINES
- ;
- UP_LOOP3: ; NON-ZERO BYTE
- CMP BX,-1
- JNE UP_LOOP4
- MOV BX,KEYLEN
- UP_LOOP4:
- MOV AL,KEYBUFF[BX]
- DEC BX
- CMP AL,0
- JNE UP_LOOP3
- ;
- ; FOUND THE NEXT ASCII ZERO, THIS IS THE END OF A LINE. SAVE NEW CURRPTR
- ;
- UP_LOOP5:
- INC BX ; FIX LATE DECREMENT
- INC BX ; POINT PAST ASCII ZERO
- AND BX,KEYLEN-1
- MOV CURRPTR,BX ; MAKE THIS CURRENT LINE
- ;
- ; NOW MOVE THIS STRING (UP TO WORKMAX CHARACTERS) INTO WORKBUFF
- ;
- MOV DI,OFFSET WORKBUFF
- MOV CX,WORKMAX
- ;
- UP_LOOP6:
- AND BX,KEYLEN-1
- MOV AL,KEYBUFF[BX]
- CMP AL,0
- JE UP_LOOP7
- STOSB
- INC BX
- LOOP UP_LOOP6
- ;
- ; AT UP_LOOP7 WE EITHER FELL OUT OF THE LOOP WITH AN ASCII ZERO OR
- ; WORKMAX CHARACTERS
- ;
- UP_LOOP7:
-
- SUB DI,OFFSET WORKBUFF
- MOV WORKPTR,DI ; SET UP POINTERS
- MOV FUNCPTR,DI
- INC DI
- MOV WORKTAIL,DI ; INTO WORKBUFF
- ;
- ; NOW JOIN COMMON CODE TO DISPLAY WORKBUFF
- ;
- JMP DISPBUFF
- ;
- ; AT DO_DOWN WE WANT TO RECALL THE NEXT LINE FROM OUR CIRCULAR BUFFER.
- ; CURRPTR WILL EITHER POINT TO THE ZERO BEFORE THE LINE WE WISH
- ; TO RECALL OR IT WILL POINT TO THE FIRST CHARACTER OF THE LINE
- ; BEFORE THE ONE WE WISH TO RECALL. IN EITHER EVENT WE SCAN FOR
- ; A ZERO THEN FOR THE FIRST NON-ZERO. THAT IS THE FIRST CHARACTER
- ; OF THE LINE WE ARE SEEKING.
- ; NOTE THAT AT DO_DOWN WE START SCANNING AT CURRPTR WHILE IN DO_UP
- ; WE DECREMENT CURRPTR BEFORE WE START SCANNING.
- ;
- ;
- DO_DOWN:
- MOV CHANGE_FLAG,0 ; CLEAR CHANGE FLAG
- MOV BX,CURRPTR
- ;
- DOWN_LOOP1: ; WE NEED TO SCAN AHEAD UNTIL WE FIND
- MOV AL,KEYBUFF[BX] ; A ZERO CHARACTER
- CMP AL,0
- JE DOWN_LOOP2 ; FOUND IT
- INC BX ;
- AND BX,KEYLEN-1 ; KEEP IN RANGE
- CMP BX,CURRPTR
- JNE DOWN_LOOP1
- JMP KEYLOOP ; NOTHING IN BUFFER
- ;
- DOWN_LOOP2: ; NOW LOOK FOR NON-ZERO
- MOV AL,KEYBUFF[BX]
- CMP AL,0
- JNE DOWN_LOOP2A
- INC BX
- AND BX,KEYLEN-1
- CMP BX,CURRPTR
- JNE DOWN_LOOP2
- JMP KEYLOOP ; NOTHING IN BUFFER
- ;
- DOWN_LOOP2A:
- ; FIRST NON-ZERO CHAR
- ; WE FOUND THE END OF THIS LINE
- ; SAVE CURRPTR AND SCAN TO FIRST
- ; REAL CHARACTER OF THIS LINE
- MOV CURRPTR,BX ; SAVE CURRPTR FOR RECALL
- MOV DI,OFFSET WORKBUFF
- MOV CX,WORKMAX
- ;
- DOWN_LOOP3:
- AND BX,KEYLEN-1 ; KEEP POINTER IN RANGE
- MOV AL,KEYBUFF[BX]
- CMP AL,0
- JE DOWN_LOOP4
- STOSB
- INC BX
- LOOP DOWN_LOOP3
- ;
- ; AT DOWN_LOOP4, WE EITHER RAN OUT OF WORKMAX CHARACTERS OR WE FOUND
- ; AN ASCII ZERO.
- ;
- DOWN_LOOP4:
- SUB DI,OFFSET WORKBUFF
- MOV WORKPTR,DI
- MOV FUNCPTR,DI
- INC DI
- MOV WORKTAIL,DI
- ;
- ; AT DISPBUFF WE NEED TO DISPLAY THE CHARACTER STRING WE JUST MOVED INTO
- ; WORKBUFF.
- ;
- DISPBUFF:
- PUSH INIT_CUR_ROW
- PUSH INIT_CUR_COL
- PUSH 0 ; RESET
- CALL VIOSETCURPOS
- PUSH DS
- PUSH OFFSET BLANK
- PUSH LAST_LENGTH ; LENGTH OF LAST LINE
- PUSH INIT_CUR_ROW
- PUSH INIT_CUR_COL
- PUSH 0
- CALL VIOWRTNCHAR
- PUSH DS
- PUSH OFFSET WORKBUFF
- PUSH WORKPTR
- PUSH 0
- CALL VIOWRTTTY
- PUSH DS
- PUSH OFFSET CURR_CUR_ROW
- PUSH DS
- PUSH OFFSET CURR_CUR_COL
- PUSH 0
- CALL VIOGETCURPOS
- MOV AX,WORKPTR
- MOV LAST_LENGTH,AX
- ADD AX,INIT_CUR_COL
- CMP AX,80
- JL DISPBUFF1
- MOV AX,INIT_CUR_ROW
- CMP AX,CURR_CUR_ROW
- JNE DISPBUFF1
- DEC INIT_CUR_ROW
- DISPBUFF1:
- JMP KEYLOOP
- ;
- ; AT DO_CPUP WE WANT TO CLEAR THE ENTIRE RECALL BUFFER
- ;
- DO_CPUP:
- MOV DI,OFFSET KEYBUFF
- MOV CX,KEYLEN
- MOV AL,0
- REP STOSB
- MOV KEYTAIL,0
- MOV CURRPTR,0
- JMP DO_ESC ; CLEAR LINE
- ;
- ; AT DO_CPDN WE NEED TO DELETE THE CURRENT LINE (POINTED TO BY CURRPTR).
- ; NOTE THAT CURRPTR WILL POINT TO THE FIRST CHAR OF THE CURRENTLY
- ; RECALLED LINE. IF IT POINTS TO A ZERO, WE HAVE NOT DONE A RECALL
- ; SO SHOULD NOT ALLOW THE DELETION
- ;
- DO_CPDN:
- MOV BX,CURRPTR ; POINT TO CURRENT LINE
- ;
- DO_CPDN1:
- MOV AL,KEYBUFF[BX]
- CMP AL,0 ; IF ZERO WE ARE DONE
- JE DO_CPDN2
- MOV AL,0 ; CLEAR THIS CHAR
- MOV KEYBUFF[BX],AL
- INC BX ; POINT TO NEXT
- AND BX,KEYLEN-1 ; KEEP IN RANGE
- CMP BX,CURRPTR ; HAVE WE LOOPED
- JE DO_CPDN2 ; YES
- JMP DO_CPDN1 ; NO, KEEP CLEARING
- ;
- DO_CPDN2:
- JMP DO_UP
- ;
- ; AT TOO_MANY WE ALREADY HAVE AS MANY KEYS AS WE WILL ACCEPT
- ;
- TOO_MANY:
- PUSH 300
- PUSH 16
- CALL DOSBEEP
- PUSH 600
- PUSH 16
- CALL DOSBEEP
- JMP KEYLOOP
- ;
- ; AT KEYDONE WE HAVE FINISHED ALL EDITING FUNCTIONS. MOVE THE NEW LINE
- ; INTO THE FUNCTION KEY BUFFER. CLEAN UP THE STACK AND GO HOME.
- ;
- KEYDONE:
- MOV DI,OFFSET FUNCBUFF
- MOV SI,OFFSET WORKBUFF
- MOV CX,WORKTAIL
- MOV FUNCMAX,CX
- DEC CX
- REP MOVSB
- MOV AL,0
- STOSB
- MOV FUNCPTR,0
- ;
- PUSH DS
- PUSH OFFSET O_CUR_SLINE
- PUSH 0
- CALL VIOSETCURTYPE
- POPF
- POP DX
- POP CX
- POP BX
- POP AX
- POP ES
- POP DS
- POP SI
- POP DI
- POP BP
- MOV AX,0
- RET
-
- NOT_OURS:
- POPF
- POP DX
- POP CX
- POP BX
- POP AX
- POP ES
- POP DS
- POP SI
- POP DI
- POP BP
- NOT_OURS1:
- MOV AX,-1
- RET
-
- BAD_FUNC:
- PUSH DS
- PUSH OFFSET O_CUR_SLINE
- PUSH 0
- CALL VIOSETCURTYPE
- POPF
- POP DX
- POP CX
- POP BX
- POP AX
- POP ES
- POP DS
- POP SI
- POP DI
- POP BP
- MOV AX,-1
- RET
-
- KEYSTRIN ENDP
-
- ;
- ; GETKEY IS THE CALL TO READ ANOTHER KEY FROM DEVICE DRIVER
- ;
- GETKEY PROC NEAR
- PUSH DS
- PUSH OFFSET KEYDEVBUF
- PUSH DS
- PUSH OFFSET KEYDEVPRM
- PUSH 74H ; READ CHARACTER FUNCTION
- PUSH 04H ; KEYBOARD CONTROL CATEGORY
- MOV AX,KEYHAND
- PUSH AX
- CALL DOSDEVIOCTL
- RET
- GETKEY ENDP
-
- ;
- ; DISPTAIL WILL (RE)DISPLAY WORKBUFF FROM WORKPTR TO WORKTAIL
- ; IF AX == 0 THE CURRENT CURSOR POSITION WILL NOT BE UPDATED UNLESS
- ; A LINE WRAP OCCURRED, THEN CURR_CUR_ROW AND INIT_CUR_ROW WILL BE
- ; FIXED. IF AX != 0 CURSOR WILL BE BUMPED BY AX POSITIONS.
- ; THIS_LENGTH WILL ALWAYS BE UPDATED
- ;
- DISPTAIL PROC NEAR
- PUSH BX
- PUSH CX
- PUSH DX
- PUSH AX
- MOV AX,WORKTAIL
- DEC AX
- MOV THIS_LENGTH,AX
- CMP AX,LAST_LENGTH
- JLE DISPT1
- MOV LAST_LENGTH,AX
- DISPT1:
- PUSH DS
- MOV AX,WORKPTR
- ADD AX,OFFSET WORKBUFF
- PUSH AX
- MOV AX,WORKTAIL
- SUB AX,WORKPTR
- PUSH AX
- XOR AX,AX
- PUSH AX
- CALL VIOWRTTTY
- MOV BX,CURR_CUR_ROW ; SAVE OLD CUR_POS
- MOV CX,CURR_CUR_COL
- PUSH DS
- PUSH OFFSET CURR_CUR_ROW
- PUSH DS
- PUSH OFFSET CURR_CUR_COL
- PUSH 0
- CALL VIOGETCURPOS
- POP AX ; SHOULD WE UPDATE CUR_POS
- CMP AX,0 ; TO END OF LINE
- JE NO_UPDATE_CUR ; NO
- JMP UPDATE_CUR
- ;
- NO_UPDATE_CUR:
- MOV AX,WORKTAIL ; NO UPDATE
- ADD AX,INIT_CUR_COL
- CMP AX,80 ; DID WE WRAP A LINE?
- JL RESET_CUR ; NO
- MOV AX,INIT_CUR_ROW ; YES
- CMP AX,CURR_CUR_ROW ; DID ROW CHANGE
- JNE RESET_CUR ; NO, THE SCREEN DID NOT SCROLL
- DEC AX ; YES, THE SCREEN SCROLLED
- MOV INIT_CUR_ROW,AX ; MOVE INIT_CUR_ROW BACK ONE
- MOV BX,AX ; SHOW CURR_CUR_ROW BACK ONE
- RESET_CUR:
- MOV CURR_CUR_ROW,BX ; DO NOT UPDATE CURSOR POSITION
- MOV CURR_CUR_COL,CX
- PUSH BX ; RESET CURSOR POSITION
- PUSH CX
- PUSH 0
- CALL VIOSETCURPOS
- JMP DISPTDONE
- ;
- ;
- UPDATE_CUR:
- MOV CURR_CUR_ROW,BX
- MOV CURR_CUR_COL,CX
- ADD AX,CX
- MOV CURR_CUR_COL,AX
- CMP AX,80
- JL DISPTDONE ; NO LINE WRAP
- SUB AX,80
- MOV CURR_CUR_COL,AX
- INC CURR_CUR_ROW
- MOV AX,INIT_CUR_ROW
- CMP AX,CURR_CUR_ROW ; THERE WAS A LINE WRAP
- JNE DISPTDONE ; BUT THE SCREEN DID NOT SCROLL
- DEC AX ; THE SCREEN DID SCROLL
- MOV INIT_CUR_ROW,AX ; SHOW INIT_CUR AS BACK ONE LINE
- ;
- DISPTDONE:
- PUSH CURR_CUR_ROW
- PUSH CURR_CUR_COL
- PUSH 0
- CALL VIOSETCURPOS
- POP DX
- POP CX
- POP BX
- RET
-
- DISPTAIL ENDP
-
- ;
- ; ADDSYN IS THE PUBLIC ENTRY POINT TO THE ALIAS SYSTEM.
- ; ADDSYN IS CALLED WITH A FAR POINTER TO AN ASCIIZ ALIAS.
- ; THE ALIAS TAKES THE FORM OF ALIAS REPLACEMENT. ALIAS MUST NOT
- ; CONTAIN ANY SPACES, REPLACEMENT IS ASCIIZ. ON RETURN AX == 0
- ; IF SUCCESSUFLLY ADDED, AX != 0 IF BUFFER FULL.
- ;
- ; THE ALIAS BUFFER CONSISTS OF SETS OF ALIAS REPLACEMENTS STORED AS FOLLOWS:
- ; ALIASA,0FFH,REPLACEMENTA,0H,ALIASB,0FFH,REPLACEMENTB,0H...
- ; ALIASN,0FFH,REPLACEMENTN,0H,0FFH
- ;
- ASSUME CS:KEYREP, DS:SBUFF, ES:LBUFF
- PUBLIC ADDSYN
- ;
- ADDSYN PROC FAR
- PUSH BP
- MOV BP,SP
- PUSH BX
- PUSH CX
- PUSH DX
- PUSH DI
- PUSH SI
- PUSH ES
- PUSH DS
- MOV AX,SEG SBUFF
- MOV DS,AX
-
- ASSUME ES:SBUFF
- ;
- A0:
- ; OK, WE ARE LOADED.
- ; STACK LOOKS LIKE THIS:
- ; [BP+0] - BP
- ; [BP+2] - RETURN SEGMENT
- ; [BP+4] - RETURN OFFSET
- ; [BP+6] - OFFSET OF ALIAS STRING
- ; [BP+8] - SEGMENT OF ALIAS STRING
- MOV AX,SEG SBUFF
- MOV ES,AX
- MOV DI,ES:SYNHEAD ; ES:DI POINTS TO ALIAS BUFFER
- MOV AX,[BP+8]
- MOV DS,AX
- MOV SI,[BP+6] ; DS:SI POINTS TO ALIAS STRING
- MOV DX,SYNLEN-1
- MOV CX,0
- PUSH SI
- ;
- A1: ; SCAN FOR LENGTH OF ALIAS
- LODSB
- INC CX
- CMP AL,' '
- JE A2
- CMP AL,0
- JNE A1
- JMP DEL_SYN
- ;
- A2:
- DEC CX
- POP SI
- CMP DI,ES:SYNTAIL ; ARE WE AT START OF BUFFER?
- JE ADDSYN1 ; YES, JUST DO ADD
- CALL CMPSTR ; NO, LOOK FOR ALIAS
- CMP AX,0
- JNE ADDSYN1
- JMP REPLACE_SYN
- ;
- ADDSYN1:
- MOV CX,0 ; CLEAR COUNT
- PUSH SI ; POINTER TO ALIAS STRING
- ;
- ALIAS_LEN:
- LODSB ; GET CHAR
- INC CX
- CMP AL,0
- JNE ALIAS_LEN
- ;
- PUSH CX ; CONTAINS LENGTH OF NEW ALIAS
- PUSH DI ; END OF ALIAS BUFFER
- ALIAS_LEN1:
- INC DI
- CMP DI,SYNLEN
- JE NO_ROOM
- LOOP ALIAS_LEN1
- JMP HAVE_ROOM
- ;
- NO_ROOM: ; NOT ENOUGH ROOM FOR NEW ALIAS
- POP DI
- POP CX
- POP SI
- JMP ADD_FAIL
- ;
- HAVE_ROOM: ; WE HAVE ROOM
- POP DI
- POP CX
- POP SI
- PUSH DI ; SAVE POINTER FOR A MOMENT
- ;
- PUT_ALIAS_IN:
- LODSB
- STOSB
- LOOP PUT_ALIAS_IN
- MOV AL,0FFH ; MARK END OF ALIAS
- STOSB ; STORE IT
- MOV ES:SYNTAIL,DI ; NEW SYNTAIL
- POP DI ; RESTORE POINTER TO START
- ;
- FIND_FIRST_SPACE:
- MOV AL,ES:[DI]
- CMP AL,' ' ; SCAN FOR FIRST SPACE
- JE FOUND_FIRST_SPACE
- INC DI
- JMP FIND_FIRST_SPACE
- ;
- FOUND_FIRST_SPACE:
- MOV AL,0FFH
- MOV ES:[DI],AL
- POP DS
- POP ES
- POP SI
- POP DI
- POP DX
- POP CX
- POP BX
- POP BP
- MOV AX,0
- RET 4
- ;
- ; AT REPLACE_SYN, WE NEED TO REPLACE AN EXISTING ALIAS. WHAT WE WILL DO
- ; IS TO DELETE THIS ALIAS AND SLIDE THE BUFFER CLOSED. WE THEN
- ; REJOIN THE CODE TO ADD AN ALIAS. ON ENTRY DI POINTS TO THE
- ; START OF THE REPLACEMENT STRING FOR THIS ALIAS SOURCE. WE NEED
- ; TO BACK DI UP TO THE START OF THIS ALIAS.
- ;
- REPLACE_SYN:
- PUSH DS
- PUSH ES
- POP DS
- R1:
- DEC DI
- CMP DI,0 ; AT START OF BUFFER?
- JE R1A
- CMP BYTE PTR [DI],0 ; AT START OF ALIAS
- JNE R1 ; NO, KEEP LOOKING
- INC DI ; POINT DI TO FIRST CHAR OF ALIAS
- R1A:
- MOV SI,DI
- ;
- R2: ; SCAN FOR END OF REPLACEMENT
- LODSB
- CMP AL,0
- JNE R2
- ;
- CMP BYTE PTR [SI],0FFH ; WAS THIS LAST STRING?
- JNE R3 ; NO
- MOV AL,0FFH ; YES, JUST MARK END.
- STOSB ; DI STILL POINTS TO START.
- MOV SYNTAIL,DI
- JMP LAST_ALIAS
- ;
- R3:
- MOV CX,SYNTAIL
- SUB CX,SI ; COUNT OF CHARACTERS TO MOVE
- REP MOVSB
- MOV SYNTAIL,DI
- ;
- LAST_ALIAS:
- POP DS
- JMP A0 ; JOIN CODE FOR ADD.
- ;
- ; AT DEL_SYN WE NEED TO REMOVE THIS ALIAS ENTIRELY
- ; THE LOGIC IS THE SAME AS REPLACE_SYN ABOVE.
- ;
-
- DEL_SYN:
- DEC CX ; CX IS LENGTH OF ALIAS
- POP SI ; RESTORE START OF ALIAS
- CALL CMPSTR ; LOOK FOR ALIAS
- CMP AX,0
- JNE DEL_SYN5 ; ALIAS DOES NOT EXIST
- PUSH ES
- POP DS
- DEL_SYN1:
- DEC DI
- CMP DI,0 ; AT START OF BUFFER?
- JE DEL_SYN2
- CMP BYTE PTR [DI],0 ; AT START OF ALIAS
- JNE DEL_SYN1 ; NO, KEEP LOOKING
- INC DI ; POINT DI TO FIRST CHAR OF ALIAS
- DEL_SYN2:
- MOV SI,DI
- ;
- DEL_SYN3: ; SCAN FOR END OF REPLACEMENT
- LODSB
- CMP AL,0
- JNE DEL_SYN3
- ;
- CMP BYTE PTR [SI],0FFH ; WAS THIS LAST STRING?
- JNE DEL_SYN4 ; NO
- MOV AL,0FFH ; YES, JUST MARK END.
- STOSB ; DI STILL POINTS TO START.
- MOV SYNTAIL,DI
- JMP DEL_SYN5
- ;
- DEL_SYN4:
- MOV CX,SYNTAIL
- SUB CX,SI ; COUNT OF CHARACTERS TO MOVE
- REP MOVSB
- MOV SYNTAIL,DI
- ;
- DEL_SYN5:
- POP DS
- POP ES
- POP SI
- POP DI
- POP DX
- POP CX
- POP BX
- POP BP
- MOV AX,0
- RET 4
- ;
- ADD_FAIL:
- POP DS
- POP ES
- POP SI
- POP DI
- POP DX
- POP CX
- POP BX
- POP BP
- MOV AX,1
- RET 4
- ;
- ADD_FAIL2:
- POP DS
- POP ES
- POP SI
- POP DI
- POP DX
- POP CX
- POP BX
- POP BP
- MOV AX,2
- RET 4
- ;
- ADDSYN ENDP
-
- ASSUME CS:KEYREP, DS:SBUFF, ES:SBUFF
- ;
- ; CLEARSYN WILL SIMPLY CLEAR OUT ALL ALIASES
- ;
- PUBLIC CLEARSYN
-
- CLEARSYN PROC FAR
- PUSH BX
- PUSH CX
- PUSH DX
- PUSH DS
- PUSH ES
- ;
- ASSUME DS:SBUFF
- ;
- C1:
- MOV AX,SEG SBUFF
- MOV DS,AX
- XOR AX,AX
- MOV SYNHEAD,AX
- MOV SYNTAIL,AX
- MOV BX,AX
- MOV CX,SYNLEN
- CLEAR1: MOV [BX],AL
- INC BX
- LOOP CLEAR1
- ;
- CLEAR2:
- POP ES
- POP DS
- POP DX
- POP CX
- POP BX
- MOV AX,0
- RET
- ;
- CLEAR3:
- POP ES
- POP DS
- POP DX
- POP CX
- POP BX
- MOV AX,1
- RET
-
- CLEARSYN ENDP
-
- ASSUME CS:KEYREP, DS:SBUFF, ES:SBUFF
- PUBLIC LIST_SYN
- ;
- ; LIST_SYN WILL LIST THE CURRENT ALIASES OUT TO STDOUT
- ;
- LIST_SYN PROC FAR
- PUSH BP
- MOV BP,SP
- PUSH BX
- PUSH CX
- PUSH DX
- PUSH SI
- PUSH DI
- PUSH ES
- PUSH DS
- MOV AX,SEG SBUFF
- MOV DS,AX
- JMP LIST_SYN1
- ;
- ASSUME ES:SBUFF
- ;
- LIST_SYN1:
- MOV AX,DS
- MOV ES,AX
- MOV SI,SYNHEAD
- CMP SI,SYNTAIL
- JNE GET_SYN0
- JMP NO_SYN_LIST
- ;
- GET_SYN0:
- MOV DI,OFFSET PRINT_LINE
- MOV CX,0
- GET_SYN:
- LODSB
- CMP AL,0FFH
- JE GET_SYN1
- STOSB
- INC CX
- JMP GET_SYN
- ;
- GET_SYN1:
- MOV AL,20H
- STOSB
- INC CX
- ;
- GET_SYN2:
- LODSB
- CMP AL,0
- JE GET_SYN3
- STOSB
- INC CX
- JMP GET_SYN2
- ;
- GET_SYN3:
- MOV AL,0DH
- STOSB
- MOV AL,0AH
- STOSB
- ADD CX,2
- MOV AX,1
- PUSH AX
- MOV DI,OFFSET PRINT_LINE
- PUSH DS
- PUSH DI
- PUSH CX
- PUSH DS
- MOV AX,OFFSET WRITTEN
- PUSH AX
- CALL DOSWRITE
- ;
- CMP BYTE PTR [SI],0FFH
- JE GET_SYN4
- ;
- MOV CX,0
- JMP GET_SYN
- ;
- GET_SYN4:
- POP DS
- POP ES
- POP DI
- POP SI
- POP DX
- POP CX
- POP BX
- POP BP
- MOV AX,0
- RET
- ;
- NO_SYN_LIST:
- POP DS
- POP ES
- POP DI
- POP SI
- POP DX
- POP CX
- POP BX
- POP BP
- MOV AX,1
- RET
- ;
- NO_SYN_LIST2:
- POP DS
- POP ES
- POP DI
- POP SI
- POP DX
- POP CX
- POP BX
- POP BP
- MOV AX,2
- RET
- ;
- LIST_SYN ENDP
-
-
- ;
- ; ON ENTRY TO ALIAS BOTH DS AND ES POINT TO LBUFF
- ; WE WANT TO SET ES TO SYN AND SCAN THROUGH SBUFFER TO FIND A
- ; MATCHING ALIAS. IF FOUND WE WILL COPY THAT BACK TO THE CALLING
- ; ROUTINE ALONG WITH THE REMAINDER OF WORKBUFF
- ;
- ASSUME CS:KEYREP, DS:LBUFF, ES:SBUFF
- ALIAS PROC
- PUSH BX
- PUSH CX
- PUSH DX
- PUSH SI
- PUSH DI
- PUSH DS
- PUSH ES
- MOV SI,OFFSET WORKBUFF
- PUSH SI
- MOV CX,0
- FIND_END:
- LODSB
- INC CX
- CMP AL,' '
- JE FOUND_END
- CMP AL,0DH
- JNE FIND_END
- FOUND_END:
- DEC CX
- POP SI
- ; SI POINTS TO SOURCE TO MATCH
- ; CX IS LENGTH TO MATCH
- ; ACTUALLY [SI+CX] == ' '
- MOV AX,SEG SBUFF
- MOV ES,AX
- MOV DX,SYNLEN
- DEC DX
- MOV DI,ES:SYNHEAD ; START OF SYNBUFF IN ES
- CMP DI,ES:SYNTAIL ; ANYTHING IN BUFFER?
- JE NOSYN ; NO
- CALL CMPSTR ; YES, GO LOOKING
- CMP AX,0
- JE GOTSYN
- JMP NOSYN
- ;
- ; AT GOTSYN, WE FOUND AN ALIAS. ES:DI POINTS TO START OF REPLACEMENT
- ; DS:SI STILL POINTS TO START OF SOURCE AND CX STILL CONTAINS
- ; LENGTH OF SOURCE
- ;
- GOTSYN: MOV BX,DI ; BX POINTS TO REPLACEMENT
- MOV DI,OFFSET XMITBUFF
- MOV AX,ES
- PUSH DS
- POP ES
- MOV DS,AX
- ;
- ALOOP4: MOV AL,[BX] ; REPLACEMENT IN DS:[BX]
- CMP AL,0 ; XMITBUFF IN ES:[DI]
- JE ALOOP5
- STOSB
- INC BX
- AND BX,SYNLEN-1
- JMP ALOOP4
- ;
- ALOOP5: PUSH ES
- POP DS ; DS NOW POINTS TO BOTH WORKBUFF AND XMITBUFF
- ADD SI,CX
- ;
- ALOOP6: LODSB
- CMP AL,0DH
- JE ALOOP7
- STOSB
- JMP ALOOP6
- ;
- ALOOP7: STOSB
- POP ES
- POP DS
- POP DI
- POP SI
- POP DX
- POP CX
- POP BX
- MOV AX,0
- JMP ALOOPDONE
- ;
- NOSYN:
- POP ES
- POP DS
- POP DI
- POP SI
- POP DX
- POP CX
- POP BX
- MOV AX,1
- ;
- ALOOPDONE:
- RET
-
- ALIAS ENDP
-
- ;
- ; CMPSTR IS A ROUTINE TO COMPARE A SOURCE STRING IN DS:SI OF LENGTH CX
- ; TO A SET OF STRINGS IN A CIRCULAR BUFFER ES:DI OF LENGTH DX+1.
- ; THE STRINGS ARE FORMED AS STRINGA,0FFH,STRINGB,0H. WE ATTEMPT TO
- ; MATCH THE SOURCE STRING WITH STRINGA. THE FINAL STRING SET IS
- ; TERMINATED WITH A 0H AND A 0FFH.
- ; ON RETURN, IF AX==0 MATCH FOUND AND DI POINTS TO REPLACEMENT.
- ; IF AX == 1 NO MATCH FOUND AND DI POINTS TO END OF BUFFER.
- ;
- CMPSTR PROC NEAR
- PUSH SI
- PUSH CX
-
- S_LOOP: LODSB
- CMP AL,61H
- JL S_LOOP1
- CMP AL,7AH
- JG S_LOOP1
- SUB AL,20H
- S_LOOP1:
- MOV AH,AL
- MOV AL,ES:[DI]
- CMP AL,61H
- JL S_LOOP2
- CMP AL,7AH
- JG S_LOOP2
- SUB AL,20H
- S_LOOP2:
- CMP AL,AH
- JNE NO_MATCH
- INC DI
- AND DI,DX
- LOOP S_LOOP
- E_LOOP: CMP BYTE PTR ES:[DI],0FFH
- JE FOUND_MATCH
- JMP NO_MATCH1
- NO_MATCH:
- INC DI
- AND DI,DX
- NO_MATCH1:
- CMP BYTE PTR ES:[DI],0
- JNE NO_MATCH
- INC DI
- AND DI,DX
- CMP BYTE PTR ES:[DI],0FFH
- JE FAIL
- POP CX
- POP SI
- PUSH SI
- PUSH CX
- JMP S_LOOP
- ;
- FOUND_MATCH:
- POP CX
- POP SI
- INC DI
- MOV AX,0
- RET
- ;
- FAIL: POP CX
- POP SI
- MOV AX,1
- RET
-
- CMPSTR ENDP
-
-
- KEYREP ENDS
- END START
-
-