/*DDK*************************************************************************/
/*                                                                           */
/* COPYRIGHT    Copyright (C) 1995 IBM Corporation                           */
/*                                                                           */
/*    The following IBM OS/2 WARP source code is provided to you solely for  */
/*    the purpose of assisting you in your development of OS/2 WARP device   */
/*    drivers. You may use this code in accordance with the IBM License      */
/*    Agreement provided in the IBM Device Driver Source Kit for OS/2. This  */
/*    Copyright statement may not be removed.                                */
/*                                                                           */
/*****************************************************************************/
/**********************************************************************/
/*                                                                    */
/*   Module          = EDDAPTMK                                       */
/*                                                                    */
/*   Description     = Display Device Driver subroutines              */
/*                     PatternSetUp and MarkerSetUp                   */
/*                                                                    */
/*   Function        = PatternSetUp calculates the desired pattern    */
/*                     bitmap.                                        */
/*                     MarkerSetUp calculates the desired marker      */
/*                     bitmap.                                        */
/*                                                                    */
/*   Reference       = Winthorn Functional Specification              */
/*                     Device Driver Interface Specification          */
/*                     Display Device Driver Design Specification     */
/*                                                                    */
/*                                                                    */
/**********************************************************************/
#define INCL_GRE_FONTS
#define INCL_GRE_LCID                                       
#define INCL_DDIMISC
#include <eddinclt.h>

#include <edddtypt.h>
#include <eddttypt.h>

#include <eddhcone.h>
#include <eddhtype.h>

#include <eddacone.h>
#include <eddbcone.h>
#include <eddecone.h>
#include <eddmcone.h>
#include <eddtcone.h>

#include <eddaextf.h>
#include <eddbextf.h>
#include <eddgextf.h>
#include <eddtextf.h>
#include <eddmextf.h>
#include <eddhmacr.h>

#ifndef VRAMPTR
#include <hwaccess.h>    DELETE
#endif /* ndef VRAMPTR */

#include <memman.h>
#ifdef VRAMPTR
#include <eddncach.h>
#endif /* VRAMPTR */

#ifdef TMP                                                  
#include <missing.h>                   // for GetDriverInfo32 def.
#endif 
#ifndef VRAMPTR
pBitmapHeader cached_pattern = NULL; DELETE
extern ULONG              fSeamlessActive; DELETE
#endif /* ndef VRAMPTR */
extern BitmapHeader       NewPatternTable[];
#ifndef VRAMPTR
extern ULONG              FreeVRAM; DELETE
#endif /* ndef VRAMPTR */
extern DDTType            DDT;
extern BYTE               cursor_status;

extern PVOID              pDefaultFont;

extern SHORT              softDrawInUse;

#ifndef SDBM20
/**********************************************************************/
/* we need this data structure to be in locked memory                 */
/* ie in the data segment                                             */
/**********************************************************************/
UnlockDataStruct   PatUnlockData;
#endif /* ndef SDBM20 */

/* private functions */
pBitmapHeader new_symbol_BM_header (pBitmapHeader OldSymbolHeader,
                                    USHORT        DefaultDataEnd );
USHORT set_marker_shape (VOID);
USHORT set_pattern_from_font(VOID);
USHORT set_pattern_from_bitmap(VOID);
VOID   initialise_bitmap_header(pBitmapHeader pBitmapHdr);
USHORT set_non_AA_marker(pBitmapHeader pBitmapHdr,
                         PFOCAFONT     pFocaFont);
USHORT edda_CreateCharacterBitmap( pBitmapHeader pBitmapHdr,
                                   PFOCAFONT     pFocaFont,
                                   USHORT        usCodePoint,
                                   USHORT        usCodePage );

#ifdef EDD_DEBUG
SHORT   DebugPattOn = 1;
#endif /* EDD_DEBUG */

/**********************************************************************/
/* PatternSetUp calculates the bitmap representing the desired pattern*/
/* and stores it in the DC instance data.                             */
/**********************************************************************/

USHORT edda_PatternSetUp (VOID)
{
    /******************************************************************/
    /* Local variables                                                */
    /******************************************************************/
    USHORT             Symbol;         /* desired pattern symbol      */


    /******************************************************************/
    /* Check for default set.                                         */
    /* If set is default then there is no problem.                    */
    /******************************************************************/
    if ( pdc->DCICurPtnAts.abnd.usSet == 0 )
    {
        /**************************************************************/
        /* Get Symbol number out the attribute bundle                 */
        /**************************************************************/
        Symbol = pdc->DCICurPtnAts.abnd.usSymbol;

        /**************************************************************/
        /* Check that the symbol is valid                             */
        /* First allow for symbols outside the range of 1 to          */
        /* NUMBER_PATTERNS.                                           */
        /**************************************************************/
        if (Symbol == PATSYM_DEFAULT)
        {
            Symbol = PATSYM_SOLID;
        }
        else if (Symbol == PATSYM_BLANK)
        {
            Symbol = PATSYM_NOSHADE;
        }

        if (Symbol > NUMBER_PATTERNS)
        {
            LogWarning(PMERR_INV_PATTERN_SET_ATTR);

            /**********************************************************/
            /* Invalid symbol so use default (solid)                  */
            /**********************************************************/
            Symbol = PATSYM_SOLID;
        }

        /**************************************************************/
        /* If the pattern is currently a character from a font then   */
        /* a bitmap will have been allocated for it - delete it now   */
        /**************************************************************/
        if ( pdc->DCIChanged & PATTERN_BITMAP_CREATED )
        {
            destroy_character_bitmap(pdc->TempPattern);

            /**********************************************************/
            /* Get rid of the bitmap header                           */
            /**********************************************************/
            FreeMemory(pdc->TempPattern);

            /**********************************************************/
            /* Reset the flags in pdc->                               */
            /**********************************************************/
            pdc->DCIChanged &=
                     ~(PATTERN_BITMAP_CREATED | PATTERN_HEADER_CREATED);
        }
        else if (pdc->DCIChanged & PATTERN_HEADER_CREATED)
        {
            /**********************************************************/
            /* bitmaps use the bits from the actual bitmap as the     */
            /* pattern - they dont keep the bits again                */
            /* so we only need wait for the bits to be finished with  */
            /* then delete the header that points to them             */
            /**********************************************************/
            /**********************************************************/
            /* question: why do we bother unlocking bits              */
            /* that we dont want to delete anyway ??                  */
            /**********************************************************/

            OutputString("Extra memory is allocated");
            OutputPair("pdc->TempPattern", pdc->TempPattern, HEX);

            /**********************************************************/
            /* DEFECT - 54940  (Joe Celi 10/2/92)                     */
            /*                                                        */
            /* If the pattern bitmap was cached then evict it.        */
            /**********************************************************/
           #ifdef VRAMPTR
            if ( BITMAP_IS_CACHED(pdc->TempPattern) )
               evict_cached_bitmap(pdc->TempPattern->bm_cache_slot);
           #endif /* VRAMPTR */

            /**********************************************************/
            /* free the header                                        */
            /**********************************************************/
            FreeMemory(pdc->TempPattern);

            /**********************************************************/
            /* Reset the flag in the DC                               */
            /**********************************************************/
            pdc->DCIChanged &= ~PATTERN_HEADER_CREATED;
        }

        /**************************************************************/
        /* Set DC pattern pointer to the pattern stored in global     */
        /* data.                                                      */
        /**************************************************************/
        pdc->TempPattern = &NewPatternTable[Symbol - 1];

        pdc->DCIChanged &= ~NEW_PATTERN_SYMBOL;

        return(OK);
    }

    /******************************************************************/
    /* The pattern must be either a font or a bitmap.                 */
    /*                                                                */
    /* If it is a font the defset field will either contain a value   */
    /* between 0 and 254 (an LCID for an AI format font) or a pointer */
    /* to a FocaFont.                                                 */
    /*                                                                */
    /* If it is a bitmap the defset field will contain a far pointer  */
    /* to the bitmap list entry.                                      */
    /*                                                                */
    /* We therefore have the problem that if we have a pointer, it    */
    /* could be to a font or a bitmap. I would imagine that           */
    /* somewhere in the AREABUNDLE there is a bit to tell us this,    */
    /* but it does not seem to be documented. We therefore work it    */
    /* out ourselves by looking at the first ULONG (4 bytes) of the   */
    /* structure. For a FocaFont this is defined to be 0xFFFFFFFE,    */
    /* and for a bitmap this will be a pointer to the actual bitmap   */
    /* bits (which won't be 0xFFFFFFFE!).                             */
    /******************************************************************/
#ifndef TMP                                                 
    if (((ULONG)pdc->DCICurPtnAts.adef.defSet > MAX_LCID) &&
        (*(PULONG)pdc->DCICurPtnAts.adef.defSet != 0xFFFFFFFEL) )
#else 
    /*----------------------------------------------------------------*/
    /* It seems that we have to assume usSet is bitmap LCID when      */
    /* defSet is NULL.                                                */
    /*----------------------------------------------------------------*/
    if ((pdc->DCICurPtnAts.adef.defSet == NULL) ||
       (((ULONG)pdc->DCICurPtnAts.adef.defSet > MAX_LCID) &&
        (*(PULONG)pdc->DCICurPtnAts.adef.defSet != 0xFFFFFFFEL)))
#endif 
    {
        /**************************************************************/
        /* The selected pattern is a bitmap.                          */
        /**************************************************************/
        if ( !set_pattern_from_bitmap() )
        {
            return(ERROR_ZERO);
        }
    }
    else
    {
        /**************************************************************/
        /* The selected pattern is a font.                            */
        /**************************************************************/
        if ( !set_pattern_from_font() )
        {
            return(ERROR_ZERO);
        }

    } /* pattern set is a font */


    pdc->DCIChanged &= ~NEW_PATTERN_SYMBOL;

    return(OK);

}





/**********************************************************************/
/* MarkerSetUp calculates the bitmap representing the desired marker  */
/* and stores it in the DC instance data.                             */
/**********************************************************************/

USHORT edda_MarkerSetUp (VOID)

{
    /******************************************************************/
    /* Local variables                                                */
    /******************************************************************/
    USHORT             Symbol;         /* desired marker symbol       */


    pdc->DCIChanged &= ~NEW_MARKER_SYMBOL;

    /******************************************************************/
    /* Check for default set.                                         */
    /* If set default then there is no problem.                       */
    /******************************************************************/
    if ( pdc->DCICurMrkAts.mbnd.usSet == 0 )
    {
        /**************************************************************/
        /* Get symbol number out the attribute bundle                 */
        /**************************************************************/
        if ( pdc->DCICurMrkAts.mbnd.usSymbol == MARKSYM_DEFAULT )
        {
            Symbol = MARKSYM_CROSS;
        }
        else
        {
            Symbol = pdc->DCICurMrkAts.mbnd.usSymbol;

            /**********************************************************/
            /* Check that the symbol is valid                         */
            /* First allow for symbols outside the range of 1 to      */
            /* NUMBER_PATTERNS.                                       */
            /**********************************************************/
            if (Symbol == MARKSYM_BLANK)
            {
                Symbol = MARKSYM_SMALLCIRCLE + 1;
            }
            else if (Symbol > MARKSYM_SMALLCIRCLE)
            {
                LogWarning(PMERR_INV_MARKER_SYMBOL_ATTR);

                /******************************************************/
                /* invalid symbol so use default (cross)              */
                /******************************************************/
                Symbol = MARKSYM_CROSS;
            }

        } /* non-default symbol */

        /**************************************************************/
        /* If any memory allocated for marker definition then free it */
        /* This is the case if                                        */
        /* DCIMarker is a pointer to a bitmap header rather than the  */
        /* default set symbol number                                  */
        /**************************************************************/
        if ( (USHORT)pdc->DCIMarker > MARKSYM_SMALLCIRCLE )
        {
            FreeMemory(pdc->DCIMarker);
            pdc->DCIChanged &= ~MARKER_BITMAP_CREATED;
        }

        /**************************************************************/
        /* for the default set DCIMarker is the symbol number         */
        /* No simulations are required                                */
        /* Decrement the symbol number since they number from         */
        /* one but we want it zero based for offsets                  */
        /**************************************************************/
        pdc->DCIMarker = (pBitmapHeader)(Symbol - 1);
        pdc->DCIMarkerSimReq = FALSE;

    }

    else /* not the default marker set */
    {
        /**************************************************************/
        /* To reach this point the marker set must be a font          */
        /* we would not have got to call this routine if the marker   */
        /* required simulation, so go ahead and set up the marker     */
        /**************************************************************/
        if ( !set_marker_shape() )
        {
            return(ERROR_ZERO);
        }

    } /* not the default marker set */

    return(OK);

} /* edda_MarkerSetUp */





VOID initialise_bitmap_header(pBitmapHeader pBitmapHdr)
{

    /******************************************************************/
    /* At 2.0 we no longer have a locked heap, so we dont have a      */
    /* physical address of the bitmap bits                            */
    /******************************************************************/
    pBitmapHdr->BMPhys = FNULL;

    /******************************************************************/
    /* initialise the rest of the bitmap header                       */
    /* note: Info.Width, .Height, and .Bitcount are set before calling*/
    /*       this routine                                             */
    /******************************************************************/
    pBitmapHdr->bm_cache_slot = BITMAP_NOT_CACHED;

    pBitmapHdr->DCHandle = FNULL;

    pBitmapHdr->BytesPerLine = (USHORT)(
             ((ULONG)pBitmapHdr->Info.Width *
              (ULONG)pBitmapHdr->Info.BitCount + 7) / 8);
    pBitmapHdr->Info.HWHeight = (USHORT)((ULONG)pBitmapHdr->Info.Height - 1);
    pBitmapHdr->BMSize = pBitmapHdr->Info.Height *
                                               pBitmapHdr->BytesPerLine;

} /* initialise_bitmap_header */




/**********************************************************************/
/* Pattern set is a bitmap                                            */
/**********************************************************************/
USHORT set_pattern_from_bitmap(VOID)


{
    /******************************************************************/
    /* Local Variables                                                */
    /******************************************************************/
    pBitmapHeader      pBitmapHdr;
    pBitmapHeader      pPatListEntry;  /* pattern bitmap list entry   */


    if ( pdc->DCIChanged & PATTERN_BITMAP_CREATED )
    {
        /**************************************************************/
        /* if we already have a bitmap header allocated for the       */
        /* pattern then hang on to it but destroy any allocated       */
        /* bitmap associated with it                                  */
        /* (we cant allocate a bitmap without also allocating a header*/
        /**************************************************************/
        pBitmapHdr = pdc->TempPattern;
        destroy_character_bitmap(pBitmapHdr);
        pdc->DCIChanged &= ~PATTERN_BITMAP_CREATED;
    }
    else if ( pdc->DCIChanged & PATTERN_HEADER_CREATED )
    {
        /**************************************************************/
        /* use the existing header                                    */
        /* dont change the flags because they say we already have     */
        /* a header but dont have a (character) bitmap                */
        /**************************************************************/
        pBitmapHdr = pdc->TempPattern;

        /**********************************************************/
        /* DEFECT - 55770  (Joe Celi 10/15/92)                    */
        /*                                                        */
        /* Get rid of the bitmap memory                           */
        /**********************************************************/
       #ifdef VRAMPTR
        if ( BITMAP_IS_CACHED(pBitmapHdr) )
           evict_cached_bitmap(pBitmapHdr->bm_cache_slot);
       #endif /* VRAMPTR */
    }
    else
    {
        /**************************************************************/
        /* Get some memory for the new bitmap header: pass the        */
        /* current symbol bitmap header pointer and the end address   */
        /* of the default pattern table                               */
        /**************************************************************/
        pdc->TempPattern =
        pBitmapHdr = new_symbol_BM_header( pdc->TempPattern,
                     ((USHORT)NewPatternTable) +
                     sizeof(BitmapHeader) * ENTRIES_IN_PATTERN_TABLE );

        if (!pBitmapHdr)
        {
#ifdef FIREWALLS
            haltproc();
#endif
            return(ERROR_ZERO);
        }

        /**************************************************************/
        /* flag that we now have a bitmap header                      */
        /**************************************************************/
        pdc->DCIChanged |= PATTERN_HEADER_CREATED;
#ifdef TMP                                                  
        /*------------------------------------------------------------*/
        /* To avoid confusion of BITMAP_IS_CACHED() macro, when this  */
        /* func error-returns before calling initialise_bitmap_header.*/
        /*------------------------------------------------------------*/
        pBitmapHdr->bm_cache_slot = BITMAP_NOT_CACHED;
#endif 
    }

    /**************************************************************/
    /* If the pattern is to be taken from a bitmap the defSet     */
    /* field in the area bundle contains a pointer to the header  */
    /* for the required bitmap                                    */
    /**************************************************************/
    pPatListEntry = (pBitmapHeader)pdc->DCICurPtnAts.adef.defSet;

#ifdef TMP                                                  
    /*----------------------------------------------------------------*/
    /* if the pointer is NULL, we need to get bitmap pointer from     */
    /*  engine.                                                       */
    /*----------------------------------------------------------------*/
    if (NULL == pPatListEntry)
    {
        HBITMAP hbmap;

        hbmap = GreQueryBitmapHandle (pdc->DCIhdc,
                                      pdc->DCICurPtnAts.abnd.usSet );
                                       /* get bitmap handle from LCID */
        if (GPI_ERROR == hbmap)        /* if cannot get handle        */
        {
#ifdef FIREWALLS
            haltproc();
#endif
            return ERROR_ZERO;
        }

        pPatListEntry = GetDriverInfo32( hbmap,
                                         DI_HBITMAP,
                                         pdc->DCIhdc );
                                       /* get bitmap ptr from handle  */
        if (GPI_ALTERROR == pPatListEntry)
        {
#ifdef FIREWALLS
            haltproc();
#endif
            return ERROR_ZERO;
        }
    }

#endif 
    pBitmapHdr->Info.Width = pPatListEntry->Info.Width;
    pBitmapHdr->Info.HWWidth  = (USHORT)(
                    (((ULONG)pBitmapHdr->Info.Width + 7) & 0xfff8) - 1);
    pBitmapHdr->Info.Height = pPatListEntry->Info.Height;

    /**************************************************************/
    /* Set pointer to start of bitmap data to be used             */
    /**************************************************************/
    pBitmapHdr->Bitmap = pPatListEntry->Bitmap;

    /******************************************************************/
    /* the pattern has the same format as the passed bitmap           */
    /******************************************************************/
    pBitmapHdr->Info.HWFormat = pPatListEntry->Info.HWFormat;
    pBitmapHdr->Info.BitCount = pPatListEntry->Info.BitCount;

    /******************************************************************/
    /* now set up the rest of the fields                              */
    /******************************************************************/
    initialise_bitmap_header(pBitmapHdr);

    return(OK);

} /* set_pattern_from_bitmap */



/**********************************************************************/
/* Pattern set is a font                                              */
/**********************************************************************/
USHORT set_pattern_from_font(VOID)
{
    /******************************************************************/
    /* Local Variables                                                */
    /******************************************************************/
    pBitmapHeader      pBitmapHdr;
    PFOCAFONT          pFocaFont;


    if (pdc->DCICurPtnAts.adef.defSet == 0)
    {
        /******************************************************/
        /* The default font is required.                      */
        /* Assign the default font address to pFocaFont       */
        /******************************************************/
        pFocaFont = (PFOCAFONT)pDefaultFont;
    }
    else
    {
        pFocaFont = (PFOCAFONT)pdc->DCICurPtnAts.adef.defSet;
    }

    /**********************************************************/
    /* Now check that we are not trying to use an             */
    /* anti-aliased character as a pattern. This is           */
    /* invalid.                                               */
    /**********************************************************/
    if ( (ULONG)pFocaFont <= MAX_LCID )
    {
        LogError(PMERR_INV_CHAR_SET_ATTR);
        return(ERROR_ZERO);
    }

    if ( pdc->DCIChanged & PATTERN_BITMAP_CREATED )
    {
        /**************************************************************/
        /* if we already have a bitmap header allocated for the       */
        /* pattern then hang on to it but destroy any allocated       */
        /* bitmap associated with it                                  */
        /* (we cant allocate a bitmap without also allocating a header*/
        /**************************************************************/
        pBitmapHdr = pdc->TempPattern;
        destroy_character_bitmap(pBitmapHdr);
        pdc->DCIChanged &= ~PATTERN_BITMAP_CREATED;
    }
    else if ( pdc->DCIChanged & PATTERN_HEADER_CREATED )
    {
        /**************************************************************/
        /* use the existing header                                    */
        /* dont change the flags because they say we already have     */
        /* a header but dont have a (character) bitmap                */
        /**************************************************************/
        pBitmapHdr = pdc->TempPattern;
    }
    else
    {
        /**************************************************************/
        /* Get some memory for the new bitmap header: pass the        */
        /* current symbol bitmap header pointer and the end address   */
        /* of the default pattern table                               */
        /**************************************************************/
        pdc->TempPattern =
        pBitmapHdr = new_symbol_BM_header( pdc->TempPattern,
                     ((USHORT)NewPatternTable) +
                     sizeof(BitmapHeader) * ENTRIES_IN_PATTERN_TABLE );

        if (!pBitmapHdr)
        {
#ifdef FIREWALLS
            haltproc();
#endif
            return(ERROR_ZERO);
        }

        /**************************************************************/
        /* flag that we now have a bitmap header                      */
        /**************************************************************/
        pdc->DCIChanged |= PATTERN_HEADER_CREATED;
#ifdef TMP                                                  
        /*------------------------------------------------------------*/
        /* To avoid confusion of BITMAP_IS_CACHED() macro, when this  */
        /* func error-returns before calling initialise_bitmap_header.*/
        /*------------------------------------------------------------*/
        pBitmapHdr->bm_cache_slot = BITMAP_NOT_CACHED;
#endif 
    }

    /**********************************************************/
    /* Create a new bitmap containing the requested character */
    /**********************************************************/
    if (!edda_CreateCharacterBitmap(
                           pBitmapHdr,
                           pFocaFont,
                           pdc->DCICurPtnAts.abnd.usSymbol,
                           (USHORT)pdc->DCICurPtnAts.adef.CodePage ))
    {
        /******************************************************/
        /* An error occurred. Return immediately.             */
        /******************************************************/
        return(ERROR_ZERO);
    }

    /******************************************************************/
    /* Mark the dc to indicate that we have created a bitmap for      */
    /* use as the pattern (containing a character from a font)        */
    /******************************************************************/
    pdc->DCIChanged |= PATTERN_BITMAP_CREATED;

    /*******************************************************************/
    /* patterns from fonts are always 1 bpp                            */
    /*******************************************************************/
    pBitmapHdr->Info.HWFormat = ONE_BIT_PER_PEL;
    pBitmapHdr->Info.BitCount = 1;

    /*******************************************************************/
    /* set up the rest of the bitmap header fields                     */
    /*******************************************************************/
    initialise_bitmap_header(pBitmapHdr);

#ifndef VRAMPTR
    if (
#ifdef SEAMLESS
         !fSeamlessActive &&
#endif /* SEAMLESS */
         !softDrawInUse )
    {
      /*****************************************************************/
      /* cache the character in VRAM                                   */
      /*****************************************************************/
      if ( cached_pattern != NULL )
      {
          cached_pattern->BMPhys = 0;
      }                                          DELETE

      CopyMemoryToVRAM( pBitmapHdr->Bitmap,
                        FreeVRAM,
                        pBitmapHdr->Info.HWWidth,
                        pBitmapHdr->Info.HWHeight,
                        ONE_BPP );

      cached_pattern = pBitmapHdr;
      pBitmapHdr->BMPhys = FreeVRAM;
    }
#endif /* ndef VRAMPTR */

    return(OK);

} /* set_pattern_from_font */





USHORT set_non_AA_marker(pBitmapHeader pBitmapHdr,
                         PFOCAFONT     pFocaFont)
{
    USHORT      char_width;     /* pel width of character             */
    /**********************************************************/
    /* Create a new bitmap containing the requested character */
    /**********************************************************/
    char_width = edda_CreateCharacterBitmap(
                                   pBitmapHdr,
                                   pFocaFont,
                                   pdc->DCICurMrkAts.mbnd.usSymbol,
                                   (USHORT)pdc->DCICurMrkAts.mdef.CodePage);
    if ( char_width == 0 )
    {
        /******************************************************/
        /* An error occurred. Return immediately.             */
        /******************************************************/
        return(ERROR_ZERO);
    }

    /******************************************************************/
    /* The Info.Width and Height fields contain the cell width and    */
    /* height but when the symbol is is being bltted we need to take  */
    /* account of the left and right margins (these are the source    */
    /* blt dimensions while Info.Width and Height are the source      */
    /* bitmap dimensions).                                            */
    /* The margin information is stored in the memory that was        */
    /* allocated for the bitmap bits. This assumes that the bitmap    */
    /* would have contained enough bits to cover the size of the      */
    /* MARKER_INFO.                                                   */
    /******************************************************************/
    pBitmapHdr->MarkerInfo.MarginWidth = 0;
    pBitmapHdr->MarkerInfo.MarginHeight = pBitmapHdr->Info.Width - char_width;

    /*************************************************************/
    /* mark the dc to indicate that we have created a bitmap for */
    /* use as the pattern (containing a character from a font)   */
    /*************************************************************/
    pdc->DCIChanged |= MARKER_BITMAP_CREATED;

    return(OK);

} /* set_non_AA_marker */







/**********************************************************************/
/* Marker set is a font or bitmap                                     */
/**********************************************************************/
USHORT set_marker_shape (VOID)
{
    /******************************************************************/
    /* Local Variables                                                */
    /******************************************************************/
    pBitmapHeader      pBitmapHdr;
    PFOCAFONT          pFocaFont;

    /**********************************************************/
    /* check for the default font.                            */
    /**********************************************************/
    if ( pdc->DCICurMrkAts.mdef.defSet == 0 )
    {
        /******************************************************/
        /* The default font is required                       */
        /******************************************************/
        pFocaFont = (PFOCAFONT)pDefaultFont;
    }

    else /* non-default font */
    {
        pFocaFont = (PFOCAFONT)pdc->DCICurMrkAts.mdef.defSet;

    } /* non-default font */

   /***********************************************************/
   /* if we've created a bitmap for a marker previously then  */
   /* delete it now but hang on to the bitmap header as we    */
   /* can recycle that                                        */
   /***********************************************************/
   if ( pdc->DCIChanged & MARKER_BITMAP_CREATED )
   {
       destroy_character_bitmap(pdc->DCIMarker);
       pBitmapHdr = pdc->DCIMarker;
       pdc->DCIChanged &= ~MARKER_BITMAP_CREATED;
   }
   else
   {
       /***********************************************************/
       /* get some memory for the new bitmap header: pass the     */
       /* current symbol bitmap header pointer and the maximum    */
       /* value it can take if it is actually the symbol number   */
       /* from the default set rather than a pointer to a non-    */
       /* default-set symbol-bitmap-header                        */
       /***********************************************************/
       /***************************************************************/
       /* This call is definitely bugged.  However it will need       */
       /* rewriting when we change our heap handling etc. so for the  */
       /* moment I wont fix the     (which I think is non trivial).   */
       /*                                                             */
       /* The basic     is that the subroutine expects an address of  */
       /* the marker data but we pass it a maximum index...           */
       /***************************************************************/
/**********************************************************************/
/* This routine looks ok to me... but we could do with a tidy up on   */
/* comments and structure field names, and parameter names too!!!     */
/**********************************************************************/
       pdc->DCIMarker =
           pBitmapHdr = new_symbol_BM_header(pdc->DCIMarker,
                                             MARKSYM_SMALLCIRCLE);
       if ( !pBitmapHdr )
       {
#ifdef FIREWALLS
            haltproc();
#endif
           return(ERROR_ZERO);
       }
   }

   if ( !set_non_AA_marker(pBitmapHdr, (PVOID)pFocaFont) )
   {
       /******************************************************/
       /* An error occurred. Return immediately.             */
       /******************************************************/
       return(ERROR_ZERO);
   }

   /*******************************************************************/
   /* markers are always forced to be 1 bpp                           */
   /*******************************************************************/
   pBitmapHdr->Info.HWFormat = ONE_BIT_PER_PEL;
   pBitmapHdr->Info.BitCount = 1;

   /*******************************************************************/
   /* set up the rest of the bitmap header fields                     */
   /*******************************************************************/
   initialise_bitmap_header(pBitmapHdr);

   return(OK);

} /* set_marker_shape */





pBitmapHeader new_symbol_BM_header (pBitmapHeader OldSymbolHeader,
                                    USHORT        DefaultDataEnd )
{
    pBitmapHeader pNewHeader;

    /******************************************************************/
    /* OldSymbolHeader is a pointer to the previously defined symbol  */
    /* header. DefaultDataEnd is the end address of the default       */
    /* symbol set in the data segment. If the old header is at a      */
    /* higher address then it is for a symbol from a non-default set. */
    /* If the previously defined symbol was not from the default set  */
    /* then we may have to unlock the memory. If it was then we need  */
    /* to allocate a bitmap header on the heap for the new symbol     */
    /******************************************************************/
    if ( (USHORT)OldSymbolHeader > DefaultDataEnd )
    {
        /**************************************************************/
        /* we're going to reuse the memory previously allocated for   */
        /* the old symbol bitmap header so return the pointer to this */
        /**************************************************************/
        return(OldSymbolHeader);

    }

    else /* last symbol was from default set */
    {
        /**************************************************************/
        /* Allocate memory for the bitmap header and return a pointer */
        /* to it (if the allocate fails this will be zero)            */
        /**************************************************************/
        pNewHeader = eddb_AllocBitmapHeader();

        /**************************************************************/
        /* Initialize the margin width and height to zero (ie. we     */
        /* will use all of the bitmap as the marker).                 */
        /**************************************************************/
#ifdef TMP                                                  
    if (pNewHeader)                    // only when alloc completes.
      {
#endif 
        pNewHeader->MarkerInfo.MarginWidth = 0;
        pNewHeader->MarkerInfo.MarginHeight = 0;
#ifdef TMP                                                  
      }
#endif 

        return(pNewHeader);
    }

} /* new_symbol_BM_header */




VOID destroy_character_bitmap(pBitmapHeader pBitmapHdr)
{
    /**************************************************************/
    /* we have created a bitmap for use as a pattern: occurs when */
    /* the pattern or marker symbol is a character from a font    */
    /* Delete the bitmap via the general bitmap deletion function */
    /**************************************************************/

    /**************************************************************/
    /* DEFECT - 55770  (Joe Celi 10/15/92)                        */
    /*                                                            */
    /* If the bitmap was cached then evict it.                    */
    /**************************************************************/
   #ifdef VRAMPTR
    if ( BITMAP_IS_CACHED(pBitmapHdr) )
       evict_cached_bitmap(pBitmapHdr->bm_cache_slot);
   #endif /* VRAMPTR */

    eddb_FreeMemForBitmap(pBitmapHdr);

} /* destroy_character_bitmap */




USHORT edda_CreateCharacterBitmap( pBitmapHeader pBitmapHdr,
                                   PFOCAFONT     pFocaFont,
                                   USHORT        usCodePoint,
                                   USHORT        usCodePage )
{
    /******************************************************************/
    /* Local variables                                                */
    /******************************************************************/
    USHORT      usGlyphIndex;
    PUSHORT     pCodePageVector;
    USHORT      usCellSize;
    USHORT      usFirstChar;
    PBYTE       pPerCharDefs;   /* Pointer to base char definitions   */
    PCHAR_DEFN  pCharDefn;      /* Pointer to char definition         */
    USHORT      xGlyphWidth;
    USHORT      yGlyphHeight;
    USHORT      xGlyphWidthInBytes;
    PBYTE       pNewBitmap;
    PBYTE       pImageData;
    USHORT      i, j;
    PBYTE       pDest;

    /******************************************************************/
    /* Set up various font pointers.                                  */
    /******************************************************************/
    pPerCharDefs = (PBYTE)pFocaFont + sizeof(FOCAFONT);
    usCellSize  = pFocaFont->fdDefinitions.usCellSize;
    usFirstChar = pFocaFont->fmMetrics.usFirstChar;

    /******************************************************************/
    /* Convert codepoint via codepage if necessary.                   */
    /******************************************************************/
#ifndef TMP                                                 
    if (usCodePage)
#else 
    /*================================================================*/
    /* SBCS Bug: we need mapping table only in this case              */
    /*================================================================*/
    if (usCodePage &&
        (pFocaFont->fmMetrics.usCodePage == 850) &&
        (pFocaFont->fmMetrics.usCodePage != usCodePage))
#endif 
    {
        /**************************************************************/
        /* Get the codepage vector.                                   */
        /**************************************************************/
        pCodePageVector = (PUSHORT)GreQueryCodePageVector(usCodePage);
        if (pCodePageVector == 0)
        {
            LogError(PMERR_INV_CODEPAGE);
            return(ERROR_ZERO);
        }
        usGlyphIndex = pCodePageVector[usCodePoint];
    }
    else
    {
        /**************************************************************/
        /* No codepage, so use the character directly as a glyph      */
        /* index.                                                     */
        /**************************************************************/
        usGlyphIndex = usCodePoint;
    }

    /******************************************************************/
    /* Now validate the glyph index, and make it relative to the      */
    /* first character of the font.                                   */
    /******************************************************************/
    if ((usGlyphIndex < usFirstChar) ||
        (usGlyphIndex > (pFocaFont->fmMetrics.usLastChar+usFirstChar)))
    {
        /**************************************************************/
        /* The glyph index is invalid. Use the default char from the  */
        /* metrics. Note that this value is relative to the first     */
        /* character in the font (which is what we want).             */
        /**************************************************************/
        usGlyphIndex = pFocaFont->fmMetrics.usDefaultChar;
    }
    else
    {
        /**************************************************************/
        /* The glyph index is valid. Adjust it so that it is relative */
        /* to the first character in the font                         */
        /**************************************************************/
        usGlyphIndex -= usFirstChar;
    }

    /******************************************************************/
    /* Read the char height.                                          */
    /******************************************************************/
    yGlyphHeight = pFocaFont->fdDefinitions.yCellHeight;

    /******************************************************************/
    /* Get a pointer to the char definition for the current character */
    /******************************************************************/
    pImageData = pPerCharDefs;

    /******************************************************************/
    /* Get the pointer to the character definition.                   */
    /******************************************************************/
    pCharDefn = pPerCharDefs + (usCellSize * usGlyphIndex);

    /******************************************************************/
    /* Now read the width of the character.                           */
    /******************************************************************/
    if (pFocaFont->fdDefinitions.fsChardef != FONTDEFCHAR3)
    {
        /**************************************************************/
        /* Proportional spaced or fixed spaced - use the char width   */
        /**************************************************************/
        xGlyphWidth = pCharDefn->nonabcDefn.usCharWidth;
        pImageData  = (PBYTE)pFocaFont +
                      pCharDefn->nonabcDefn.ulImageOffset;
    }
    else
    {
        /**************************************************************/
        /* ABC spaced - use the b space                               */
        /**************************************************************/
        xGlyphWidth = pCharDefn->abcDefn.usBSpace;
        pImageData  = (PBYTE)pFocaFont +
                      pCharDefn->abcDefn.ulImageOffset;
    }

    /******************************************************************/
    /* Fill in the fields in the bitmap header.                       */
    /******************************************************************/
    pBitmapHdr->Info.Width  = (USHORT)(((ULONG)xGlyphWidth + 7) & 0xFFF8);
    pBitmapHdr->Info.Height = yGlyphHeight;
    pBitmapHdr->Info.BitCount = 1;

    /******************************************************************/
    /* Now get some memory for the bitmap bits.                       */
    /******************************************************************/
    if (!eddb_AllocMemForBitmap(pBitmapHdr))
    {
        return(ERROR_ZERO);
    }

    /******************************************************************/
    /* Now copy the character bits over from Winthorn format          */
    /* (vertical strips) to bitmap format (horizontal rows).          */
    /******************************************************************/
    xGlyphWidthInBytes = (USHORT)(((ULONG)xGlyphWidth + 7) / 8);
    pNewBitmap = pBitmapHdr->Bitmap;

    for (i = xGlyphWidthInBytes; i--; )
    {
        pDest = pNewBitmap++;
        for (j = yGlyphHeight; j--; )
        {
            *pDest = *pImageData++;
            pDest += xGlyphWidthInBytes;
        }
    }

#ifdef EDD_DEBUG
#ifdef DEBUG_PATT
    if (DebugPattOn)
    {
        DebugOutput("New pattern:\n\r");
        pSrc = pBitmapHdr->Bitmap;
        for (i = 0; i < yGlyphHeight; i++ )
        {
            Mask = 0x80;
            for (j = 0; j < xGlyphWidth; j++ )
            {
                if (*pSrc & Mask)
                {
                    DebugOutput("*");
                }
                else
                {
                    DebugOutput(".");
                }

                if ((Mask >>= 1) == 0)
                {
                    Mask = 0x80;
                    pSrc++;
                }
            }
            DebugOutput("\n\r");
            if (Mask != 0x80)
            {
                pSrc++;
            }
        }
        DebugInput();
    }
#endif /* kkkkkk */
#endif /* EDD_DEBUG */
    return(xGlyphWidth);
}
