📄 tanxlat.asm
字号:
;*
;* CW : Character Windows Drivers
;*
;* tanxlat.asm : Tandy 1000 Key translation
;*****************************************************************************
;********** VwFromSc **********
;* entry : CH = sc (scan code)
;* CL = ch (character)
;* BX = mpscvw = pointer to MPSCVW array (in CS)
;* * convert scan code to virtual key
;* * return virtual key
;* exit : BL = vw
;* Z flag set if (vw == 0)
;* * TRASHES BX and AX only
cProc VwFromSc, <NEAR, ATOMIC, PUBLIC>
cBegin nogen ;VwFromSc
;{{
; Assert(sc != 0);
; while (mpscvw->sc != 0)
; {
; if (mpscvw->sc == sc (DH))
; return mpscvw->vw; // in bl
; mpscvw++;
; }
; return 0;
;}}
IFDEF DEBUG
cmp ch,0
jnz vfs_ok1
int 3
vfs_ok1:
ENDIF
tovw_loop:
mov al,CS:[bx].scMpVw
or al,al
jz fail_tovw
add bx,SIZE MPSCVW
cmp al,ch
jne tovw_loop
mov bl,CS:[bx].(vwMpVw - SIZE MPSCVW)
or bl,bl ;* set nz
ret
fail_tovw: ;* no match
xor bl,bl ;* set z
ret
cEnd nogen ;VwFromSc
;********** ChFromSc **********
;* entry : CH = sc (scan code)
;* CL = ch (character)
;* DX = mpscch = pointer to MPSCCH array (in CS)
;* * convert scan code to virtual key
;* * return virtual key
;* exit : CL = ch (character)
;* * TRASHES AX only
cProc ChFromSc, <NEAR, ATOMIC, PUBLIC>
cBegin nogen ;ChFromSc
push bx
mov bx, dx
;{{
; Assert(sc != 0);
; while (mpscch->sc != 0)
; {
; if (mpscch->sc == sc (DH))
; return mpscch->ch; /* in cl */
; mpscch++;
; }
; return ch; /* in cl */
;}}
IFDEF DEBUG
cmp ch,0
jnz cfs_ok1
int 3
cfs_ok1:
ENDIF
toch_loop:
mov al,CS:[bx].scMpCh
or al,al
jz done_toch
add bx,SIZE MPSCCH
cmp al,ch
jne toch_loop
mov cl,CS:[bx].(chMpCh - SIZE MPSCCH)
done_toch:
pop bx
ret
cEnd nogen ;ChFromSc
;********* XlateKey **********
;* entry: DI => driver data
;* AL = char, AH = scan code
;* DX = shift states
;* * translate into character with shifts
;* * call UpdateShiftKk and KeyboardMessage with any results
cProc XlateKey,<NEAR, PUBLIC, ATOMIC>,<SI, DI>
localW ssOn
localW ssTemp
ssOff EQU SI ;* ssOff register variable
cBegin XlateKey
AssertEQ di,OFF_lpwDataKbd
mov cx,ax ;* AL = CL = ch, AH = CH = sc
mov ssTemp,dx ;* WARNING ch is in cl !!!!
;{{
; vw (bl) = 0;
; ssOn = ssOff = 0
;}}
xor bx,bx ;* vw = 0, can assume bh == 0
mov ssOn,bx
xor ssOff,ssOff ; ssOff = 0
;{{
; if (sc == 0)
; {
; if (ch != 0)
; {
; /*
; ch is a character entered numerically using the
; Alt key in combination with the numeric key pad.
; (e.g. The user typed Alt-down 1 2 3 Alt-Up the enter
; the char with decimal value 123)
; */
; vw = 0; /* already */
; ssOff = SS_ALT | SS_SHIFT | SS_CONTROL;
; }
; }
;}}
or ch,ch
jnz real_scan_code
;* * no real scan code (probably from alt-numpad)
jcxz done_xlat_2 ;* just update shift states
mov ssOff,(SS_ALT OR SS_SHIFT OR SS_CONTROL)
done_xlat_2:
jmp done_xlat
real_scan_code:
;{{ /* Some exceptions: override CH to force table lookup */
; if (sc == SC_6 && (ch == 01Eh || ch == '}') || /* [Alt] Ctrl 6 */
; sc == SC_MINUS && ch == 01Fh || /* Ctrl - */
; sc == SC_MULTIPLY && ch == 010h || /* PRINT key */
; sc == SC_ENTER || /* main ENTER */
; sc == SC_TAB ||
; sc == SC_ESCAPE ||
; sc == SC_BACKSPACE)
; ch = 0;
;}}
cmp cx, 071Eh ;* Ctrl 6^
je kill_ch
cmp cx, 077Dh ;* Alt Ctrl 6^
je kill_ch
cmp cx, 0C1Fh ;* Ctrl -_
je kill_ch
cmp cx, 3710h ;* PRINT
je kill_ch
cmp ch, SC_ENTER
je kill_ch
cmp ch, SC_TAB
je kill_ch
cmp ch, SC_ESC
je kill_ch
cmp ch, SC_BACKSPACE
jne not_special
kill_ch:
xor cl, cl
jmp short xlat_look_1
not_special:
;{{ /* Numpad ENTER is a little peculiar */
; if (ch == SC_NUMPAD_ENTER && ch != 0)
; {
; vw = VwOfVk(VK_RETURN);
; ssOn |= SS_EXTENDED;
; goto done_xlat; /* skip the table lookup */
; }
;}}
cmp ch, 57h ;* SC_NUMPAD_ENTER
jne not_num_enter
or cl, cl ;* watch out! Shift-F4 has same sc
jz not_num_enter
mov bl, VwOfVk(VK_RETURN)
or ssOn, SS_EXTENDED
jmp short done_xlat_2
not_num_enter:
;{{ /* Some numpad exceptions when NumLock is off */
; if (! (ssTemp & SS_NUMLOCK))
; {
; if (sc == SC_NUMPAD1 && ch == '1' ||
; sc == SC_NUMPAD3 && ch == '3' ||
; sc == SC_NUMPAD9 && ch == '5' ||
; sc == SC_SHIFT_INSERT && ch == '+' ||
; sc == SC_DELETE && ch == '-')
; {
; ssTemp &= ~SS_SHIFT;
; ssOn |= SS_SHIFT;
; /* the following is optimized into the above 'if' */
; if (sc == SC_NUMPAD5)
; sc = SC_PLAIN_NUMPAD5, ch = 0;
; else if (sc == SC_SHIFT_INSERT)
; sc = SC_INSERT, ch = 0;
; else if (sc == SC_DELETE)
; ch = 0;
; }
; }
;}}
test ssTemp, SS_NUMLOCK
jnz num_lock_on ;* handle shift w/o NumLock first
cmp cx, 4F31h ;* sc == NUMPAD1, ch == '1'
je num_shift
cmp cx, 5133h ;* sc == NUMPAD3, ch == '3'
je num_shift
cmp cx, 4939h ;* sc == NUMPAD9, ch == '9'
je num_shift
cmp cx, 4C35h ;* sc == NUMPAD5, ch == '5'
jne not_5
mov ch, 0F3h ;* sc = PLAIN_NUMPAD5
jmp short num_shift
not_5:
cmp cx, 552Bh ;* sc == SHIFT_INSERT, ch == '+'
jne not_ins
mov ch, 52h ;* sc = INSERT
jmp short num_shift
not_ins:
cmp cx, 532Dh ;* sc == DELETE, ch = '-'
jne xlat_look_1
num_shift:
xor cl, cl ;* kill ch to force table lookup
and ssTemp, not SS_SHIFT ;* fool the sc to vw conversion
or ssOn, SS_SHIFT ;* but keep the shift state
xlat_look_1:
jmp xlat_lookup
num_lock_on:
;{{ /* Some more exceptions, this time with NumLock on */
; else
; { /* The weird INSERT/'+' key */
; if (sc == SC_SHIFT_INSERT && ch == '+' ||
; sc == SC_INSERT && ch == 0 ||
; sc == SC_CONTROL_INSERT && ch == 0)
; ch = '+', vw = VwOfVk(VK_ADD),
; ssOn |= SS_EXTENDED;
; /* and skip the VwFromSc transform */
;}}
cmp cx, 552Bh ;* sc == SHIFT_INSERT, ch = '+'
je num_add_1
cmp cx, 5200h ;* sc == INSERT, ch == 0
je num_add
cmp cx, 9F00h ;* sc == CONTROL_INSERT, ch = 0
jne num_not_add
num_add:
mov cl, '+'
num_add_1:
mov bl, VwOfVk(VK_ADD)
jmp short num_add_sub
num_not_add:
;{{ /* The weird DELETE/'-' key */
; else if (sc == SC_DELETE && (ch == '-' || ch == 0) ||
; sc == SC_CONTROL_DELETE && ch == 0)
; ch = '-', vw = VwOfVk(VK_SUBTRACT);
; /* and skip the VwFromSc transform */
; }
;}}
cmp cx, 532Dh ;* sc == DELETE, ch == '-'
je num_sub_1
cmp cx, 5300h ;* sc == DELETE, ch == 0
je num_sub
cmp cx, 9D00h ;* sc == CONTROL_DELETE, ch = 0
jne not_num_sub
num_sub:
mov cl, '-'
num_sub_1:
mov bl, VwOfVk(VK_SUBTRACT)
num_add_sub:
or ssOn, SS_EXTENDED
jmp done_xlat
not_num_sub:
xlat_lookup:
;{{ /* Convert scan codes to VW's, aided by knowledge of shift state */
; if (ch == 0)
; {
; if (ssTemp & SS_ALT)
; pmpscvw = pmpscvwAlt,
; pmpscch = pmpscchAlt;
; else if (ssTemp & SS_CONTROL)
; pmpscvw = pmpscvwCtrl,
; pmpscch = pmpscchCtrl;
; else if (ssTemp & SS_SHIFT)
; pmpscvw = pmpscvwShift,
; pmpscch = pmpscchShift;
; else
; pmpscvw = pmpscvwPlain,
; pmpscch = pmpscchPlain;
; ch = ChFromSc(pmpscch, sc);
; vw = VwFromSc(pmpscvw, sc);
; if (vw)
; if (vw == VwOfVk(VK_MULTIPLY) ||
; vw == VwOfVk(VK_ADD) ||
; vw == VwOfVk(VK_SUBTRACT) ||
; vw == VwOfVk(VK_DECIMAL) ||
; vw == VwOfVk(VK_NUMPAD0 ||
; vw == VwOfVk(VK_NUMPAD6))
; ssOn |= SS_EXTENDED;
; }
;}}
or cl, cl
jnz done_lookup
mov ax, ssTemp
mov bx, drvOffset mpscvwAlt
mov dx, drvOffset mpscchAlt
test ax, SS_ALT
jnz lookup_bx
mov bx, drvOffset mpscvwCtrl
mov dx, drvOffset mpscchCtrl
test ax, SS_CONTROL
jnz lookup_bx
mov bx, drvOffset mpscvwShift
mov dx, drvOffset mpscchShift
test ax, SS_SHIFT
jnz lookup_bx
mov bx, drvOffset mpscvwPlain
mov dx, drvOffset mpscchPlain
lookup_bx:
cCall ChFromSc
cCall VwFromSc
jz done_lookup ;* if (!vw)
cmp bl, VwOfVk(VK_MULTIPLY)
je add_extend
cmp bl, VwOfVk(VK_ADD)
je add_extend
cmp bl, VwOfVk(VK_SUBTRACT)
je add_extend
cmp bl, VwOfVk(VK_DECIMAL)
je add_extend
cmp bl, VwOfVk(VK_NUMPAD0)
je add_extend
cmp bl, VwOfVk(VK_NUMPAD6)
jne done_xlat
add_extend:
or ssOn, SS_EXTENDED
jmp short done_xlat
done_lookup:
;{{ /* Assign VW's to some leftover ascii keys */
; if (vw == 0)
; {
; if (ch >= 'A' && ch <= 'Z')
; vw = VwOfVk(VK_A) + ch - 'A';
; else if (ch >= 'a' && ch <= 'z')
; vw = VwOfVk(VK_A) + ch - 'a';
; else if (ch >= 1 && ch <= 26)
; vw = VwOfVk(VK_A) + ch - 1;
; else if (ch >= '0' && ch <= '9')
; {
; if (sc < SC_NUMBER_MAX)
; vkBase = VK_0;
; else
; vkBase = VK_NUMPAD, ssOn |= SS_EXTENDED;
; vw = VwOfVk(vkBase) + ch - '0';
; }
; else if (ch == ' ')
; vw = 0;
; else if (ch == '.' && sc == SC_DECIMAL)
; vw = VwOfVk(VK_DECIMAL), ssOn |= SS_EXTENDED;
; }
;}}
AssertEQ bl, 0
mov bl, VwOfVk(VK_A) ;* min VW of run
mov al, 'A' ;* min CH
cmp cl, al
jb not_upper
cmp cl, 'Z' ;* max CH
jna assign_vw
not_upper:
mov al, 'a'
cmp cl, al
jb not_lower
cmp cl, 'z'
jna assign_vw
not_lower:
mov al, 1
cmp cl, al
jb not_ctrl
cmp cl, 26
jna assign_vw
not_ctrl:
mov bl, VwOfVk(VK_0)
mov al, '0'
cmp cl, al
jb not_number
cmp cl, '9'
ja not_number
Assert SC_NUMBER_MAX LT SC_NUMPAD_MIN
cmp ch, SC_NUMBER_MAX
jb assign_vw
mov bl, VwOfVk(VK_NUMPAD0)
or ssOn, SS_EXTENDED
assign_vw:
sub al, cl ;* bl = bl + (cl - al)
sub bl, al ;/* vw += ch - chMin; */
jmp short done_xlat
not_number:
xor bl, bl
cmp cl, ' '
je done_xlat
cmp cx, 562Eh ;* ch = '.', sc = SC_DECIMAL
jne done_xlat
mov bl, VwOfVk(VK_DECIMAL)
or ssOn, SS_EXTENDED
done_xlat: ;* CX == sc:ch, ssTemp == ss, BL = vw
;{{
; ssNew = (ss & ~ssOff) | ssOn;
; DoShift(ssNew);
;}}
mov ax,ssOff
not ax
and ax,ssTemp ;* ss & ~ssOff
or ax,ssOn
push ax ;* save ssNew
pop dx ;* ssNew
;{{
; if (vw | ch)
; {
; /* 1 message for WM_CHAR only !! */
; KeyboardMessage(vw, ch, KkOfSs(ssNew), FALSE);
; }
mov al,bl
or al,cl
jz no_key_event
mov al,ch ;* sc
Assert <?PLM>
push bx ;* vw
xor ch,ch
or cl,cl
jnz we_have_char
;* * no char -- put in the VK
Assert <VwOfVk(155H) EQ 55H>
mov cl,bl
inc ch ;* ch == 1
we_have_char:
push cx ;* ch
cCall KkOfSs, <dx>
push ax
xor bx,bx
push bx ;* FALSE
mov bx,[di].pinkbCur
cCall [bx].lpfnKeyboardMessageInkb
no_key_event:
;{{ /* restore shift states */
; DoShift(ss);
; goto retry_xlating;
;}}
cCall DoShift,<ssTemp>
cEnd XlateKey
;*********************************************************************
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -