;       SCCSID = @(#)subsys.asm 6.4 92/06/08
; ****************************************************************************
; *                                                                          *
; *                       IBM/Microsoft Confidential                         *
; *                                                                          *
; *                 Copyright (c) IBM Corporation  1987, 1990                *
; *                 Copyright (c) Microsoft Corp.  1987, 1990                *
; *                           All Rights Reserved                            *
; *                                                                          *
; ****************************************************************************

;/*********************** START OF SPECIFICATIONS ****************************/
;/*                                                                          */
;/* Source File Name: SUBSYS.ASM                                             */
;/*                                                                          */
;/* Descriptive Name: Change the stack to adhere to the documented stack     */
;/*                    that is expected by an alternate subsystem. Reference */
;/*                    KbdRegister API in OS/2 1.3 Toolkit.                  */
;/*                                                                          */
;/* CopyRight: (c) IBM Corp. 1987, 1992                                      */
;/*                                                                          */
;/* Status: OS/2 Release 2.00                                                */
;/*                                                                          */
;/* Function: This module provides all the required assembler routines for   */
;/*           the router. Its primary purpose is to adjust the stack         */
;/*           before/after the call to the alternate subsystems. This        */
;/*           is required because a specific stack frame was documented      */
;/*           which is impossible to recreate from C.                        */
;/*                                                                          */
;/* Entry Points:                                                            */
;/*               The following are called from ROUTER() in ROUTER.C         */
;/*               --------------------------------------------------         */
;/*               MOUBASESUBSYS - Adjust stack and call Base Mouse Subsystem */
;/*               MOUALTSUBSYS  - Adjust stack and call Alt Mouse Subsystem  */
;/*               KBDBASESUBSYS - Adjust stack and call Base Keyboard Subsys */
;/*               KBDALTSUBSYS  - Adjust stack and call Alt Keyboard Subsys  */
;/*                                                                          */
;/*               The following are called from  KbdGetFocus() and           */
;/*               KbdFreeFocus(), also in ROUTER.C                           */
;/*               --------------------------------------------------         */
;/*               GETFOCUSBASESUBSYS - Adjust stack and call BKS             */
;/*               GETFOCUSALTSUBSYS  - Adjust stack and call AKS             */
;/*               FREEFOCUSBASESUBSYS - Adjust stack and call BKS            */
;/*               FREEFOCUSALTSUBSYS  - Adjust stack and call AKS            */
;/*                                                                          */
;/* External References:                                                     */
;/* Routines:   None.                                                        */
;/*                                                                          */
;/* Data: CDATA is the name of the Global data segment.                      */
;/*       _DATA is the name of the Per Process Instance data segment.        */
;/*                                                                          */
;/* Notes:  The whole reason for this mess, is that someone decided that     */
;/*         the stack frame needed to be documented in 1.x. The stack        */
;/*         frame can be located in the CP reference under the definition    */
;/*         for MouRegister().  Theoretically, the stack only needs to be    */
;/*         adjusted for the registered subsystem calls but, we have found   */
;/*         that a few problems occured when rewriting the code from MASM    */
;/*         to 'C'.  MS Word 5.0, a full screen protect mode app, uses a     */
;/*         128 byte stack which is illegal according to the docs.  We lost  */
;/*         that battle and had to rearange the stack so that their data     */
;/*         didn't get clobered.  Refer to KbdRegister and MouRegister for   */
;/*         FC, Function Code values expected.                               */
;/*                                                                          */
;/*         The stack frame on entry to the Subsystems is as follows:        */
;/*                                                                          */
;/*                    parmx                                                 */
;/*                    parm2                                                 */
;/*                    parm1     parms ...                                   */
;/*                    CS        Applications Code Segment                   */
;/*                    IP          and Instruction Pointer                   */
;/*                    FC        Function Code                               */
;/*                    IP        Instruction Pointer (API entry)             */
;/*                    DS        Applications Data Segment                   */
;/*                    CS        Router() code segment                       */
;/*                    IP          and instruction pointer                   */
;/*                       <----- Stack at Entry point of subsystem           */
;/*                                                                          */
;/*                                                                          */
;/*   Dependencies: C compiler generates the following stack frame on entry  */
;/*                 to router():                                             */
;/*                    pusha                                                 */
;/*                    push ds                                               */
;/*                    push es                                               */
;/*                    mov  bp,sp                                            */
;/*                    sub  sp,2         -  TEMPORARY VARS -                 */
;/*                    mov  ax,CDATA_GROUP                                   */
;/*                    mov  ds,ax                                            */
;/*                                                                          */
;/*                 If the number/size of temporary variables is changed     */
;/*                 in router(), "BASELOCALVARS" needs to be changed.        */
;/*                                                                          */
;/*                 The call to Router() is local from all of the other      */
;/*                 API's with a push of the function code and the return    */
;/*                 IP on the stack.  The Focus API's do not have the return */
;/*                 IP of the calling API on the stack so a place holder is  */
;/*                 put in its place.                                        */
;/*                                                                          */
;/*                 C compiler generates the following stack frame on entry  */
;/*                 to KbdGetFocus() and KbdFreeFocus():                     */
;/*                    pusha                                                 */
;/*                    push ds                                               */
;/*                    push es                                               */
;/*                    mov  bp,sp                                            */
;/*                    sub  sp,6         -  TEMPORARY VARS -                 */
;/*                    mov  ax,CDATA_GROUP                                   */
;/*                    mov  ds,ax                                            */
;/*                                                                          */
;/*                 If the number/size of temporary variables is changed     */
;/*                 in KbdGetFocus() and KbdFreeFocus(), "FOCUSLOCALVARS"    */
;/*                 must be changed.                                         */
;/*                                                                          */
;/*   Restrictions:                                                          */
;/*                                                                          */
;/****************************************************************************/
;/******   C H A N G E       H I S T O R Y   *********************************/
;/*                                                                          */
;/*        MDLL   01/10/94  BJN   Page Tune segments for Merged DLL.         */
;/*                                                                          */
;/*********************** END OF SPECIFICATIONS ******************************/

extrn  _BKS_Addr:FAR                   ; Base Keyboard Subsystem address
extrn  _BMS_Addr:FAR                   ; Base Mouse Subsystem address

.286p

CDATA           EQU     <OS2CHAR>                                       ;MDLL
CDATA           SEGMENT WORD PUBLIC 'FAR_DATA'                          ;MDLL
 _mourout_BASEIP  dw 0                 ;
 _mourout_ALTIP   dw 0                 ;
 _kbdrout_BASEIP  dw 0                 ;
 _kbdrout_ALTIP   dw 0                 ;
CDATA           ENDS

; Define instance data in the proper segment

public _ProcessInitFlag
public _LocalInfo
public _AKS_Addr
public _AMS_Addr
public _getfocus_BASEIP
public _getfocus_BASEDS
public _getfocus_ALTIP
public _getfocus_ALTDS
public _freefocus_BASEIP
public _freefocus_BASEDS
public _freefocus_ALTIP
public _freefocus_ALTDS
public _charin_BASEIP
public _charin_BASEDS
public _charin_ALTIP
public _charin_ALTDS
public _stringin_BASEIP
public _stringin_BASEDS
public _stringin_ALTIP
public _stringin_ALTDS

_DATA           EQU     <OS2CHAR_I>                                     ;MDLL
_DATA           SEGMENT WORD PUBLIC 'FAR_DATA'                          ;MDLL
 _ProcessInitFlag  dw 0                ; Process initialization flag
 _LocalInfo        dd 0                ; Local information segment address
 _AKS_Addr         dd 0                ; Alternate Keyboard Subsystem address
 _AMS_Addr         dd 0                ; Alternate Mouse Subsystem address
 _getfocus_BASEIP  dw 0
 _getfocus_BASEDS  dw 0
 _getfocus_ALTIP   dw 0
 _getfocus_ALTDS   dw 0
 _freefocus_BASEIP dw 0
 _freefocus_BASEDS dw 0
 _freefocus_ALTIP  dw 0
 _freefocus_ALTDS  dw 0
 _charin_BASEIP    dw 0
 _charin_BASEDS    dw 0
 _charin_ALTIP     dw 0
 _charin_ALTDS     dw 0
 _stringin_BASEIP  dw 0
 _stringin_BASEDS  dw 0
 _stringin_ALTIP   dw 0
 _stringin_ALTDS   dw 0
_DATA           ENDS

FC_KBDGETFOCUS         EQU      8      ;Function Code
FC_KBDFREEFOCUS        EQU      9      ;Function Code
FC_KBDCHARIN           EQU      0      ;Function Code
FC_KBDSTRINGIN         EQU      5      ;Function Code
BASELOCALVARS          EQU      2      ;Router() local variables in bytes
FOCUSLOCALVARS         EQU      6      ;KbdGetFocus/KbdFreeFocus
CHARINLOCALVARS        EQU      6      ;KbdCharIn local variables in bytes
STRINGINLOCALVARS      EQU      6      ;KbdStringIn local variables in bytes

_TEXT           EQU     <CTEXT>                                         ;MDLL


CTEXT_TUNE5  SEGMENT byte public 'CODE'                                 ;MDLL
        ASSUME  CS:CTEXT_TUNE5,DS:CDATA,ES:NOTHING,SS:NOTHING           ;MDLL


;/*********************** START OF SPECIFICATIONS ****************************/
;/*                                                                          */
;/* SUBROUTINE NAME: MOUBASESUBSYS                                           */
;/*                                                                          */
;/* FUNCTION: Flushes stack of all C temporary variables and callers saved   */
;/*           registers. Only the caller's DS, function code, near IP to the */
;/*           calling function in API.C and parameters pushed by the caller  */
;/*           will remain on the stack.                                      */
;/*                                                                          */
;/* NOTES:                                                                   */
;/*                                                                          */
;/* ENTRY POINT: MOUBASESUBSYS()                                             */
;/*     LINKAGE: CALL NEAR from router                                       */
;/*                                                                          */
;/* INPUT: None                                                              */
;/*                                                                          */
;/* EXIT-NORMAL: None                                                        */
;/*                                                                          */
;/* EXIT-ERROR: None                                                         */
;/*                                                                          */
;/* ASSUMPTIONS:  That caller is a _saveregs function called directly from   */
;/*               an API worker, and the caller isn't using any register     */
;/*               variables or need local variables preserved across this    */
;/*               call.  The caller does not call this service from more     */
;/*               than one place (since we stash the return address in       */
;/*               global data, for convenience).                             */
;/*                                                                          */
;/*********************** END OF SPECIFICATIONS ******************************/

    .386p
    public  _MOUBASESUBSYS             ;declaration for external reference
_MOUBASESUBSYS proc near
    pop     [_mourout_BASEIP]          ;save return address to router()
    mov     sp,bp                      ;throw away local variables
    pop     es                         ;save caller's ES
    pop     ds                         ;save caller's DS
    popa                               ;undo _saveregs prolog (general regs)
    push    ds                         ;restore caller's DS
    push    seg CDATA                  ;set DS to our common data segment
    pop     ds                         ;
    ASSUME  DS:CDATA                   ;

    call    DWORD PTR [_BMS_Addr]

    pop     ds                         ;save caller's DS
    ASSUME  DS:NOTHING                 ;
    pusha                              ;restore _saveregs prolog
    push    ds                         ;restore caller's DS
    push    es                         ;restore ES
    mov     bp,sp                      ;restore stack frame
    sub     sp,BASELOCALVARS           ;restore local variable placement
    push    seg CDATA                  ;set DS to our common data segment
    pop     ds                         ;
    ASSUME  DS:CDATA                   ;
    push    [_mourout_BASEIP]          ;restore return address to mourout()
    ret
_MOUBASESUBSYS endp

;/*********************** START OF SPECIFICATIONS ****************************/
;/*                                                                          */
;/* SUBROUTINE NAME: KBDBASESUBSYS                                           */
;/*                                                                          */
;/* FUNCTION: Flushes stack of all C temporary variables and callers saved   */
;/*           registers. Only the caller's DS, function code, near IP to the */
;/*           calling function in API.C and parameters pushed by the caller  */
;/*           will remain on the stack.                                      */
;/*                                                                          */
;/* NOTES:                                                                   */
;/*                                                                          */
;/* ENTRY POINT: KBDBASESUBSYS()                                             */
;/*     LINKAGE: CALL NEAR from router                                       */
;/*                                                                          */
;/* INPUT: None                                                              */
;/*                                                                          */
;/* EXIT-NORMAL: None                                                        */
;/*                                                                          */
;/* EXIT-ERROR: None                                                         */
;/*                                                                          */
;/* ASSUMPTIONS:  That caller is a _saveregs function called directly from   */
;/*               an API worker, and the caller isn't using any register     */
;/*               variables or need local variables preserved across this    */
;/*               call.  The caller does not call this service from more     */
;/*               than one place (since we stash the return address in       */
;/*               global data, for convenience).                             */
;/*                                                                          */
;/*********************** END OF SPECIFICATIONS ******************************/

    public  _KBDBASESUBSYS             ;declaration for external reference
_KBDBASESUBSYS proc near
    pop     [_kbdrout_BASEIP]          ;save return address to router()
    mov     sp,bp                      ;throw away local variables
    pop     es                         ;save caller's ES
    pop     ds                         ;save caller's DS
    popa                               ;undo _saveregs prolog (general regs)
    push    ds                         ;restore caller's DS
    mov     ax,CDATA                   ;set DS to our common data segment
    mov     ds,ax                      ;
    ASSUME  DS:CDATA                   ;

    call    DWORD PTR [_BKS_Addr]

    pop     ds                         ;save caller's DS
    ASSUME  DS:NOTHING                 ;
    pusha                              ;restore _saveregs prolog
    push    ds                         ;restore caller's DS
    push    es                         ;restore ES
    mov     bp,sp                      ;restore stack frame
    sub     sp,BASELOCALVARS           ;restore local variable placement
    push    seg CDATA                  ;set DS to our common data segment
    pop     ds                         ;
    ASSUME  DS:CDATA                   ;
    push    [_kbdrout_BASEIP]          ;restore return address to mourout()
    ret
_KBDBASESUBSYS endp

CTEXT_TUNE5   ENDS                                                      ;MDLL


_TEXT   SEGMENT byte public 'CODE'  USE16                               ;MDLL
        ASSUME  CS:_TEXT,DS:CDATA,ES:NOTHING,SS:NOTHING                 ;MDLL


;/*********************** START OF SPECIFICATIONS ****************************/
;/*                                                                          */
;/* SUBROUTINE NAME: MOUALTSUBSYS                                            */
;/*                                                                          */
;/* FUNCTION: Replaces stack with all C temporary variables and callers      */
;/*           saved registers.                                               */
;/*                                                                          */
;/* NOTES:                                                                   */
;/*                                                                          */
;/* ENTRY POINT: MOUALTSUBSYS()                                              */
;/*     LINKAGE: CALL NEAR from router                                       */
;/*                                                                          */
;/* INPUT: None                                                              */
;/*                                                                          */
;/* EXIT-NORMAL: None                                                        */
;/*                                                                          */
;/* EXIT-ERROR: None                                                         */
;/*                                                                          */
;/* ASSUMPTIONS:  That caller is a _saveregs function called directly from   */
;/*               an API worker, and the caller isn't using any register     */
;/*               variables or need local variables preserved across this    */
;/*               call.  The caller does not call this service from more     */
;/*               than one place (since we stash the return address in       */
;/*               global data, for convenience).                             */
;/*                                                                          */
;/*********************** END OF SPECIFICATIONS ******************************/

    public  _MOUALTSUBSYS              ;declaration for external reference
_MOUALTSUBSYS proc near
    pop     [_mourout_ALTIP]           ;save return address to router()
    mov     sp,bp                      ;throw away local variables
    pop     es                         ;save caller's ES
    pop     ds                         ;save caller's DS
    popa                               ;undo _saveregs prolog (general regs)
    push    ds                         ;restore caller's DS
    push    seg _DATA                  ;set DS to our common data segment
    pop     ds                         ;
    ASSUME  DS:_DATA                   ;

    call    [_AMS_Addr]

    pop     ds                         ;save caller's DS
    ASSUME  DS:NOTHING                 ;
    pusha                              ;restore _saveregs prolog
    push    ds                         ;restore caller's DS
    push    es                         ;restore ES
    mov     bp,sp                      ;restore stack frame
    sub     sp,BASELOCALVARS           ;restore local variable placement
    push    seg CDATA                  ;set DS to our common data segment
    pop     ds                         ;
    ASSUME  DS:CDATA                   ;
    push    [_mourout_ALTIP]           ;restore return address to mourout()
    ret

_MOUALTSUBSYS endp

;/*********************** START OF SPECIFICATIONS ****************************/
;/*                                                                          */
;/* SUBROUTINE NAME: KBDALTSUBSYS                                            */
;/*                                                                          */
;/* FUNCTION: Replaces stack with all C temporary variables and callers      */
;/*           saved registers.                                               */
;/*                                                                          */
;/* NOTES:                                                                   */
;/*                                                                          */
;/* ENTRY POINT: KBDALTSUBSYS()                                              */
;/*     LINKAGE: CALL NEAR from router                                       */
;/*                                                                          */
;/* INPUT: None                                                              */
;/*                                                                          */
;/* EXIT-NORMAL: None                                                        */
;/*                                                                          */
;/* EXIT-ERROR: None                                                         */
;/*                                                                          */
;/* ASSUMPTIONS:  That caller is a _saveregs function called directly from   */
;/*               an API worker, and the caller isn't using any register     */
;/*               variables or need local variables preserved across this    */
;/*               call.  The caller does not call this service from more     */
;/*               than one place (since we stash the return address in       */
;/*               global data, for convenience).                             */
;/*                                                                          */
;/*********************** END OF SPECIFICATIONS ******************************/

    public  _KBDALTSUBSYS              ;declaration for external reference
_KBDALTSUBSYS proc near
    pop     [_kbdrout_ALTIP]           ;save return address to router()
    mov     sp,bp                      ;throw away local variables
    pop     es                         ;save caller's ES
    pop     ds                         ;save caller's DS
    popa                               ;undo _saveregs prolog (general regs)
    push    ds                         ;restore caller's DS
    mov     ax,_DATA                   ;set DS to our common data segment
    mov     ds,ax                      ;
    ASSUME  DS:_DATA                   ;

    call    [_AKS_Addr]

    pop     ds                         ;save caller's DS
    ASSUME  DS:NOTHING                 ;
    pusha                              ;restore _saveregs prolog
    push    ds                         ;restore caller's DS
    push    es                         ;restore ES
    mov     bp,sp                      ;restore stack frame
    sub     sp,BASELOCALVARS           ;restore local variable placement
    push    seg CDATA                  ;set DS to our common data segment
    pop     ds                         ;
    ASSUME  DS:CDATA                   ;
    push    [_kbdrout_ALTIP]           ;restore return address to mourout()
    ret

_KBDALTSUBSYS endp

;/*********************** START OF SPECIFICATIONS ****************************/
;/*                                                                          */
;/* SUBROUTINE NAME: GETFOCUSBASESUBSYS                                      */
;/*                                                                          */
;/* FUNCTION: Flushes stack of all C temporary variables and callers saved   */
;/*           registers. Only the caller's DS, function code, and parameters */
;/*           to the KBDGETFOCUS remain on the stack.  The call is then      */
;/*           routed to the Base Keyboard Subsystem.                         */
;/*                                                                          */
;/* NOTES:                                                                   */
;/*                                                                          */
;/* ENTRY POINT: GETFOCUSBASESUBSYS()                                        */
;/*     LINKAGE: CALL NEAR from KbdGetFocus()                                */
;/*                                                                          */
;/* INPUT: None                                                              */
;/*                                                                          */
;/* EXIT-NORMAL: None                                                        */
;/*                                                                          */
;/* EXIT-ERROR: None                                                         */
;/*                                                                          */
;/* ASSUMPTIONS:  That caller is a _saveregs function called directly from   */
;/*               an API worker, and the caller isn't using any register     */
;/*               variables or need local variables preserved across this    */
;/*               call.  The caller does not call this service from more     */
;/*               than one place (since we stash the return address in       */
;/*               global data, for convenience).                             */
;/*                                                                          */
;/*********************** END OF SPECIFICATIONS ******************************/

    public  _GETFOCUSBASESUBSYS        ;declaration for external reference
_GETFOCUSBASESUBSYS proc near
    push    seg _DATA                  ;set DS to our instance data segment
    pop     ds                         ;
    ASSUME  DS:_DATA                   ;
    pop     [_getfocus_BASEIP]         ;save return address to API
    mov     sp,bp                      ;throw away local variables
    pop     es                         ;save caller's ES
    pop     [_getfocus_BASEDS]         ;save caller's DS
    popa                               ;undo _saveregs prolog (general regs)
    push    FC_KBDGETFOCUS             ;push Function Code on stack
    push    0                          ;create dummy near IP
    push    [_getfocus_BASEDS]         ;restore callers DS
    push    seg CDATA                  ;set DS to our common data segment
    pop     ds                         ;
    ASSUME  DS:CDATA                   ;

    call    DWORD PTR [_BKS_Addr]

    pop     ds                         ;save caller's DS
    ASSUME  DS:NOTHING                 ;
    add     sp,4                       ;undo dummy near IP and Function Code
    pusha                              ;restore _saveregs prolog
    push    ds                         ;restore caller's DS
    push    es                         ;restore ES
    mov     bp,sp                      ;restore stack frame
    push    seg _DATA                  ;set DS to our instance data segment
    pop     ds                         ;
    ASSUME  DS:_DATA                   ;
    sub     sp,FOCUSLOCALVARS          ;restore local variable placement
    push    [_getfocus_BASEIP]         ;restore return address to API
    push    seg CDATA
    pop     ds
    ASSUME  DS:CDATA                   ;reload common data segment
    ret
_GETFOCUSBASESUBSYS endp


;/*********************** START OF SPECIFICATIONS ****************************/
;/*                                                                          */
;/* SUBROUTINE NAME: GETFOCUSALTSUBSYS                                       */
;/*                                                                          */
;/* FUNCTION: Flushes stack of all C temporary variables and callers saved   */
;/*           registers. Only the caller's DS, function code, and parameters */
;/*           to the KBDGETFOCUS remain on the stack.  The call is then      */
;/*           routed to the Alternate Keyboard Subsystem.                    */
;/*                                                                          */
;/* NOTES:                                                                   */
;/*                                                                          */
;/* ENTRY POINT: GETFOCUSALTSUBSYS()                                         */
;/*     LINKAGE: CALL NEAR from KbdGetFocus()                                */
;/*                                                                          */
;/* INPUT: None                                                              */
;/*                                                                          */
;/* EXIT-NORMAL: None                                                        */
;/*                                                                          */
;/* EXIT-ERROR: None                                                         */
;/*                                                                          */
;/* ASSUMPTIONS:  That caller is a _saveregs function called directly from   */
;/*               an API worker, and the caller isn't using any register     */
;/*               variables or need local variables preserved across this    */
;/*               call.  The caller does not call this service from more     */
;/*               than one place (since we stash the return address in       */
;/*               global data, for convenience).                             */
;/*                                                                          */
;/*********************** END OF SPECIFICATIONS ******************************/

    public  _GETFOCUSALTSUBSYS         ;declaration for external reference
_GETFOCUSALTSUBSYS proc near
    push    seg _DATA
    pop     ds
    ASSUME  DS:_DATA                   ;
    pop     [_getfocus_ALTIP]          ;save return address to API
    mov     sp,bp                      ;throw away local variables
    pop     es                         ;save caller's ES
    pop     [_getfocus_ALTDS]          ;save caller's DS
    popa                               ;undo _saveregs prolog (general regs)
    push    FC_KBDGETFOCUS             ;push Function Code on stack
    push    0                          ;create dummy near IP
    push    [_getfocus_ALTDS]          ;restore callers DS
    push    seg _DATA                  ;set DS to our instance data segment
    pop     ds                         ;
    ASSUME  DS:_DATA                   ;

    call    [_AKS_Addr]

    pop     ds                         ;save caller's DS
    ASSUME  DS:NOTHING                 ;
    add     sp,4                       ;undo dummy near IP and Function Code
    pusha                              ;restore _saveregs prolog
    push    ds                         ;restore caller's DS
    push    es                         ;restore ES
    mov     bp,sp                      ;restore stack frame
    push    seg _DATA                  ;set DS to our instance data segment
    pop     ds                         ;
    ASSUME  DS:_DATA                   ;
    sub     sp,FOCUSLOCALVARS          ;restore local variable placement
    push    [_getfocus_ALTIP]          ;restore return address to API
    push    seg CDATA
    pop     ds
    ASSUME  DS:CDATA                   ;reload common data segment
    ret
_GETFOCUSALTSUBSYS endp

;/*********************** START OF SPECIFICATIONS ****************************/
;/*                                                                          */
;/* SUBROUTINE NAME: FREEFOCUSBASESUBSYS                                      */
;/*                                                                          */
;/* FUNCTION: Flushes stack of all C temporary variables and callers saved   */
;/*           registers. Only the caller's DS, function code, and parameters */
;/*           to the KBDFREEFOCUS remain on the stack.  The call is then     */
;/*           routed to the Base Keyboard Subsystem.                         */
;/*                                                                          */
;/* NOTES:                                                                   */
;/*                                                                          */
;/* ENTRY POINT: FREEFOCUSBASESUBSYS()                                       */
;/*     LINKAGE: CALL NEAR from KbdFreeFocus                                 */
;/*                                                                          */
;/* INPUT: None                                                              */
;/*                                                                          */
;/* EXIT-NORMAL: None                                                        */
;/*                                                                          */
;/* EXIT-ERROR: None                                                         */
;/*                                                                          */
;/* ASSUMPTIONS:  That caller is a _saveregs function called directly from   */
;/*               an API worker, and the caller isn't using any register     */
;/*               variables or need local variables preserved across this    */
;/*               call.  The caller does not call this service from more     */
;/*               than one place (since we stash the return address in       */
;/*               global data, for convenience).                             */
;/*                                                                          */
;/*********************** END OF SPECIFICATIONS ******************************/

    public  _FREEFOCUSBASESUBSYS       ;declaration for external reference
_FREEFOCUSBASESUBSYS proc near
    push    seg _DATA                  ;set DS to our instance data segment
    pop     ds                         ;
    ASSUME  DS:_DATA                   ;
    pop     [_freefocus_BASEIP]        ;save return address to API
    mov     sp,bp                      ;throw away local variables
    pop     es                         ;save caller's ES
    pop     [_freefocus_BASEDS]        ;save caller's DS
    popa                               ;undo _saveregs prolog (general regs)
    push    FC_KBDFREEFOCUS            ;push Function Code on stack
    push    0                          ;create dummy near IP
    push    [_freefocus_BASEDS]        ;restore callers DS
    push    seg CDATA                  ;set DS to our common data segment
    pop     ds                         ;
    ASSUME  DS:CDATA                   ;

    call    DWORD PTR [_BKS_Addr]

    pop     ds                         ;save caller's DS
    ASSUME  DS:NOTHING                 ;
    add     sp,4                       ;undo dummy near IP and Function Code
    pusha                              ;restore _saveregs prolog
    push    ds                         ;restore caller's DS
    push    es                         ;restore ES
    mov     bp,sp                      ;restore stack frame
    push    seg _DATA                  ;set DS to our instance data segment
    pop     ds                         ;
    ASSUME  DS:_DATA                   ;
    sub     sp,FOCUSLOCALVARS          ;restore local variable placement
    push    [_freefocus_BASEIP]        ;restore return address to API
    push    seg CDATA
    pop     ds
    ASSUME  DS:CDATA                   ;reload common data segment
    ret
_FREEFOCUSBASESUBSYS endp


;/*********************** START OF SPECIFICATIONS ****************************/
;/*                                                                          */
;/* SUBROUTINE NAME: FREEFOCUSALTSUBSYS                                       */
;/*                                                                          */
;/* FUNCTION: Flushes stack of all C temporary variables and callers saved   */
;/*           registers. Only the caller's DS, function code, and parameters */
;/*           to the MOUCALLS API remain on the stack.  The call is then     */
;/*           routed to the Alternate Keyboard Subsystem.                    */
;/*                                                                          */
;/* NOTES:                                                                   */
;/*                                                                          */
;/* ENTRY POINT: FREEFOCUSALTSUBSYS()                                         */
;/*     LINKAGE: CALL NEAR from KbdSetFocus(), KbdFreeFocus(), KbdCharIn(),  */
;/*              and KbdStringIn().                                          */
;/*                                                                          */
;/* INPUT: None                                                              */
;/*                                                                          */
;/* EXIT-NORMAL: None                                                        */
;/*                                                                          */
;/* EXIT-ERROR: None                                                         */
;/*                                                                          */
;/* ASSUMPTIONS:  That caller is a _saveregs function called directly from   */
;/*               an API worker, and the caller isn't using any register     */
;/*               variables or need local variables preserved across this    */
;/*               call.  The caller does not call this service from more     */
;/*               than one place (since we stash the return address in       */
;/*               global data, for convenience).                             */
;/*                                                                          */
;/*********************** END OF SPECIFICATIONS ******************************/

    public  _FREEFOCUSALTSUBSYS         ;declaration for external reference
_FREEFOCUSALTSUBSYS proc near
    push    seg _DATA
    pop     ds
    ASSUME  DS:_DATA                   ;
    pop     [_freefocus_ALTIP]         ;save return address to API
    mov     sp,bp                      ;throw away local variables
    pop     es                         ;save caller's ES
    pop     [_freefocus_ALTDS]         ;save caller's DS
    popa                               ;undo _saveregs prolog (general regs)
    push    FC_KBDFREEFOCUS            ;push Function Code on stack
    push    0                          ;create dummy near IP
    push    [_freefocus_ALTDS]         ;restore callers DS
    push    seg _DATA                  ;set DS to our instance data segment
    pop     ds                         ;
    ASSUME  DS:_DATA                   ;

    call    [_AKS_Addr]

    pop     ds                         ;save caller's DS
    ASSUME  DS:NOTHING                 ;
    add     sp,4                       ;undo dummy near IP and Function Code
    pusha                              ;restore _saveregs prolog
    push    ds                         ;restore caller's DS
    push    es                         ;restore ES
    mov     bp,sp                      ;restore stack frame
    push    seg _DATA                  ;set DS to our instance data segment
    pop     ds                         ;
    ASSUME  DS:_DATA                   ;
    sub     sp,FOCUSLOCALVARS          ;restore local variable placement
    push    [_freefocus_ALTIP]         ;restore return address to API
    push    seg CDATA
    pop     ds
    ASSUME  DS:CDATA                   ;reload common data segment
    ret
_FREEFOCUSALTSUBSYS endp

;/*********************** START OF SPECIFICATIONS ****************************/
;/*                                                                          */
;/* SUBROUTINE NAME: CHARINBASESUBSYS                                        */
;/*                                                                          */
;/* FUNCTION: Flushes stack of all C temporary variables and callers saved   */
;/*           registers. Only the caller's DS, function code, and parameters */
;/*           to the KBDCHARIN remain on the stack.  The call is then        */
;/*           routed to the Base Keyboard Subsystem.                         */
;/*                                                                          */
;/* NOTES:                                                                   */
;/*                                                                          */
;/* ENTRY POINT: CHARINBASESUBSYS()                                         */
;/*     LINKAGE: CALL NEAR from KbdCharIn                                    */
;/*                                                                          */
;/* INPUT: None                                                              */
;/*                                                                          */
;/* EXIT-NORMAL: None                                                        */
;/*                                                                          */
;/* EXIT-ERROR: None                                                         */
;/*                                                                          */
;/* ASSUMPTIONS:  That caller is a _saveregs function called directly from   */
;/*               an API worker, and the caller isn't using any register     */
;/*               variables or need local variables preserved across this    */
;/*               call.  The caller does not call this service from more     */
;/*               than one place (since we stash the return address in       */
;/*               global data, for convenience).                             */
;/*                                                                          */
;/*********************** END OF SPECIFICATIONS ******************************/

    public  _CHARINBASESUBSYS          ;declaration for external reference
_CHARINBASESUBSYS proc near
    push    seg _DATA                  ;set DS to our instance data segment
    pop     ds                         ;
    ASSUME  DS:_DATA                   ;
    pop     [_charin_BASEIP]           ;save return address to API
    mov     sp,bp                      ;throw away local variables
    pop     es                         ;save caller's ES
    pop     [_charin_BASEDS]           ;save caller's DS
    popa                               ;undo _saveregs prolog (general regs)
    push    FC_KBDCHARIN               ;push Function Code on stack
    push    0                          ;create dummy near IP
    push    [_charin_BASEDS]           ;restore callers DS
    push    seg CDATA                  ;set DS to our common data segment
    pop     ds                         ;
    ASSUME  DS:CDATA                   ;

    call    DWORD PTR [_BKS_Addr]

    pop     ds                         ;save caller's DS
    ASSUME  DS:NOTHING                 ;
    add     sp,4                       ;undo dummy near IP and Function Code
    pusha                              ;restore _saveregs prolog
    push    ds                         ;restore caller's DS
    push    es                         ;restore ES
    mov     bp,sp                      ;restore stack frame
    push    seg _DATA                  ;set DS to our instance data segment
    pop     ds                         ;
    ASSUME  DS:_DATA                   ;
    sub     sp,CHARINLOCALVARS         ;restore local variable placement
    push    [_charin_BASEIP]           ;restore return address to API
    push    seg CDATA
    pop     ds
    ASSUME  DS:CDATA                   ;reload common data segment
    ret
_CHARINBASESUBSYS endp


;/*********************** START OF SPECIFICATIONS ****************************/
;/*                                                                          */
;/* SUBROUTINE NAME: CHARINALTSUBSYS                                         */
;/*                                                                          */
;/* FUNCTION: Flushes stack of all C temporary variables and callers saved   */
;/*           registers. Only the caller's DS, function code, and parameters */
;/*           to the KBDCALLS API remain on the stack.  The call is then     */
;/*           routed to the Alternate Keyboard Subsystem.                    */
;/*                                                                          */
;/* NOTES:                                                                   */
;/*                                                                          */
;/* ENTRY POINT: CHARINALTSUBSYS()                                           */
;/*     LINKAGE: CALL NEAR from KbdCharin()                                  */
;/*                                                                          */
;/* INPUT: None                                                              */
;/*                                                                          */
;/* EXIT-NORMAL: None                                                        */
;/*                                                                          */
;/* EXIT-ERROR: None                                                         */
;/*                                                                          */
;/* ASSUMPTIONS:  That caller is a _saveregs function called directly from   */
;/*               an API worker, and the caller isn't using any register     */
;/*               variables or need local variables preserved across this    */
;/*               call.  The caller does not call this service from more     */
;/*               than one place (since we stash the return address in       */
;/*               global data, for convenience).                             */
;/*                                                                          */
;/*********************** END OF SPECIFICATIONS ******************************/

    public  _CHARINALTSUBSYS           ;declaration for external reference
_CHARINALTSUBSYS proc near
    push    seg _DATA
    pop     ds
    ASSUME  DS:_DATA                   ;
    pop     [_charin_ALTIP]            ;save return address to API
    mov     sp,bp                      ;throw away local variables
    pop     es                         ;save caller's ES
    pop     [_charin_ALTDS]            ;save caller's DS
    popa                               ;undo _saveregs prolog (general regs)
    push    FC_KBDCHARIN               ;push Function Code on stack
    push    0                          ;create dummy near IP
    push    [_charin_ALTDS]            ;restore callers DS
    push    seg _DATA                  ;set DS to our instance data segment
    pop     ds                         ;
    ASSUME  DS:_DATA                   ;

    call    [_AKS_Addr]

    pop     ds                         ;save caller's DS
    ASSUME  DS:NOTHING                 ;
    add     sp,4                       ;undo dummy near IP and Function Code
    pusha                              ;restore _saveregs prolog
    push    ds                         ;restore caller's DS
    push    es                         ;restore ES
    mov     bp,sp                      ;restore stack frame
    push    seg _DATA                  ;set DS to our instance data segment
    pop     ds                         ;
    ASSUME  DS:_DATA                   ;
    sub     sp,CHARINLOCALVARS         ;restore local variable placement
    push    [_charin_ALTIP]            ;restore return address to API
    push    seg CDATA
    pop     ds
    ASSUME  DS:CDATA                   ;reload common data segment
    ret
_CHARINALTSUBSYS endp

;/*********************** START OF SPECIFICATIONS ****************************/
;/*                                                                          */
;/* SUBROUTINE NAME: STRINGINBASESUBSYS                                      */
;/*                                                                          */
;/* FUNCTION: Flushes stack of all C temporary variables and callers saved   */
;/*           registers. Only the caller's DS, function code, and parameters */
;/*           to KbdStringIn() remain on the stack.  The call is then        */
;/*           routed to the Base Keyboard Subsystem.                         */
;/*                                                                          */
;/* NOTES:                                                                   */
;/*                                                                          */
;/* ENTRY POINT: STRINGINBASESUBSYS()                                        */
;/*     LINKAGE: CALL NEAR from KbdStringIn                                  */
;/*                                                                          */
;/* INPUT: None                                                              */
;/*                                                                          */
;/* EXIT-NORMAL: None                                                        */
;/*                                                                          */
;/* EXIT-ERROR: None                                                         */
;/*                                                                          */
;/* ASSUMPTIONS:  That caller is a _saveregs function called directly from   */
;/*               an API worker, and the caller isn't using any register     */
;/*               variables or need local variables preserved across this    */
;/*               call.  The caller does not call this service from more     */
;/*               than one place (since we stash the return address in       */
;/*               global data, for convenience).                             */
;/*                                                                          */
;/*********************** END OF SPECIFICATIONS ******************************/

    public  _STRINGINBASESUBSYS        ;declaration for external reference
_STRINGINBASESUBSYS proc near
    push    seg _DATA                  ;set DS to our instance data segment
    pop     ds                         ;
    ASSUME  DS:_DATA                   ;
    pop     [_stringin_BASEIP]         ;save return address to API
    mov     sp,bp                      ;throw away local variables
    pop     es                         ;save caller's ES
    pop     [_stringin_BASEDS]         ;save caller's DS
    popa                               ;undo _saveregs prolog (general regs)
    push    FC_KBDSTRINGIN             ;push Function Code on stack
    push    0                          ;create dummy near IP
    push    [_stringin_BASEDS]         ;restore callers DS
    push    seg CDATA                  ;set DS to our common data segment
    pop     ds                         ;
    ASSUME  DS:CDATA                   ;

    call    DWORD PTR [_BKS_Addr]

    pop     ds                         ;save caller's DS
    ASSUME  DS:NOTHING                 ;
    add     sp,4                       ;undo dummy near IP and Function Code
    pusha                              ;restore _saveregs prolog
    push    ds                         ;restore caller's DS
    push    es                         ;restore ES
    mov     bp,sp                      ;restore stack frame
    push    seg _DATA                  ;set DS to our instance data segment
    pop     ds                         ;
    ASSUME  DS:_DATA                   ;
    sub     sp,STRINGINLOCALVARS       ;restore local variable placement
    push    [_stringin_BASEIP]         ;restore return address to API
    push    seg CDATA
    pop     ds
    ASSUME  DS:CDATA                   ;reload common data segment
    ret
_STRINGINBASESUBSYS endp


;/*********************** START OF SPECIFICATIONS ****************************/
;/*                                                                          */
;/* SUBROUTINE NAME: STRINGINALTSUBSYS                                       */
;/*                                                                          */
;/* FUNCTION: Flushes stack of all C temporary variables and callers saved   */
;/*           registers. Only the caller's DS, function code, and parameters */
;/*           to KbdStringIn() remain on the stack.  The call is then        */
;/*           routed to the Alternate Keyboard Subsystem.                    */
;/*                                                                          */
;/* NOTES:                                                                   */
;/*                                                                          */
;/* ENTRY POINT: STRINGINALTSUBSYS()                                         */
;/*     LINKAGE: CALL NEAR from KbdStringin()                                */
;/*                                                                          */
;/* INPUT: None                                                              */
;/*                                                                          */
;/* EXIT-NORMAL: None                                                        */
;/*                                                                          */
;/* EXIT-ERROR: None                                                         */
;/*                                                                          */
;/* ASSUMPTIONS:  That caller is a _saveregs function called directly from   */
;/*               an API worker, and the caller isn't using any register     */
;/*               variables or need local variables preserved across this    */
;/*               call.  The caller does not call this service from more     */
;/*               than one place (since we stash the return address in       */
;/*               global data, for convenience).                             */
;/*                                                                          */
;/*********************** END OF SPECIFICATIONS ******************************/

    public  _STRINGINALTSUBSYS         ;declaration for external reference
_STRINGINALTSUBSYS proc near
    push    seg _DATA
    pop     ds
    ASSUME  DS:_DATA                   ;
    pop     [_stringin_ALTIP]          ;save return address to API
    mov     sp,bp                      ;throw away local variables
    pop     es                         ;save caller's ES
    pop     [_stringin_ALTDS]          ;save caller's DS
    popa                               ;undo _saveregs prolog (general regs)
    push    FC_KBDSTRINGIN             ;push Function Code on stack
    push    0                          ;create dummy near IP
    push    [_stringin_ALTDS]          ;restore callers DS
    push    seg _DATA                  ;set DS to our instance data segment
    pop     ds                         ;
    ASSUME  DS:_DATA                   ;

    call    [_AKS_Addr]

    pop     ds                         ;save caller's DS
    ASSUME  DS:NOTHING                 ;
    add     sp,4                       ;undo dummy near IP and Function Code
    pusha                              ;restore _saveregs prolog
    push    ds                         ;restore caller's DS
    push    es                         ;restore ES
    mov     bp,sp                      ;restore stack frame
    push    seg _DATA                  ;set DS to our instance data segment
    pop     ds                         ;
    ASSUME  DS:_DATA                   ;
    sub     sp,STRINGINLOCALVARS       ;restore local variable placement
    push    [_stringin_ALTIP]          ;restore return address to API
    push    seg CDATA
    pop     ds
    ASSUME  DS:CDATA                   ;reload common data segment
    ret
_STRINGINALTSUBSYS endp

_TEXT   ENDS
        END
