/********************* START OF SPECIFICATIONS *************************/
/*                                                                     */
/*  SUBROUTINE NAME: NLSINTSETBIDIATT                                  */
/*                                                                     */
/*  DESCRIPTIVE NAME: Changes the contents of the control block.       */
/*                                                                     */
/*  COPYRIGHT: (c) IBM Corp. 1989                                      */
/*                                                                     */
/*  FUNCTION: The NlsIntSetBidiAtt changes the Bidi Attributes for any */
/*            of the sessions or for any of the three printers         */
/*            connected to the system.                                 */
/*                                                                     */
/*  ENTRY POINT: NlsIntSetBidiAtt                                      */
/*      LINKAGE: CALL FAR (from any internal component).               */
/*                                                                     */
/*  INPUT:       (Scope,Effect,SetInfo)                                */
/*               Scope (DWORD)    - Session identifier                 */
/*               Effect (DWORD)   - Select Keyboard/Video or printer   */
/*               SetInfo (@Other) - Address of an area for the API     */
/*                                  to copy the new data from it       */
/*                                                                     */
/*  EXIT-NORMAL: RC = 0                                                */
/*                                                                     */
/*  EXIT-ERROR:  RC = ERROR_BIDI_INVALID_SCOPE                         */
/*               RC = ERROR_BIDI_INVALID_EFFECT                        */
/*               RC = ERROR_BIDI_INVALID_COMBINATION                   */
/*               RC = ERROR_BIDI_INVLALID_LENGTH                       */
/*               RC = ERROR_BIDI_INVALID_RESERVED                      */
/*               RC = ERROR_BIDI_INVALID_ORIENTATION                   */
/*               RC = ERROR_BIDI_INVALID_NUM_SHAPE                     */
/*               RC = ERROR_BIDI_INVALID_CSD                           */
/*               RC = ERROR_BIDI_INVALID_LEVEL                         */
/*               RC = ERROR_BIDI_INVALID_TYPE_SUPPORT                  */
/*                                                                     */
/*  SIDE EFFECTS: The contents of the control blocks may be updated.   */
/*                                                                     */
/*  INTERNAL REFERENCES:                                               */
/*     LOCAL DATA DEFINITION:                                          */
/*                                                                     */
/*         DWORD index             - Index the control block           */
/*          WORD ActualLength      - Contains the first word of the    */
/*                                   control block.                    */
/*         DWORD CBcount           - Dummy counter.                    */
/*          WORD ChangeLanguage    - Flag to indicate that the         */
/*                                   language has to changed.          */
/*          WORD length            - length of buffer for list         */
/*          WORD ListLength        - length of returned list           */
/*          WORD CodePage          - current code page                 */
/*          WORD CurRow            - Used to refresh cursor position.  */
/*          WORD CurCol            - Used to refresh cursor position.  */
/*        @OTHER screen            - Array of 6880 characters.         */
/*          WORD CellNum           - Number of cells to refresh.       */
/*          WORD gdt_descriptor    - Holds the segment selector.       */
/*          WORD ldt_descriptor    - Holds the segment selector.       */
/*          STRUCT gdt             - structure of type PGINFOSEG.      */
/*          WORD CurrentSess       - Hold the current session ID       */
/*          WORD ChangeOrientation - Flag to indicate that the         */
/*                                   orientation has to be changed     */
/*          WORD KbdHandle         - Used as a handle to the keyboard  */
/*                                   in DosOpen().                     */
/*          @OTHER usaction        - Address to store action taken in  */
/*                                   DosOpen().                        */
/*          DWORD ReturnCode       - Used by the called functions.     */
/*          @OTHER ShrPtr          - Pointer to a structure of type    */
/*                                   bididseg.                         */
/*          @OTHER SetInfo         - Pointer to a structure of type    */
/*                                   setinfo.                          */
/*          @OTHER KbvInfo         - Pointer to a structure of type    */
/*                                   kbvcb                             */
/*          STRUCT OldKbvcb        - Structure of type kbvcb           */
/*          @OTHER LptInfo         - Pointer to a structure of type    */
/*                                   PRCBTYPE                          */
/*                                                                     */
/*     GLOBAL DATA DEFINITION:                                         */
/*      STRUCT SETINFO    - Structure of the area from which the API   */
/*                          copies the BiDi attributes.                */
/*                          It consists of the following:              */
/*                           WORD length      - Length of the structure*/
/*                           BYTE SetArea[78] - Rest of the structure. */
/*                                                                     */
/*      STRUCT BIDIATT    - Structure of the BiDi attributes.          */
/*                          It consists of the following:              */
/*                           BYTE CsdValue    - The character shapes.  */
/*                           BYTE NumShapes   - The numeral shapes.    */
/*                           BYTE orientation - The screen orientation.*/
/*                           BYTE reserved    - Reserved byte.         */
/*                                                                     */
/*      STRUCT KBVCB      - Structure of the keyboard video control    */
/*                          block.                                     */
/*                          It consists of the following:              */
/*                           WORD    length   - The length of the      */
/*                                              control block.         */
/*                           WORD    BDVerID  - The BiDi version ID.   */
/*                     STRUCT bidiatt BidiAtt - The BiDi attributes.   */
/*                             BYTE    reserved[4] - Reserved.         */
/*                             WORD    HotKeys     - Hot keys flags.   */
/*                             WORD    flags       - BiDi flags.       */
/*                                                                     */
/*      STRUCT PRCB       - Structure of the printer control block.    */
/*                          It consists of the following:              */
/*                           WORD  length     - control block length   */
/*                     STRUCT bidiatt BidiAtt - The BiDi attributes.   */
/*                                                                     */
/*      STRUCT lptblock   - Structure of the printer control block     */
/*                          It consists of the following:              */
/*                           WORD  LptLength   - Length of the         */
/*                                                control block.       */
/*                           BYTE  LptArea[18] - Rest of the control   */
/*                                               block                 */
/*                                                                     */
/*      STRUCT kbvblock   - Structure of the keyboard video            */
/*                          control block.                             */
/*                          It consists of the following:              */
/*                           WORD  KbvLength   - Length of the         */
/*                                               control block.        */
/*                           BYTE  KbvArea[78] - Rest of the control   */
/*                                               block                 */
/*                                                                     */
/*      STRUCT bididseg   - Structure of the BiDi data segment         */
/*                          It consists of the following:              */
/*                           BYTE  reserved[320] - Reserved area       */
/*                           lptblock  lpt[3]    - Printers area       */
/*                           kbvblock  kbvcb[17] - Keyboard video      */
/*                                                 area.               */
/*                                                                     */
/*     ROUTINES: CheckData()                                           */
/*                                                                     */
/*  EXTERNAL REFERENCES:                                               */
/*     ROUTINES: NlsIntQueryBidiAtt()                                  */
/*               NlsQueryBidisegAddress()                              */
/*               DosOpen()                                             */
/*               DosClose()                                            */
/*               DosDevIOCtl()                                         */
/*               VioGetCurPos()                                        */
/*               VioSetCurPos()                                        */
/*               VioReadCellStr()                                      */
/*               VioWrtCellStr()                                       */
/*               DosGetCp()                                            */
/*               DosGetInfoSeg()                                       */
/*                                                                     */
/********************** END OF SPECIFICATIONS **************************/
#define  INCL_BASE
#include <os2.h>
#include "bdcalls.h"        /* include the Bidi Data Segment structure, */
#include "sq.h"             /* the RetInfo Structure.                   */
                            /* include the error codes                  */

#define  KBVCB_FLAG      0
#define  PRCB_FLAG       1
#define  ACTUAL_LENGTH   16
#define  PRIMARY_LAYER   0
#define  SECONDARY_LAYER 1

USHORT EXPENTRY NlsQueryBidisegAddress (ULONG);

USHORT far pascal _loadds NlsIntSetBidiAtt (LONG Scope,
                                           LONG Effect,
                                           PSETINFO setinfo)
{
/*-----------------------------------------------------------------------*/
/*                         Variables Definition                          */
/*-----------------------------------------------------------------------*/
   int      ActualLength;
   int      ChangeLanguage, ChangeOrientation;
   USHORT   CellNum,ReturnCode;
   static   char screen[8000];                            /* 2 x 80 x 50 */
   ULONG    CurrentSess;
   USHORT   CBcount;
   HFILE    KbdHandle;
   USHORT   usaction;
   USHORT   ParmList[2];                 /* Parameter list for the IOCtl */
   struct   bididseg  *ShrPtr;
   KBVCB    *KbvInfo;
   KBVCB    OldKbvInfo;
   SETINFO  *SetInfo;
   USHORT   length = 6;                  /* variables used by DosGetCp() */
   USHORT   CodePage;
   USHORT   ListLength;
   PGINFOSEG  gdt;
   USHORT   CurRow,CurCol;
   SEL      gdt_descriptor,ldt_descriptor;        /* infoseg descriptors */
   LONG     index;
   USHORT   RC=0;
/*-----------------------------------------------------------------------*/
/* Insure that the I/P parms are valid                                   */
/*-----------------------------------------------------------------------*/
   SetInfo =(SETINFO*) setinfo;

   RC= NlsQueryBidisegAddress ((ULONG)&ShrPtr);
                                               /* Get the address of the */
                                               /* BiDi data segment      */
   if(RC !=0) return (RC);        /* e.g ERROR_BIDI_NO_SUPPORT  */

if (!(Scope >= MIN_SCOPE && Scope <= SCOPE_LIMIT)) /* Scope out of range */
   return(ERROR_BIDI_INVALID_SCOPE);               /* -1 <= Scope <= 15  */

if (!(Effect >= NULL && Effect <= EFFECT_LIMIT))
   return(ERROR_BIDI_INVALID_EFFECT);            /* Effect out of range */

if (Scope != NULL && Effect != NULL)
    return(ERROR_BIDI_INVALID_COMBINATION);
/*----------------------------------------------------------------------*/
/*  The inputs parameters are valid.                                    */
/*  Is it required to query for the BiDi Keyboard Video Control Block   */
/*  or for the BiDi Printer Control Block                               */
/*----------------------------------------------------------------------*/

if (Effect == NULL) {                     /* Set for the Bidi keyboard  */
                                          /* video control block        */
   index = Scope+1;                       /* 0 <= index <= 16           */
   ActualLength = ShrPtr ->kbvcb[index].KbvLength;
                                       /* The caller is not allowed     */
   if (SetInfo ->length <= 4)          /* to change the BiDi version ID */
       return(ERROR_BIDI_INVALID_LENGTH);

   if (SetInfo ->length > ActualLength)
                                     /* The caller is not allowed to    */
                                     /* set more than the actual length */
      return(ERROR_BIDI_INVALID_LENGTH);
                                     /* The inputs are valid , however  */
                                     /* check the written data          */
   ReturnCode = CheckData(KBVCB_FLAG, SetInfo);
   if (ReturnCode != NO_ERROR)
      return(ReturnCode);
                               /* Compare the original and the          */
                               /* caller control block. If the          */
                               /* screen orientation or the             */
                               /* language layer has changed then       */
                               /* set two global variables accordingly. */
   OldKbvInfo.length = ACTUAL_LENGTH;
   ReturnCode = NlsIntQueryBidiAtt(Scope,0L,(PRETINFO)&OldKbvInfo);

   KbvInfo = (KBVCB*) SetInfo;

   if ( (OldKbvInfo.BidiAtt & ORIENTATION_BYTE)
                  != (KbvInfo ->BidiAtt & ORIENTATION_BYTE) ){
      ChangeOrientation = 1;
      CellNum = sizeof(screen);
      ReturnCode = VioReadCellStr(screen,&CellNum,0,0,0);
        if (ReturnCode != NO_ERROR)
          return(ReturnCode);
      }
                                     /* Isolate the bit four to test it */
   if ( (OldKbvInfo.flags & 16) != (KbvInfo ->flags & 16) )
      ChangeLanguage = 1;
                                   /* All tests were done, start coping */
                                   /* Copy the specified length from    */
                                   /* the SetInfo to the BDKBVCB[index] */
   for (CBcount = 0; CBcount < SetInfo ->length - 2; CBcount++)
      ShrPtr ->kbvcb[index].KbvArea[CBcount] = SetInfo ->SetArea[CBcount];

   DosGetInfoSeg(&gdt_descriptor, &ldt_descriptor);
   gdt = MAKEPGINFOSEG(gdt_descriptor);
                                  /* this contains forground session ID */
   CurrentSess = gdt->sgCurrent;

   if (ChangeLanguage == 1 && CurrentSess == Scope) {
                                                   /* Open the keyboard */
     ReturnCode = DosOpen( (PSZ)"KBD$",&KbdHandle,&usaction,(ULONG)0,
                           (USHORT)4,(USHORT)1,(USHORT)0x20C2,(ULONG)0 );
     if (ReturnCode != NO_ERROR)
        return(ReturnCode);

     ReturnCode = DosGetCp (length,&CodePage,&ListLength);
     if (ReturnCode != NO_ERROR)
        return(ReturnCode);

     if ((KbvInfo ->flags & 16) == 0) {       /* Required English layer */
        ParmList[0] = CodePage;
        ParmList[1] = PRIMARY_LAYER;
                                   /* Issue IOCtl to change the current */
                                   /* code page layer                   */
        ReturnCode = DosDevIOCtl(0L,ParmList,(USHORT)0x0058,(USHORT)0x0004,
                                 (HFILE)KbdHandle);
        if (ReturnCode != NO_ERROR)
           return(ReturnCode);
     }
     else {                                  /* Required national layer */
        ParmList[0] = CodePage;
        ParmList[1] = SECONDARY_LAYER;
                                   /* Issue IOCtl to change the current */
                                   /* code page layer                   */
        ReturnCode = DosDevIOCtl(0L,ParmList,(USHORT)0x0058,(USHORT)0x0004,
                                 (HFILE)KbdHandle);
        if (ReturnCode != NO_ERROR)
           return(ReturnCode);
     }
                                                  /* Close the keyboard */
     ReturnCode = DosClose(KbdHandle);
     if (ReturnCode != NO_ERROR)
        return(ReturnCode);
   }

   if (ChangeOrientation == 1) {       /* change the cursor position */
     ReturnCode = VioGetCurPos(&CurRow,&CurCol,0);
       if (ReturnCode != NO_ERROR)
         return(ReturnCode);
     ReturnCode = VioSetCurPos(CurRow,CurCol,0);
       if (ReturnCode != NO_ERROR)
         return(ReturnCode);
                                       /* change the screen orientation */
     ReturnCode = VioWrtCellStr(screen,CellNum,0,0,0);
       if (ReturnCode != NO_ERROR)
         return(ReturnCode);
      }
   return (NO_ERROR);
   }
else {                            /* Set the Bidi printer control block */
   ActualLength = ShrPtr ->lpt[Effect - 1].LptLength;
   if ( SetInfo ->length <= 2 )
      return(ERROR_BIDI_INVALID_LENGTH);

   if ( SetInfo ->length > ActualLength)
                                     /* The user is not allowed to      */
                                     /* set more than the actual length */
      return(ERROR_BIDI_INVALID_LENGTH);

                                       /* The inputs are valid, however */
                                       /* check the written data        */
   ReturnCode = CheckData( PRCB_FLAG, SetInfo );
   if (ReturnCode != NO_ERROR)
      return(ReturnCode);

                                    /* All test were done, start coping */
                                    /* Copy the specified length from   */
                                    /* SetInfo to BDPRCB[Effect - 1]    */
   for (CBcount = 0; CBcount < SetInfo ->length - 2; CBcount++)
     ShrPtr ->lpt[Effect - 1].LptArea[CBcount] = SetInfo ->SetArea[CBcount];
   return (NO_ERROR);
   }
}

/********************* START OF SPECIFICATIONS *************************/
/*                                                                     */
/*  SUBROUTINE NAME: CHECKDATA                                         */
/*                                                                     */
/*  DESCRIPTIVE NAME: Checks the caller's data.                        */
/*                                                                     */
/*  FUNCTION: Checks on the data provided by the caller before         */
/*            updating the required control block.                     */
/*                                                                     */
/*  ENTRY POINT: CheckData                                             */
/*      LINKAGE: CALL NEAR (from NlsIntSetBidiAtt).                    */
/*                                                                     */
/*  INPUT:       (type, SetInfo)                                       */
/*               WORD type     - Indicates the control block type      */
/*                               (keyboard video or printer).          */
/*                               It can be KBVCB for keyboard video    */
/*                               control block or PRCB for printer     */
/*                               control block.                        */
/*              @OTHER SetInfo - Address of an area for the API        */
/*                               to copy the new data from it          */
/*                                                                     */
/*  EXIT-NORMAL: RC = 0                                                */
/*                                                                     */
/*  EXIT-ERROR:                                                        */
/*               RC = ERROR_BIDI_INVALID_RESERVED                      */
/*               RC = ERROR_BIDI_INVALID_ORIENTATION                   */
/*               RC = ERROR_BIDI_INVALID_NUM_SHAPE                     */
/*               RC = ERROR_BIDI_INVALID_CSD                           */
/*               RC = ERROR_BIDI_INVALID_LEVEL                         */
/*               RC = ERROR_BIDI_INVALID_TYPE_SUPPORT                  */
/*                                                                     */
/*  INTERNAL REFRENCES:                                                */
/*     LOCAL DATA DEFINITION:                                          */
/*               WORD ResCount  - Dummy counter.                       */
/*               WORD PushLevel - Contains the push level bits.        */
/*               WORD SymSwap   - Contains the symmetric swapping value*/
/*               WORD TypeSupp  - Contains the type of support value.  */
/*               WORD SuppLevel - Contains the support level value.    */
/*               WORD NumShape  - Contains the numeral shapes value.   */
/*                                                                     */
/*               @OTHER ChkKbv  - Pointer to a structure of type       */
/*                                KBVCBTYPE.                           */
/*               @OTHER ChkLpt  - Pointer to a structure of type       */
/*                                PRCBTYPE.                            */
/*               @OTHER SetInfo - Pointer to a structure of type       */
/*                                setinfo.                             */
/*                                                                     */
/*     GLOBAL DATA DEFINITION:                                         */
/*      STRUCT setinfo   - Structure of the area from which the API    */
/*                         copyies the BiDi attributes.                */
/*                         It consists of the following:               */
/*                          WORD length      - Length of the structure.*/
/*                          BYTE SetArea[78] - Rest of the structure.  */
/*                                                                     */
/*      STRUCT bidiatt   - Structure of the BiDi attributes.           */
/*                         It consists of the following:               */
/*                          BYTE CsdValue    - The character shapes.   */
/*                          BYTE NumShapes   - The numeral shapes.     */
/*                          BYTE orientation - The screen orientation. */
/*                          BYTE reserved    - Reserved byte.          */
/*                                                                     */
/*      STRUCT KBVCBTYPE - Structure of the keyboard video control     */
/*                         block.                                      */
/*                         It consists of the following:               */
/*                          WORD    length  - The length of the        */
/*                                            control block.           */
/*                          WORD    BDVerID - The BiDi version ID.     */
/*                 STRUCT bidiatt BidiAtt   - The BiDi attributes.     */
/*                          BYTE    reserved[4] - Reserved.            */
/*                          WORD    HotKeys     - Hot keys flags.      */
/*                          WORD    flags       - BiDi flags.          */
/*                                                                     */
/*      STRUCT PRCBTYPE  - Structure of the printer control block.     */
/*                         It consists of the following:               */
/*                          WORD   length   - The control block length.*/
/*                 STRUCT bidiatt BidiAtt   - The BiDi attributes.     */
/*                                                                     */
/*     ROUTINES: NONE.                                                 */
/*                                                                     */
/*  EXTERNAL REFERENCES:                                               */
/*     ROUTINES: NONE.                                                 */
/*                                                                     */
/********************** END OF SPECIFICATIONS **************************/
int  CheckData(int type, SETINFO* SetInfo)
{
   KBVCB *ChkKbv;
   PRCB  *ChkLpt;
   int   ResCount, PushLevel;
   ULONG SymSwap, TypeSupp, SuppLevel, NumShape;
   char  Csd_Values;

   if (type == KBVCB_FLAG) {          /* Required to check the contents */
                                      /* of the caller keyboard video   */
                                      /* control block                  */
      ChkKbv = (KBVCB*) SetInfo;

      switch (ChkKbv ->length) {
      default:

      case 15:                        /* Insure that the push level < 2 */
         PushLevel = ChkKbv ->flags & 12;
         if (PushLevel == 8 || PushLevel == 12) {
            return (ERROR_BIDI_INVALID_RESERVED);
            }

      case 9: case 10: case 11: case 12: case 13: case 14:
                                   /* Insure that the four bytes        */
                                   /* following the BiDi attributes are */
                                   /* zeros                             */
         for (ResCount = 0; ResCount <= 3; ResCount++) {
         if (ChkKbv ->reserved[ResCount] !=0) {
            return (ERROR_BIDI_INVALID_RESERVED);
            }
         } /* endfor */

      case 8:                        /* Lower half of the byte, type of */
                                     /* support must be visual "0"      */
         TypeSupp = (ChkKbv ->BidiAtt & RESERVED_BYTE) & 0x0F000000;
         if (TypeSupp != 0)
            return (ERROR_BIDI_INVALID_TYPE_SUPPORT);
                                   /* Higher half of the byte, support  */
                                   /* level must be on screen level "3" */
         SuppLevel = (ChkKbv ->BidiAtt & RESERVED_BYTE) & 0xF0000000;
         if (SuppLevel != 0x30000000)
            return (ERROR_BIDI_INVALID_LEVEL);

      case 7:
         if ((ChkKbv ->BidiAtt & ORIENTATION_BYTE) > 0x00010000)
            return (ERROR_BIDI_INVALID_ORIENTATION);

      case 6:        /* The lower half must be 1 (symetric swapping off */
                     /* and the higher half must be either 1 or 2       */
         SymSwap = (ChkKbv ->BidiAtt & NUMERAL_BYTE) & 0x00000F00;
         if (SymSwap != 0) {
            return (ERROR_BIDI_INVALID_RESERVED);
            }

         NumShape = (ChkKbv ->BidiAtt & NUMERAL_BYTE) & 0x0000F000;

         if ( (NumShape != 0x00001000) && (NumShape != 0x00002000) )
/*                                     && (NumShape != 0x00000000) ) */
            return (ERROR_BIDI_INVALID_NUM_SHAPE);

       case 5:                         /* if CSD values are out of range */

         Csd_Values =(char)(ChkKbv ->BidiAtt & CSD_BYTE);
         switch (Csd_Values) {
           case 0: case 1: case 16: case 17:  case 18:  case 19:  case 20:
              break;
           default:
              return (ERROR_BIDI_INVALID_CSD);
              break;
         } /* endswitch */

     /* case 4 will be commented because it is a redundent path and can not */
     /* be executed  3-11-90..... A.E                                       */
     /*  case 4:                                                            */
     /*    if (ChkKbv ->BDVerID != 0x10)                                    */
     /*      return (ERROR_BIDI_INVALID_VER_ID);                            */
     /***********************************************************************/
      } /* endswitch */

    return (NO_ERROR);
      } /* endif */

     else {                       /* Required to check the contents of  */
                                  /* the caller printer control block   */
      ChkLpt = (PRCB*) SetInfo;
      switch (ChkLpt ->length) {
      default:
      case 6:                        /* Lower half of the byte, type of */
                                     /* support must be visual "0"      */
      TypeSupp = (ChkLpt ->BidiAtt & RESERVED_BYTE) & 0x0F000000;
      if (TypeSupp != 0)
            return (ERROR_BIDI_INVALID_TYPE_SUPPORT);
                                    /* Higher half of the byte, support */
                                    /* level must be on screen level "3"*/
      SuppLevel = (ChkLpt ->BidiAtt & RESERVED_BYTE) & 0xF0000000;
      if (SuppLevel != 0x30000000)
            return (ERROR_BIDI_INVALID_LEVEL);

      case 5:
         if ((ChkLpt ->BidiAtt & ORIENTATION_BYTE) > 0x00010000)
            return (ERROR_BIDI_INVALID_ORIENTATION);

      case 4:       /* The lower half must be 1 (symetric swapping off) */
                    /* and the higher half must be either 1 or 2        */
         SymSwap = (ChkLpt ->BidiAtt & NUMERAL_BYTE) & 0x00000F00;
         if (SymSwap != 0) {
            return (ERROR_BIDI_INVALID_RESERVED);
            }

         NumShape = (ChkLpt ->BidiAtt & NUMERAL_BYTE) & 0x0000F000;
         if ( (NumShape != 0x00001000) && (NumShape != 0x00002000)
                                       && (NumShape != 0x00000000) )
                              /* Numeral shapes are not Arabic or Hindu */
            return (ERROR_BIDI_INVALID_NUM_SHAPE);

      case 3:

         Csd_Values =(char) (ChkLpt ->BidiAtt & CSD_BYTE);
         switch (Csd_Values) {
           case 0: case 1: case 16: case 17:  case 18:  case 19:  case 20:
              break;
           default:
              return (ERROR_BIDI_INVALID_CSD); /* if CSD value is invalid */
              break;
         } /* endswitch */
      } /* endswitch */
    return (NO_ERROR);
    }
}
