;/*
; *                      Microsoft Confidential
; *                      Copyright (C) Microsoft Corporation 1991
; *                      All Rights Reserved.
; */
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
;       CODE PAGE DRIVER FUNCTIONS
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
IF1                                     ;
        ;%out .               ®CPS-FUNC.INC¯
ENDIF                                   ;
                                        ;
CP_FUNCTION     LABEL   BYTE            ;
        DW   4CH,OFFSET DESIGNATE_BEGIN ;
        DW   4DH,OFFSET DESIGNATE_END   ;
        DW   4AH,OFFSET INVOKE_CP       ;
        DW   6AH,OFFSET QUERY_CP        ;
        DW   6BH,OFFSET QUERY_CP_LIST   ;
NUM_CP_FUNCTION  EQU ($-CP_FUNCTION)/4  ;
                                        ;
DESG_SEMAPHORE  DB      0               ; TEMPORARY
G_IOCTL_SEMA    DB      0               ; SEMAPHORE TO INDICATE IF CPS IS BUSY!
                                        ;
CHAR_HEIGHT     DB      8               ;
                DB     14               ;
                DB     16               ;
                DB     19               ;
                DB      0               ;
                DB      0               ;
                DB      0               ;
                DB      0               ;
NUM_CHAR_HEIGHT EQU ($-CHAR_HEIGHT)     ;
                                        ;
                                        ;
GENERIC_IOCTL PROC                      ; CON OUTPUT
        CLI                           ;S;
        MOV     SI,SP                 ;S;
        MOV     CS:OLD_STACK_O,SI     ;S;
        MOV     SI,SS                 ;S;
        MOV     CS:OLD_STACK_S,SI     ;S;
        MOV     AX,OFFSET STACK_START ;S;
        MOV     SI,CS                 ;S;
        MOV     SS,SI                 ;S;
        MOV     SP,AX                 ;S;
        STI                           ;S;
        PUSH    DS                      ;
                                        ;
        PUSH    CS                      ;
        POP     DS                      ; FROM HERE IN, DS=CS
                                        ;
        LES     DI,DWORD PTR BUF.RH_PTRO; GET RH
                                        ;
GI_1:   MOV     AL,RH.MINOR_F           ; PUT MINOR VERSION IN AL
        XOR     AH,AH                   ; CLEAR OUT HIGH BYTE FOR COMPARES
                                        ;
        PUSH    DI                      ; SAVE POINTER!!!
        PUSH    ES                      ;
        PUSH    CS                      ;
        POP     ES                      ;
        MOV     CX,NUM_CP_FUNCTION      ;
        MOV     DI,OFFSET CP_FUNCTION   ;
GI_1A:  SCASW                           ; SEARCH THROUGH THE LIST OF VALID FN's
        JE      GI_2                    ;
        INC     DI                      ;
        INC     DI                      ;
        LOOP    GI_1A                   ;
        POP     ES                      ;
        POP     DI                      ;
        jmp     short GI_3                    ; NOT FOUND!
GI_2:   POP     ES                      ;
        MOV     SI,DI                   ;
        POP     DI                      ;
                                        ;
        MOV     G_IOCTL_SEMA,ONE        ; SEMAPHORE TO INDICATE CALLS ARE BUSY!
        CALL    [SI]                    ; JMP OFF TO THE APPROPRIATE CALL!
        MOV     G_IOCTL_SEMA,ZERO       ; SEMAPHORE TO INDICATE CALLS ARE DONE!
        STC                             ; SET CY not TO TRY ATTACHED CON!
        jmp     short GI_4                    ;
GI_3:   CLC                             ; CLEAR CY TO TRY ATTACHED CON!
GI_4:   POP     DS                      ;
        CLI                           ;S;
        MOV     AX,CS:OLD_STACK_O     ;S;
        MOV     SI,CS:OLD_STACK_S     ;S;
        MOV     SS,SI                 ;S;
        MOV     SP,AX                 ;S;
        STI                           ;S;
        RET                             ;
GENERIC_IOCTL ENDP                      ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
;       DESIGNATE BEGIN
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
DESIGNATE_BEGIN PROC                    ;
        LES     DI,RH.REQUEST_PACKET    ; AND DI TO POINT TO REQUEST PACKET
        MOV     CX,RH.DESG_N            ; MOVE THE NUMBER OF CODE PAGES DESIG'ed
                                        ;
        OR      CX,CX                   ;
        JZ      DB_0C                   ; CHECK IF ZERO CP's DESIGNATED
                                        ; IF SO, THEN THIS IS THE REFRESH CALL
DB_0:   CMP     CX,CPD_DESG_N           ; CHECK IF NUMBER > # CONFIGed
        JA      DB_0B                   ;
        jmp     short DB_1B                   ;
                                        ;
DB_0D:  OR      BUF.STATUS,EIGHT        ; Error>> KEYBOARD ERROR!!
        RET                             ;
DB_2D:  POP     CX                      ; RESTORE STACK ELEMENTS
        POP     BX                      ;
        POP     CX                      ; RESTORE STACK ELEMENTS
        POP     BX                      ;
DB_0B:  OR      BUF.STATUS,TEN          ; Error>> DEVICE ERROR!!
        RET                             ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
;       REFRESH ACTIVE CODE PAGE TO DISPLAY
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
DB_0C:  MOV     DESG_SEMAPHORE,TWO      ; SET REFRESH COMMENCED
        MOV     CPD_REQ_DESG,CX         ; SAVE NUMBER OF REQUESTED CP'S (0)
        MOV     DX,CPD_ACTIVE           ; THIS IS THE REFRESH CALL
        CMP     DX,-1                   ; CHECK IF THE ACTIVE_CP = INVALID
        JE      DB_0B                   ;
        CLC                             ; CLEAR OUT THE CARRY FLAG
        CALL    SIGNAL_KBD_INVK         ;
        JC      DB_0D                   ; IF CY SET, THEN KEYBOARD IS WRONG
        CALL    TEST_CP                 ;
        JC      DB_0B                   ;
        CALL    INVOKE_DATA             ;
        JC      DB_0B                   ;
        RET                             ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
;       THIS SECTION FORMS THE NEW DESIGNATE CP LIST IN THE
;       CPD_TEMP_DESG.  AT THE SAME TIME THE TOTAL NUMBER OF
;       REQUESTED CP's ARE FOUND.
;
;       DX will contain the real CP's to load
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
DB_1B:  CLD                             ; SET DIRECTION FORWARD
        PUSH    ES                      ;
        PUSH    CX                      ;
        PUSH    DI                      ;
        PUSH    CS                      ;
        POP     ES                      ;
        MOV     CX,CPD_DESG_N           ;
        INC     CX                      ; ACCOUNT FOR NUMBER OF CPS
        LEA     SI,CPD_DESG_N           ; COPY PREPARED CP LIST TO TEMP BUFFER
        LEA     DI,CPD_TEMP_DESG        ;
        REP     MOVSW                   ;
        POP     DI                      ;
        POP     CX                      ;
        POP     ES                      ;
                                        ;
        XOR     DX,DX                   ; SET COUNT OF CP's TO PREPARE = 0
        PUSH    CX                      ;
        PUSH    BX                      ;
        MOV     CPD_REQ_DESG,CX         ; SAVE NUMBER OF REQUESTED CP'S
        MOV     SI,2                    ;
        MOV     BX,SI                   ;
DB_1:   MOV     AX,RH.DESG_N[BX]        ; GET REQUESTED CP
        CMP     AX,-1                   ; TEST IF REQUESTED IS PLACE HOLDER..
        JE      DB_1A                   ;
        INC     DX                      ; ADD ONE TO THE # VALID DESG
        MOV     CPD_TEMP_DESG[SI],AX    ; OVERLAY THE NEWER CP INTO TEMP BUFFER
DB_1A:  MOV     CPD_REQ_DESG[SI],AX     ; COPY TO THE REQ DESG LIST
        INC     SI                      ;
        INC     SI                      ;
        INC     BX                      ;
        INC     BX                      ;
        LOOP    DB_1                    ;
        POP     BX                      ;
        POP     CX                      ;
                                        ;
        OR      DX,DX                   ; ARE THERE NO CP's TO PREPARE?
        JZ      DB_0B                   ; IF NONE TO DESG, THEN ERROR!!
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
;       THIS SECTION CHECKS THE LIST OF DESIGed CP's IN THE
;       TEMP BUFFER AND SETS AN ERROR FOR DUPLICATES.
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
DB_2:   PUSH    BX                      ; CHECK THE DESIGNATE LIST FOR DUP's
        PUSH    CX                      ; AND FOR INVALIDS
        MOV     CX,CPD_TEMP_DESG        ;
        DEC     CX                      ; NORMALIZE
        JZ      DB_3                    ; IF ZERO, THEN NONE TO COMPARE
        MOV     BX,2                    ; SET BX TO START OF LIST....
        MOV     SI,2                    ; SETUP SI READY TO MOVE DESG LIST IN!
DB_2A:  PUSH    BX                      ;
        PUSH    CX                      ;
        MOV     AX,CPD_TEMP_DESG[BX]    ; GET CP DESGINATED
        CMP     AX,-1                   ; TEST IF ENTRY = -1
        JE      DB_2E                   ; IF SO, THEN SKIP
DB_2B:  CMP     CX,1                    ; TEST IF IT IS THE ONLY ONE TO COMPARE
        JE      DB_2E                   ; AGAINST!
        INC     BX                      ; ADVANCE POINTER TO NEXT CP DESIGNATED
        INC     BX                      ;
        CMP     AX,CPD_TEMP_DESG[BX]    ; CHECK IF NEXT CP's = ONE TESTED
        JNE     DB_2C                   ; IF error, THEN GET OUT
        JUMP    DB_2D                   ;
                                        ;
DB_2C:  LOOP    DB_2B                   ;
DB_2E:  POP     CX                      ;
        POP     BX                      ;
        INC     BX                      ;
        INC     BX                      ;
        OR      CX,CX                   ;
        JE      DB_3                    ; TEST IF ONLY ONE CP SPECIFIED
        LOOP    DB_2A                   ;
                                        ;
DB_3:   POP     CX                      ;
        POP     BX                      ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
;       NOW, THE TEMPORARY BUFFER CONTAINS THE NEW LIST
;       OF DESGINATED CODE PAGES.  COPY THIS TO THE
;       PREPARED CP LIST.
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
        PUSH    ES                      ; NOW ALL TESTS ARE SUCCESSFUL,
        PUSH    CX                      ;
        PUSH    DI                      ;
        PUSH    CS                      ;
        POP     ES                      ;
        MOV     CX,CPD_DESG_N           ;
        INC     CX                      ; ACCOUNT FOR NUMBER OF CPS
        LEA     SI,CPD_TEMP_DESG        ; COPY TEMP BUFFER INTO NEW CP LIST
        LEA     DI,CPD_DESG_N           ;
        REP     MOVSW                   ;
        POP     DI                      ;
        POP     CX                      ;
        POP     ES                      ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
;       NOW THAT THE LIST IS VALID, THE FONT PARSER & PARSING TABLES
;       ARE PREPARED FOR INITIALIZATION OF DESIGNATION.
;
;       DX is the number of valid CP's
;       CX is the number of CP's desginated
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
        PUSH    BX                      ;
        PUSH    ES                      ;
        PUSH    DI                      ;
                                        ; CX=#DESGed, BX=pnter DESG LIST
        MOV     BX,2                    ; SET BX TO POINT TO FIRST CP DESGed
        LEA     DI,FTABLE               ; SET DI TO POINT TO MAIN PARSER TABLE
        PUSH    CS                      ;
        POP     ES                      ; INITIALIZE ES=CS
        MOV     [DI].FLAG,FLAG_RESTART  ; SETUP UP MAIN TABLE FOR F-PARSER.SRC
        MOV     [DI].BUFFER_LEN,0       ; PREPARING FOR START OF DESIGNATION
        MOV     [DI].NUM_FTBLK,DX       ; DX=#DESG TO PARSE OUT
                                        ;
        LEA     SI,CPD_CLASS            ; SET DI TO POINT TO (EGA,LCD) CLASSES
        LEA     DI,FTB1                 ; SET DI TO POINT TO FIRST PARSING TABLE
                                        ;
DB_4:   MOV     AX,CPD_REQ_DESG[BX]     ;
        CMP     AX,-1                   ; CHECK FOR PLACE HOLDER
        JE      DB_5                    ;
        MOV     [DI].FTB_CP,AX          ; COPY THE DESG CP VALUE INTO THE TABLE
        PUSH    CX                      ; AND ALSO THE CPD_CLASS
        PUSH    SI                      ;
        PUSH    DI                      ;
        LEA     DI,[DI].FTB_TID         ;
        MOV     CX,8                    ;
        REP     MOVSB                   ;
        POP     DI                      ;
        POP     SI                      ;
        POP     CX                      ;
                                        ;
        ADD     DI,TYPE FTBLK           ; MOVE POINTERS TO NEXT PARSING TABLE
DB_5:   INC     BX                      ;
        INC     BX                      ; ADVANCE BX TO NEXT DESG CP
        LOOP    DB_4                    ;
                                        ;
        POP     DI                      ;
        POP     ES                      ;
        POP     BX                      ;
                                        ;
        CALL    FONT_PARSER             ; CALL FONT PARSER TO INITIALIZE WRITES
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
;       THIS WILL COPY THE START LOCATION OF THE FONTS (set by INIT)
;       INTO THE START LOCATION FOR THE DESIGNATE WRITE, WHICH FOLLOWS!
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
        PUSH    SI                      ;
        PUSH    DI                      ;
        PUSH    ES                      ;
        PUSH    CS                      ;
        POP     ES                      ; SET EXTRA SEG ES = CS
        LEA     SI,CPD_FONT_PNTER       ;
        LEA     DI,CPD_FONT_WRITE       ;
        MOV     CX,CPD_DESG_N           ; GET NUMBER OF DESIGNATES
        ADD     CX,CX                   ; DOUBLE FOR SEG:OFFSET
        REP     MOVSW                   ; COPY FONT START LOC's TO START WRITE
        XOR     DI,DI                   ;
        LEA     SI,CPD_FONT_DATA        ; SET THE FONT_DATA COUNTERS BACK TO 0
        MOV     CX,CPD_DESG_N           ;
DB_6:   MOV     [SI],DI                 ;
        INC     SI                      ;
        INC     SI                      ;
        LOOP    DB_6                    ;
        POP     ES                      ;
        POP     DI                      ;
        POP     SI                      ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
;       CREATE THE FONT_PRIORITY TABLE
;
;       THIS IS USED TO PLACE PRIORITY ON THE FONTS BEING DESIGNATED
;       ESPECIALLY WHEN THE NUMBER OF DESIGNATED FONTS < FONTS IN THE
;       xxx.CPI FILE.  THIS IS USED TO SELECT THE NEEDED FONTS FOR
;       CP SUPPORT.
;
;       RULE:  PRIORITY 1 = ACTIVE MODE's FONT RESOLUTION
;              PRIORITY 2 = FONT RESOLUTION (non-repeats) OF ALL DISPLAY
;                           MODES - STARTING FROM MODE (0) - MODE (?)
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
        PUSH    AX                      ;
        PUSH    BX                      ;
        PUSH    CX                      ;
        PUSH    SI                      ;
        PUSH    DI                      ;
                                        ;
        LEA     DI,FONT_PRIORITY        ;
        MOV     CX,CPD_FONTS_N          ; GET THE NUMBER OF SPECIFIED FONTS
                                        ;
        PUSH    ES                      ;
        PUSH    DI                      ;
        PUSH    CX                      ; OVER-WRITE THE TABLE WITH 0FFH's
        PUSH    CS                      ;
        POP     ES                      ;
        MOV     AL,-1                   ;
        REP     STOSB                   ;
        POP     CX                      ;
        POP     DI                      ;
        POP     ES                      ;
                                        ;
        XOR     AH,AH                   ; AH=0 FOR MODE SET, AL=MODE_TYPE
        MOV     AL,MODE_VALUE           ;
        MOV     SI,AX                   ; ESTABLISH INDEX INTO LOAD_MECH table
        MOV     AL,[SI].FONT_SIZE       ; GET FONT_SIZE FOR THIS MODE_VALUE
        OR      AL,AL                   ; TEST FOR FONT_VALUE=0
        JNZ     DB_8                    ;
        CALL    ASK_BIOS_FONT_SIZE      ; GET BIOS TO INDICATE FONT_SIZE
DB_8:   MOV     CS:[DI],AL              ; PUT ACTIVE FONT RESOLUTION INTO 1ST!
        INC     DI                      ; ADVANCE POINTER TO NEXT POSITION
        DEC     CX                      ; SUBTRACT ONE FONT RESOLUTION...
        JZ      DB_A                    ; IF THERE WAS ONLY 1 FONT...THEN DONE
                                        ;
        XOR     SI,SI                   ; START WITH MODE = 0
DB_8A:  PUSH    CX                      ;
        PUSH    DI                      ;
        MOV     CX,NUM_FONT_PRIORITY    ;
        LEA     DI,FONT_PRIORITY        ; SET DI TO START OF TABLE
        MOV     AL,[SI].FONT_SIZE       ; GET FONT SIZE FOR THIS MODE
        CMP     AL,-1                   ; TEST FOR INVALID FONT SIZE
        JE      DB_9                    ; IF SO, THEN TRY NEXT VALUE
        OR      AL,AL                   ; TEST FOR FONT_VALUE=0
        JNZ     DB_8C                   ;
                                        ; OTHERWISE, ONLY EGA BIOS WOULD KNOW!!!
        CMP     SI,EIGHT                ; ONLY EIGHT DIFFERENT FONTS PERMITTED!!
        JAE     DB_9                    ;
                                        ;
        PUSH    CX                      ;
        CALL    ASK_BIOS_SCAN_LINES     ; GET ENCODED SCAN LINES VALUE!!!
        JC      DB_9                    ;
        MOV     CX,SI                   ; PUT INDEX INTO CX
        INC     CL                      ; NORMALIZE INDEX VALUE (1-8)
        SAR     AL,CL                   ;
        POP     CX                      ;
        JNC     DB_9                    ;
        MOV     AL,CS:CHAR_HEIGHT[SI]   ;
                                        ;
DB_8C:  CMP     AL,CS:[DI]              ;
        JE      DB_9                    ; IF EQUAL, THEN ALREADY IN TABLE
        INC     DI                      ; OTHERWISE, TAKE THIS MODES FONT RES
        LOOP    DB_8C                   ; AND COMPARE AGAINST NEXT PRIOR.VALUE
                                        ;
        POP     DI                      ; NEW RESOLUTION FOUND...ADD TO LIST
        POP     CX                      ;
        MOV     CS:[DI],AL              ; PUT NEW VALUE IN THE TABLE
        INC     DI                      ; AND ADVANCE FOR NEXT FONT RESOLUTION
        jmp     short DB_9A             ; LOOP WILL DECREMENT #FONTS TO FIND
DB_9:   POP     DI                      ;
        POP     CX                      ;
        INC     CX                      ; MATCH FOUND..SO LEAVE #FONT TO PRIOR.
DB_9A:  INC     SI                      ; POINT TO NEXT DISPLAY MODE
        CMP     SI,NUM_FONT_SIZES       ;
        JAE     DB_A                    ;
        LOOP    DB_8A                   ; CONTINUE UNTIL THE #FONTS DESIGNATED
                                        ; HAVE BEEN PRIORITIZED OR ALL MODES
DB_A:   POP     DI                      ; ARE CHECKED OUT!
        POP     SI                      ;
        POP     CX                      ;
        POP     BX                      ;
        POP     AX                      ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
;
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
        MOV     DESG_SEMAPHORE,ONE      ; SET DESIGNATION TO COMMENCE...
        RET                             ;
DESIGNATE_BEGIN ENDP                    ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
;       DESIGNATE END
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
DESIGNATE_END   PROC                    ;
        CMP     DESG_SEMAPHORE,ZERO     ; TEST IF DESG_SEMAPHORE = DATA WRITTEN
        JE      DE_1                    ;
                                        ;
        CMP     CPD_REQ_DESG,ZERO       ; TEST IF ZERO CP's REQUESTED (REFRESH)
        JE      DE_0                    ;
                                        ;
        CALL    VERIFY_FPARSER          ; CALL ROUTINE TO VERIFY THAT THE
        JC      DE_2                    ; FONT PARSER FINISHED OK...
                                        ;
        PUSH    ES                      ; NOW THE DESIGNATE IS OVER...
        PUSH    DI                      ;
        MOV     CX,CPD_ACTIVE           ; CHECK IF ACTIVE_CP IS STILL VALID!
        CALL    FIND_CP                 ; TRY AND FIND CPD_ACTIVE?
        POP     DI                      ;
        POP     ES                      ;
        JNC     DE_0                    ;
        MOV     CX,-1                   ;
        MOV     CPD_ACTIVE,CX           ;
DE_0:   MOV     DESG_SEMAPHORE,ZERO     ;
        RET                             ;
                                        ;
DE_1:   OR      BUF.STATUS,TWELVE       ; Error>> NO DESGINATE START
        JUMP    DE_0                    ;
DE_2:   CALL    HANDLE_WRITE_ERROR      ; RESET ALL DESIGNATED INFORMATION
        OR      BUF.STATUS,FAIL         ; Error>> FONT DATA IS BAD
        JUMP    DE_0                    ;
DESIGNATE_END   ENDP                    ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
;       INVOKE
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
INVOKE_CP       PROC                    ;
        LES     DI,RH.REQUEST_PACKET    ; AND DI TO POINT TO REQUEST PACKET
        MOV     CX,RH.INVK_LENGTH       ; GET LENGTH OF REMAINING HEADER
                                        ;
        CMP     CX,TWO                  ; TEST IF LENGTH OF TABLE IS GREATER
        JNE     ICP_2                   ; THAN ONE CP!
                                        ;
        MOV     CX,RH.INVK_CP           ; GET THE CODE PAGE TO INVOKE
        MOV     DX,CX                   ; SAVE CP VALUE
        CMP     CX,-1                   ; TEST FOR INVALID CODE PAGE!
        JE      ICP_1A                  ;
                                        ;
        PUSH    CPD_ACTIVE              ; SAVE ACTIVE_CP, FOR POSSIBLE USE...
        MOV     CPD_ACTIVE,CX           ;
        CALL    TEST_CP                 ; TRY AND LOAD THE REQUESTED CP
        POP     CX                      ;
        JC      ICP_1AA                 ; IF ERROR, THEN RESTORE OLD CP
                                        ;
        CMP     CX,CPD_ACTIVE           ; TEST IF OLD CP=ACTIVE!!!
        JE      ICP_0A                  ;
                                        ;
        CALL    INVOKE_DATA             ; IF EVERYTHING OK, THEN LOAD DATA
        JC      ICP_2A                  ;
                                        ;
ICP_0A: CALL    SIGNAL_KBD_INVK         ; DX CONTAINS CODEPAGE
        JC      ICP_1                   ; IF CY THEN ERROR
        RET                             ;
                                        ;
ICP_1:  OR      BUF.STATUS,EIGHT        ; Error>> KEYB ERROR
        RET                             ;
ICP_1AA:MOV     CPD_ACTIVE,CX           ; PUT OLD CP BACK ACTIVE
ICP_1A: OR      BUF.STATUS,SEVEN        ; Error>> CODE PAGE NOT FOUND
        RET                             ;
ICP_2A: MOV     CPD_ACTIVE,CX           ;
ICP_2:  OR      BUF.STATUS,TEN          ; Error>> DEVICE ERROR
        RET                             ;
INVOKE_CP       ENDP                    ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
;       QUERY
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
QUERY_CP        PROC                    ;
        LES     DI,RH.REQUEST_PACKET    ; SETUP ADDRESSING TO HEADER
                                        ;
        MOV     CX,TWO                  ;
        MOV     RH.INVK_LENGTH,CX       ; CREATE RETURN 'N' VALUE
                                        ;
        CALL    TEST_CP                 ; FIND OUT IF CP DATA IS OK!
        MOV     CX,CPD_ACTIVE           ;
        JNC     QCP_A                   ;
        MOV     CX,-1                   ; MAKE THE ACTIVE REPONSE AS INVALID
                                        ;
QCP_A:  MOV     RH.INVK_CP,CX           ; SET THE CODE PAGE IN HEADER
        CMP     CX,-1                   ; TEST IF NO CP SPECIFIED?
        JE      QCP_0                   ;
        RET                             ;
                                        ;
QCP_0:  OR      BUF.STATUS,SEVEN        ; Error>> NOT CODE PAGE SPECIFIED
        RET                             ;
QUERY_CP        ENDP                    ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
;       QUERY LIST
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
QUERY_CP_LIST   PROC                    ;
        LES     DI,RH.REQUEST_PACKET    ; AND DI TO POINT TO REQUEST PACKET
                                        ;
        MOV     CX,CPD_HDWR_N           ;
        MOV     RH.QLST_N_HDWR,CX       ;
        ADD     CX,CPD_DESG_N           ;
        ADD     CX,TWO                  ; ACCOUNT FOR LENGTH OF 'N's
        ADD     CX,CX                   ;
        MOV     RH.QLST_LENGTH,CX       ; CREATE RETURN TABLE LENGTH
                                        ;
        PUSH    AX                      ;
        PUSH    BX                      ;
        PUSH    SI                      ;
        MOV     CX,CPD_HDWR_N           ;
        MOV     BX,2                    ;
        OR      CX,CX                   ;
        JE      QCP_3                   ;
QCP_2:  MOV     AX,CPD_HDWR_N[BX]       ;
        MOV     RH.QLST_N_HDWR[BX],AX   ;
        INC     BX                      ;
        INC     BX                      ;
        LOOP    QCP_2                   ;
                                        ;
QCP_3:  MOV     CX,CPD_DESG_N           ; SET TABLE ENTRY FOR DESIGNATE
        MOV     RH.QLST_N_HDWR[BX],CX   ;
        INC     BX                      ;
        INC     BX                      ;
                                        ;
        OR      CX,CX                   ;
        JE      QCP_4A                  ;
        MOV     SI,2                    ;
QCP_4:  MOV     AX,CPD_DESG_N[SI]       ;
        MOV     RH.QLST_N_HDWR[BX],AX   ;
        INC     BX                      ;
        INC     BX                      ;
        INC     SI                      ;
        INC     SI                      ;
        LOOP    QCP_4                   ;
QCP_4A: POP     SI                      ;
        POP     BX                      ;
        POP     AX                      ;
        RET                             ;
QCP_5:  OR      BUF.STATUS,SEVEN        ; Error>> NO CODE PAGE INVOKED
        RET                             ;
QCP_6:  OR      BUF.STATUS,TEN          ; Error>> DEVICE ERROR
        RET                             ;
QUERY_CP_LIST   ENDP                    ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
;       GET HARDWARE CODE PAGE TABLE
;
;       INPUT:
;               none
;       OUTPUT:
;               SI = pointer to HARDWARE table (n,h_cp1,h_cp2,...)
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
GET_HDWR_CP     PROC                    ;
        LEA     SI,CP_PNTER_TABLE       ;
        MOV     SI,[SI].HDWR_CP_STRUC   ;
        RET                             ;
GET_HDWR_CP     ENDP                    ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
;       GET DESIGNATE CODE PAGE TABLE
;
;       INPUT:  none
;       OUTPUT: SI = pointer to DESIGNATE table (n,d_cp1,d_cp2,...)
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
GET_DESG_CP     PROC                    ;
        LEA     SI,CP_PNTER_TABLE       ;
        MOV     SI,[SI].DESG_CP_STRUC   ;
        RET                             ;
GET_DESG_CP     ENDP                    ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
;       GET FONT POINTER TABLE
;
;       INPUT:
;               none
;       OUTPUT:
;               SI = pointer to FONTS table (pnter_cp1,pnter_cp2,...)
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
GET_FONT_CP     PROC                    ;
        LEA     SI,CP_PNTER_TABLE       ;
        MOV     SI,[SI].FONT_CP_STRUC   ;
        RET                             ;
GET_FONT_CP     ENDP                    ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
;       GET WRITE POINTER
;
;       INPUT:
;               none
;       OUTPUT:
;               SI = pointer to WRITE pointers
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
GET_WRITE_PNTR  PROC                    ;
        LEA     SI,CP_PNTER_TABLE       ;
        MOV     SI,[SI].WRITE_DATA_STRUC;
        RET                             ;
GET_WRITE_PNTR  ENDP                    ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
;       FIND ACTIVE CODE PAGE
;
;       INPUT:
;               CX      = code page to find
;       OUTPUT:
;              'CY'     = 0 if found, 1 if NOT
;               CX      = 0 for hdwr, 1 for designated
;               ES : DI = pointer to FONT data table
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
FIND_CP         PROC                    ;
        PUSH    AX                      ;
        PUSH    BX                      ;
        PUSH    SI                      ;
        MOV     AX,CX                   ;
        CALL    GET_DESG_CP             ; SET BX TO DESG TABLE INFO
        MOV     CX,[SI]                 ; GET THE NUMBER OF DESG CP's
        OR      CX,CX                   ;
        JZ      FCP_1                   ; MOVE ONTO DESG TEST WITH 0 CP's
        MOV     BX,TWO                  ; ELSE, USE SI TO POINT TO 1ST CP
FCP_0:  CMP     AX,[SI+BX]              ; SEARCH FOR CP MATCH
        JE      FCP_4                   ; CP MATCHED!!  SET DESG INFO & EXIT
        INC     BX                      ; ADVANCE SI POINTER TO NEXT CP
        INC     BX                      ;
        LOOP    FCP_0                   ; CHECK ACROSS ALL CP's IN TABLE
FCP_1:  CALL    GET_HDWR_CP             ; NOW, REPEAT SAME OPERATION
        MOV     CX,[SI]                 ; WITH THE HARDWARE CP's
        OR      CX,CX                   ;
        JZ      FCP_3                   ; IF THIS FAR, THEN SET ERROR FOR
        INC     SI                      ;
        INC     SI                      ; ADVANCE POINTER BY TWO...SINCE
        MOV     BX,ZERO                 ; PNTER'S DON'T HAVE 'n'...
FCP_2:  CMP     AX,[SI+BX]              ; SEARCH AGAIN FOR CP MATCH
        JE      FCP_5                   ; CP MATCHED!! SET HDWR INFO & EXIT
        INC     BX                      ; ADVANCE SI POINTER TO NEXT CP
        INC     BX                      ;
        LOOP    FCP_2                   ; REPEAT FOR ALL CP ENTRIES
FCP_3:  XOR     CX,CX                   ; SET RETURN VALUES TO ZERO
        XOR     DI,DI                   ;
        POP     SI                      ;
        POP     BX                      ;
        POP     AX                      ;
        STC                             ; CY=1 FOR ERROR
        RET                             ; EXIT
FCP_4:  MOV     CX,ONE                  ; ®®DESIGNATED CODE PAGE FOUND¯¯
        CALL    GET_FONT_CP             ; SET THE BX VALUE TO THE FONT DATA
        SUB     BX,2                    ; NORMALIZE BX VALUE;;;;;;;;;;;;;;;
        ADD     SI,BX                   ; FORMULATE THE SI INDEX BY ADDING
        ADD     SI,BX                   ; BX INDEX x 2 (dword FONT_PNTER)
        MOV     DI,[SI]                 ; TAKE OFFSET DATA FROM font_table
        MOV     ES,[SI+2]               ; AND SEGMENT ALSO!
        POP     SI                      ;
        POP     BX                      ;
        POP     AX                      ;
        CLC                             ; CY=0 FOR OK!
        RET                             ; EXIT
FCP_5:  XOR     CX,CX                   ; ®®HARDWARE CODE PAGE FOUND¯¯
        XOR     DI,DI                   ;
        POP     SI                      ;
        POP     BX                      ;
        POP     AX                      ;
        CLC                             ;
        RET                             ; EXIT
FIND_CP         ENDP                    ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
;       VERIFY_FPARSER A ROUTINE THAT CHECKS THE
;       FONT_BLOCKS FOR INCOMPLETE DESIGNATES?
;       IF SO, THEN AN ERROR OCCURRED...
;
;       INPUT:
;               FONT_PARSER should be completed parsing
;
;       OUTPUT:
;               CY = 0 if all is correct
;                    1 if one or more designates are incomplete
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
VERIFY_FPARSER  PROC                    ;
        PUSH    AX                      ;
        PUSH    CX                      ;
        PUSH    ES                      ;
        PUSH    DI                      ;
                                        ;
        PUSH    CS                      ;
        POP     ES                      ;
                                        ;
        MOV     CX,CPD_REQ_DESG         ; CX = REQUESTED DESG CP's
        LEA     DI,FTB1                 ; SET DI TO POINT TO FIRST PARSING TABLE
                                        ;
VFP_4:  MOV     AX,[DI].FTB_STATUS      ; GET STATUS OF PARSING TABLE #n
        CMP     AX,FSTAT_COMPLETE       ; FIND OUT IF THIS CP COMPLETED?
        JE      VFP_6                   ;
                                        ;
        CMP     AX,FSTAT_FONT           ; CHECK IF AT LEAST THE FONT DATA FOUND
        JNE     VFP_8                   ; IF NOT, THEN AN ERROR OCCURRED....
        CMP     [DI].FTB_DLEFT,ZERO     ; IF SO, THEN NO DATA CAN BE LEFT....
        JNE     VFP_8                   ; OTHERWISE ANOTHER ERROR ?
VFP_6:  ADD     DI,TYPE FTBLK           ; MOVE POINTERS TO NEXT PARSING TABLE
        LOOP    VFP_4                   ;
        CLC                             ;
        jmp     short VFP_9                   ;
                                        ;
VFP_8:  STC                             ;
VFP_9:  POP     DI                      ;
        POP     ES                      ;
        POP     CX                      ;
        POP     AX                      ;
        RET                             ;
VERIFY_FPARSER  ENDP                    ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

