;       SCCSID = @(#)bksfree.asm	6.1 90/11/16
;       SCCSID = @(#)bksfree.asm	6.5 90/02/14
; ****************************************************************************
; *                                                                          *
; *                       IBM/Microsoft Confidential                         *
; *                                                                          *
; *                 Copyright (c) IBM Corporation  1987, 1990                *
; *                 Copyright (c) Microsoft Corp.  1987, 1990                *
; *                           All Rights Reserved                            *
; *                                                                          *
; ****************************************************************************
        PAGE    60,132
        TITLE   BKSFREE.ASM - Release Logical to Physical Bond

;******************************************************************************
;*******   C H A N G E       H I S T O R Y   **********************************
;
;       86/12/05  TPL   Reset KCB back to session default by passing handle 0.
;                       Issue KBDSETXT instead when restoring translation
;                       table.
;       86/12/11  TPL   Change KBDSETXT to KBDSETCP
;       87/07/06  TPL   Call DosEnterCritSec and DosExitCritSec to bracket
;                       critical section.
;@T52   90/01/15  TPL   DCR 704 work
;******************************************************************************

        .286p                           ; 286 Protect Mode instructions

        .xlist
        INCLUDE error2.inc              ; Extended error code file
        INCLUDE struc.inc               ; Structured Macros
        INCLUDE bksxxx.inc              ; Equates and structure template file
        INCLUDE bksextrn.inc            ; External data declaration file
        .list

CSEG    SEGMENT BYTE PUBLIC 'CODE'
CSEG    ENDS

IDSEG   SEGMENT BYTE PUBLIC 'DATA'      ; Per process data segment
IDSEG   ENDS
;
;       System services routine name(s)
;
        EXTRN   DOSDEVIOCTL:FAR         ; Set codepage
        EXTRN   KBDFLUSHBUFFER:FAR      ; Empty KIB
        EXTRN   KBDSETCP:FAR            ; Change codepage
        EXTRN   DOSENTERCRITSEC:FAR     ; Enter critical section
        EXTRN   DOSEXITCRITSEC:FAR      ; Exit critical section

;$$#I000
        EXTRN WINCONSOLEFREEFOCUS:DWORD ;CDB2
        GDSEG SEGMENT BYTE PUBLIC 'FAR_DATA'                            ;@T52
        GDSEG ENDS
;$$#END

        PUBLIC  FreeFocus


CSEG    SEGMENT BYTE PUBLIC 'CODE'
        ASSUME  CS:CSEG,DS:NOTHING,ES:NOTHING
        PAGE

;/*********************** START OF SPECIFICATIONS ***************************/
;/* SUBROUTINE NAME: FreeFocus                                              */
;/*                                                                         */
;/* DESCRIPTIVE NAME: BKS function for KBDFREEFOCUS                         */
;/*                                                                         */
;/* FUNCTION: Unbind the logical keyboard from the physical keyboard.       */
;/*                                                                         */
;/* NOTES: Once an unbind occurs, all processes in this screen group        */
;/*        using the default keyboard (handle 0) will be able to receive    */
;/*        keystrokes.  Also, a process blocked waiting to complete         */
;/*        a KBDGETFOCUS call will be unblocked.                            */
;/*                                                                         */
;/* ENTRY POINT: bksfreef                                                   */
;/*     LINKAGE: NEAR CALL  (internal call from BKSMAIN)                    */
;/*                                                                         */
;/* INPUT: push KBDHANDLE - keyboard handle (WORD)                          */
;/*        push callersCS - caller's return CS (WORD)                       */
;/*        push callersIP - caller's return IP (WORD)                       */
;/*        push func_code - KBDXXX function code (WORD)                     */
;/*        push KBDXXX_IP - KBDXXX return IP (WORD)                         */
;/*        push callersDS - caller's DS save area (WORD)                    */
;/*        push kbdroutCS - kbdrout return CS (WORD)                        */
;/*        push kbdroutIP - kbdrout return IP (WORD)                        */
;/*        push BKSMAINIP - BKSMAIN return IP (WORD)                        */
;/*        push DS        - done by BKSMAIN                                 */
;/*        push BP        - done by BKSMAIN                                 */
;/*                                                                         */
;/*        NOTE:  On entry to this routine, it is assumed that DS           */
;/*               has been set to the IDSEG data selector                   */
;/*               by BKSMAIN.                                               */
;/*               Also, it is assumed that BP has been set to the           */
;/*               stack frame (described above) by BKSMAIN.                 */
;/*                                                                         */
;/* EXIT-NORMAL: AX = NO_ERROR                                              */
;/*                                                                         */
;/* EXIT-ERROR: AX = error code from DOSDEVIOCTL                            */
;/*                                                                         */
;/* EFFECTS: Caller's AX is destroyed.                                      */
;/*                                                                         */
;/* INTERNAL                                                                */
;/* REFERENCES: bond_handle - keyboard handle that currently has a bond     */
;/*   ROUTINES: None.                                                       */
;/*                                                                         */
;/* EXTERNAL                                                                */
;/* REFERENCES: None.                                                       */
;/*   ROUTINES: DOSDEVIOCTL    - close device handle                        */
;/*             KBDSETCP       - set translate table                        */
;/*             KBDFLUSHBUFFER - flush keystroke buffer                     */
;/*                                                                         */
;/*********************** END OF SPECIFICATIONS *****************************/
        PAGE



;FreeFocus PSUEDO CODE
;
;************************************************************************
;*  On entry:  DS = IDSEG selector   AX = 0   BX = [bp].KBD_Handle      *
;************************************************************************
;
;.if <[BP].KBD_Handle eq DS:Bond_Handle>; Bond made by this handle?
;|
;| .if <DS:Bond_Handle ne DEFAULT>      ; Non "handle 0" type bond?
;| |  call DOSDEVIOCTL                  ; Reset to session default KCB
;| .elseif <DS:Flag eq CUSTOM_CODEPAGE> ; Bond made on "handle 0" and
;| |                                    ;   custom codepage is in effect?
;| |  call KBDSETCP                     ; Flush keystrokes translated with
;| |                                    ;   the custom codepage
;| |                                    ; Change codepage back to the
;| |                                    ;   last non-custom codepage
;| | .if <AX eq NO_ERROR>
;| | |  DS:Flag <-- NORMAL_CODEPAGE     ; Reset codepage bit to normal
;| | .endif
;| |
;| .endif
;|
;| .if <AX eq NO_ERROR>
;| |  DS:Bond_Handle <-- FREE           ; Reset bond handle to initial state
;| .endif
;|
;.else
;|  AX <-- ERROR_KBD_INVALID_HANDLE     ; Set error return code
;.endif
;
; ret
        PAGE



FreeFocus PROC NEAR                     ; @@ Version 1.1 code - BEGIN
        ASSUME DS:IDSEG
;
;************************************************************************
;*  On entry:  DS = IDSEG   ES = GDSEG  AX = 0   BX = [bp].KBD_Handle   *
;*             DX = KBD_SG                                              *
;************************************************************************
;

       .IF <dx A LastBaseSG>            ; Winthorn screen group
         push   hConsole                ; Free focus
         push   [bp].KBD_Handle         ;
         call   ES:WINCONSOLEFREEFOCUS  ; CDB2
       .ELSE                            ;
         test   Flag,FOCUS_ON           ;
        .if nz  AND                     ; Focus ON and input handle
        .if <bx eq Bond_Handle>         ;   matches Bond Handle!!!
          call  DOSENTERCRITSEC         ;
          or    bx,bx                   ;
         .if nz                         ; Bond made on non-default handle?
           push 0                       ; Address to DATA parmlist
           push 0                       ;
           push es                      ; Address to INPUT parmlist
           push offset KBD_CP0          ;   (handle 0)
           push 57H                     ; Function code (set default KCB)
           push KEYBOARD                ; Category code (KEYBOARD)
           push bx                      ; Device handle
           call DOSDEVIOCTL             ;
         .else                          ; bond made on default handle!!!
           test Flag,CUSTOM_ON          ;
          .if nz                        ; custom codepage in effect?
            push bx                     ; flush keystroke buffer
            call KBDFLUSHBUFFER         ;
            or   ax,ax                  ;
           .if z                        ;
             push ax                    ; reserved parameter
             push Previous_CP           ; previous codepage ID
             push bx                    ; keyboard handle
             call KBDSETCP              ; set translate table
             or   ax,ax                 ;
            .if z                       ;
              and Flag,CUSTOM_OFF       ; mask off custom codepage bit
            .endif                      ;
           .endif                       ;
          .endif                        ;
         .endif                         ;
          or    ax,ax                   ;
         .if z                          ;
           and  Flag,FOCUS_OFF          ; indicate focus OFF
         .endif                         ;
          push  ax                      ; save return code
          call  DOSEXITCRITSEC          ;
          pop   ax                      ; restore return code
        .else                           ;
          mov   ax,ERROR_KBD_INVALID_HANDLE
        .endif                          ;
       .ENDIF                           ;
        ret                             ; near return to BKSMAIN

FreeFocus ENDP                          ; @@ Version 1.1 code - END

CSEG    ENDS
        END
