/**************************************************************************************

                                  TDE_DRAWTEXT.C

***************************************************************************************/

#include "tde.h"

/**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~**
 NAME : TDE_bIsBreakChar
 VERSION : 1.0 / Yan

 AIM : Tells if a character can be a breakpoint of the line, in DT_WORDBREAK mode
**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~**/
BOOL TDE_bIsBreakChar (char c)
{
    // Any control character breaks the word
    if (c < 0x20) 
        return TRUE;

    // ' ' and '-' break the word. Other characters don't.
    switch (c)
    {
    case ' ':
    case '-':
        return TRUE;
        break;
    default:
        return FALSE;
        break;
    }
}

/**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~**
 NAME : TDE_xGetVerticalOffset
 VERSION : 1.0 / Yan

 AIM : Get the first vertical offset and the maximal number of lines for a character string
**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~**/
TDE_tdxValue TDE_xGetVerticalOffset (TDE_tdsTextBox *pTextBox, long *p_lNbLines)
{
    unsigned long       ulStyle;        // Format attributes
    TDE_tdxValue        xTopRect;       // Top of the format rectangle
    TDE_tdxValue        xBottomRect;    // Bottom of the format rectangle
    TDE_tdxValue        xHMax;          // Maximum high part in the font
    TDE_tdxValue        xVAMax;         // Maximum low part (vertical alignment) in the font
    TDE_tdsBitmapFont   *pFont;         // Pointer to the bitmap font

#ifdef TDE_DEBUG
    // Tests for reliability
    if (p_lNbLines == NULL)                     // NULL pointer to number of lines
        return 0;
    if (pTextBox == NULL)                       // NULL pointer to text box
        {   *p_lNbLines = 0;    return 0;   }
    if (pTextBox->eFontType != TDE_eFT_BITMAP)  // Non-bitmap font
        {   *p_lNbLines = 0;    return 0;   }
    if (pTextBox->p_stBFont == NULL)            // NULL pointer to bitmap font
        {   *p_lNbLines = 0;    return 0;   }
    if (pTextBox->p_stFormatRect == NULL)       // NULL pointer to format rectangle
        {   *p_lNbLines = 0;    return 0;   }
#endif

    // Short cuts
    ulStyle     = pTextBox->ulStyle;
    xTopRect    = pTextBox->p_stFormatRect->tdsSommet[0].xY;
    xBottomRect = pTextBox->p_stFormatRect->tdsSommet[2].xY;
    pFont       = pTextBox->p_stBFont;
    xHMax       = (TDE_tdxValue)pFont->usHMax;
    xVAMax      = (TDE_tdxValue)pFont->usVAMax;

    // Is the format rectangle high enough for at least one line ?
    if ((xBottomRect-xTopRect) < (xVAMax+xHMax))
    {
        *p_lNbLines = 0;
        return 0;
    }
    
    if (ulStyle & DT_VCENTER)       // Vertically centered, single line
    {
        *p_lNbLines = 1;
        return ((xBottomRect + xTopRect + (xHMax + xVAMax)*0.5) * 0.5);
    }
    else if (ulStyle & DT_BOTTOM)   // Bottom, single line
    {
        *p_lNbLines = 1;
        return (xBottomRect - xVAMax);
    }
    else                            // Top (default), either single or multiple line(s)
    {
        if (ulStyle & DT_SINGLELINE)    // Single line
            *p_lNbLines = 1;
        else                            // Multiple lines
            *p_lNbLines = (xBottomRect-xTopRect)/(xVAMax+xHMax);
        return (xTopRect + xHMax);
    }
}

/**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~**
 NAME : TDE_xGetHorizontalOffset
 VERSION : 1.0 / Yan

 AIM : Get the horizontal offset and the number of characters for the current line of a character string
**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~**/
TDE_tdxValue TDE_xGetHorizontalOffset (TDE_tdsTextBox *pTextBox, long lStartIndex, long *p_lEndIndex)
{
    unsigned long       ulStyle;        // Format attributes
    TDE_tdxValue        xLeftRect;      // Left of the format rectangle
    TDE_tdxValue        xRightRect;     // Right of the format rectangle
    TDE_tdxValue        xRectWidth;     // Width of the format rectangle
    TDE_tdxValue        xStrWidth;      // Width of the text-line
    TDE_tdxValue        xSpacing;       // Horizontal spacing between two characters
    TDE_tdsBitmapFont   *pFont;         // Pointer to the bitmap font
    TDE_tdsBitmapLetter **pLetter;      // Pointer to the array of pointers to bitmap letters
    char                *pString;       // Text string
    long                i, j;           // Counters
    unsigned char       c;              // Current char
    BOOL                bIsThereABreakChar;

#ifdef TDE_DEBUG
    // Tests for reliability
    if (p_lNbChar == NULL)                      // NULL pointer to number of characters
        return 0;
    if (pTextBox == NULL)                       // NULL pointer to text box
        {   *p_lNbChar = 0;    return 0;   }
    if (pTextBox->eFontType != TDE_eFT_BITMAP)  // Non-bitmap font
        {   *p_lNbChar = 0;    return 0;   }
    if (pTextBox->p_stBFont == NULL)            // NULL pointer to bitmap font
        {   *p_lNbChar = 0;    return 0;   }
    if (pTextBox->p_stFormatRect == NULL)       // NULL pointer to format rectangle
        {   *p_lNbChar = 0;    return 0;   }
#endif

    // Short cuts
    pFont       = pTextBox->p_stBFont;              // Pointer to the bitmap font
    pLetter     = pFont->p_stMBLetter;              // Pointer to the array of bitmap letters
    xSpacing    = (TDE_tdxValue) pFont->usHorzSep;  // Horizontal spacing between two characters
    pString     = pTextBox->p_cText;                // Text string
    ulStyle     = pTextBox->ulStyle;                // Format attributes
    xLeftRect   = pTextBox->p_stFormatRect->tdsSommet[0].xX;    // Left of format rectangle
    xRightRect  = pTextBox->p_stFormatRect->tdsSommet[1].xX;    // Right of format rectangle
    xRectWidth  = xRightRect - xLeftRect + xSpacing;            // Width of format rectangle
    xStrWidth   = 0;
    // Loop through the string until it exceeds the rect width
    // or it is finished or there is a carriage return
    for (i=lStartIndex;     (pString[i]!='\0') &&    // End of string
                            (pString[i]!=13)   &&    // Carriage return
                            (xStrWidth<xRectWidth); i++)
    {
        // Get current character
        c = *((unsigned char *)(&pString[i])) - 32;
        // If it is defined, add its width and the horizontal spacing
        if (c < TDE_kNBLETTERS)
            if (pLetter[c])
                xStrWidth += pLetter[c]->stBLetter.p_stSprite->stDim.xX + xSpacing;
    }
    // If carriage return, take also the line feed
    if (pString[i] == 13)
        if (pString[i+1] == 10)
            i++;
    // If it exceeds the rect width, remove the last character
    if (xStrWidth>xRectWidth)
    {
        i--;
        if (c < TDE_kNBLETTERS)
            if (pLetter[c])
                xStrWidth -= pLetter[c]->stBLetter.p_stSprite->stDim.xX + xSpacing;
    }
    // If we must keep word's integrity, do it !
    if (ulStyle & DT_WORDBREAK)
    {
        // Look for a break char in the line
        // (if there is no break char, we can't process
        // DT_WORDBREAK)
        bIsThereABreakChar = FALSE;
        for (j=lStartIndex; j<i; j++)
            if (TDE_bIsBreakChar(pString[j]))
                bIsThereABreakChar = TRUE;
        // If there is at least one break char, process...
        if (bIsThereABreakChar)
        {
            // Remove characters of breaked word (if necessary)
            while (!TDE_bIsBreakChar(pString[i]))
            {
                i--;
                c = *((unsigned char *)(&pString[i])) - 32;
                if (c < TDE_kNBLETTERS)
                    if (pLetter[c])
                        xStrWidth -= pLetter[c]->stBLetter.p_stSprite->stDim.xX + xSpacing;
            }
            // Remove from the width (but not from the count)
            // spaces before end on line (if any)
            if (pLetter[' '])
            {
                for (j=1; (pString[i-j]==' ') && ((i-j)>lStartIndex); j++)
                {
                    xStrWidth -= pLetter[' ']->stBLetter.p_stSprite->stDim.xX + xSpacing;
                }
                if ((i-j) == lStartIndex)
                    if (pString[i-j]==' ')
                        xStrWidth -= pLetter[' ']->stBLetter.p_stSprite->stDim.xX + xSpacing;
            }
        }
        // Add to the count (but not to the width) spaces after
        // end of line (if any)
        while (pString[i] == ' ') i++;
    }
    // Set number of characters
    *p_lEndIndex = i;
    // Compute horizontal offset
    if (ulStyle & DT_RIGHT)
        return (xRightRect - xStrWidth + xSpacing);
    else if (ulStyle & DT_CENTER)
        return xLeftRect + 0.5 * (xRectWidth - xStrWidth);
    else
        return xLeftRect;
}

/**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~**
 NAME : TDE_vDrawBitmapText
 VERSION : 2.0 / Yan
           1.0 / Franck

 AIM : Bitmap font rendering.
 
**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~**/
void TDE_vDrawBitmapText (GLD_tdpstViewportAttributes   p_stViewAttrib,
                          TDE_tdsTextBox                *pTextBox)
{
    TDE_tdsBitmapFont   *pFont;                 // Pointer to the bitmap font
    TDE_tdsBitmapLetter **pLetter;              // Pointer to the array of pointers to bitmap letters
    long                lNbLines;               // Number of displayable lines
    long                lCharIndex;             // Char index in the string
    long                lEndCharIndex;          // Char index of end of current line in the string
    long                lLineIndex;             // Line index in the string
    char                *pString;               // Text string
    char                cColorMode;             // Color mode (normal or reverse)
    TDE_tdxValue        xHOffset, xVOffset;     // Horizontal and vertical offsets
    TDE_tdxValue        xHSpacing;              // Horizontal spacing between two characters
    TDE_tdxValue        xHeightLine;            // Height of a line
    TDE_tdxValue        xHalfWidthChar;         // Half of the width of current char
    TDE_tdeCursorType   eCursorType;            // Type of the cursor (insert, overwrite, no cursor)
    long                lCursorIndex;           // Position of the cursor in the string
    long                i;                      // Counter
    unsigned char       c;                      // Current character
    
#ifdef TDE_DEBUG
    // Tests for reliability
    if (p_stViewAttrib == NULL)                 // NULL pointer to viewport attributes
        return;
    if (pTextBox == NULL)                       // NULL pointer to text box
        return;
    if (pTextBox->eFontType != TDE_eFT_BITMAP)  // Not a bitmap font
        return;
    if (pTextBox->p_stBFont == NULL)            // NULL pointer to font
        return;
#endif

    // Shortcuts
    pString         = pTextBox->p_cText;            // Pointer to the string
    if (pString == NULL)        // Test if the string is NULL
        return;       
    cColorMode      = pTextBox->cColorMode;         // Color mode (normal or reverse)
    lCursorIndex    = pTextBox->lCursorPosition;    // Cursor position
    eCursorType     = pTextBox->eCursorType;        // Cursor type
    pFont           = pTextBox->p_stBFont;          // Pointer to the font
    pLetter         = pFont->p_stMBLetter;          // Pointer to the array of bitmap letters
    xHSpacing   = (TDE_tdxValue) pFont->usHorzSep;  // Horizontal spacing between two characters
    xHeightLine = (TDE_tdxValue) (pFont->usVertSep + pFont->usHMax + pFont->usVAMax);  // Height of a line
    // Initialize the index at the beginning of the string
    lCharIndex  = 0;

    // Compute initial vertical offset
    xVOffset = TDE_xGetVerticalOffset (pTextBox, &lNbLines);

    // Loop on the displayable lines (while the string is not terminated)
    for (lLineIndex=0; (lLineIndex<lNbLines) && (pString[lCharIndex]!='\0'); lLineIndex++)
    {
        // Compute initial horizontal offset for the current line
        xHOffset = TDE_xGetHorizontalOffset (pTextBox, lCharIndex, &lEndCharIndex);
        // Loop on the characters of the current line
        for (i=lCharIndex; i<lEndCharIndex; i++)
        {
            // Get current character
            c = *((unsigned char *)(&pString[i])) - 32;
            // If the current character is defined
            if (c < TDE_kNBLETTERS)
                if (pLetter[c])
                {
                    // Compute the half of the width of the char
                    xHalfWidthChar = (pLetter[c]->stBLetter.p_stSprite->stDim.xX) * 0.5;
                    // Move horizontally to the center of the letter
                    xHOffset += xHalfWidthChar;
                    // Set coordinates of the center of the letter
                    pLetter[c]->stBLetter.stModifiedMatrix.stTranslateVertex.xX = xHOffset;
                    pLetter[c]->stBLetter.stModifiedMatrix.stTranslateVertex.xY = xVOffset -
                                 0.5*(pLetter[c]->stBLetter.p_stSprite->stDim.xY) +
                                 (TDE_tdxValue)(pLetter[c]->usVAlign);
                    // Different cases depending on the type of cursor
                    switch (eCursorType)
                    {
                    // No cursor
                    case TDE_eCT_NOCURSOR:
                        // Draw the character the normal way
                        if (cColorMode == 0)        // Normal color mode
                        {
                            TDE_vFastDrawMemorySpriteAbsolute
                                (p_stViewAttrib, &(pLetter[c]->stBLetter), pTextBox->p_stClipRect);
                        }
                        else                        // Negative color mode
                        {
                            TDE_vFastDrawMemorySpriteAbsoluteInvert
                                (p_stViewAttrib, &(pLetter[c]->stBLetter), pTextBox->p_stClipRect);
                        }
                        break;
                    // Draw overwrite cursor
                    case TDE_eCT_OVERWRITE:
                        // If the current position is the position of the cursor...
                        if (i == lCursorIndex)
                        {
                            // If the flicking state is set as 'show'...
                            if (TDE_g_cFlick)
                            {
                                // Draw the character inverted and without transparency
                                pLetter[c]->stBLetter.p_stSprite->c_NZ = 0;
                                TDE_vFastDrawMemorySpriteAbsoluteInvert
                                    (p_stViewAttrib, &(pLetter[c]->stBLetter), pTextBox->p_stClipRect);
                                pLetter[c]->stBLetter.p_stSprite->c_NZ = 1;
                            }
                            // If the flicking state is set as 'hide'...
                            else
                            {
                                // Draw the character the normal way
                                TDE_vFastDrawMemorySpriteAbsolute
                                    (p_stViewAttrib, &(pLetter[c]->stBLetter), pTextBox->p_stClipRect);
                            }                   
                        }
                        // If the current position is not the position of the cursor,
                        else
                        {
                            // Draw the character the normal way
                            if (cColorMode == 0)        // Normal color mode
                            {
                                TDE_vFastDrawMemorySpriteAbsolute
                                    (p_stViewAttrib, &(pLetter[c]->stBLetter), pTextBox->p_stClipRect);
                            }
                            else                        // Negative color mode
                            {
                                TDE_vFastDrawMemorySpriteAbsoluteInvert
                                    (p_stViewAttrib, &(pLetter[c]->stBLetter), pTextBox->p_stClipRect);
                            }
                        }
                        break;
                    // Draw insert cursor
                    case TDE_eCT_INSERT:
                        // Draw the character the normal way
                        if (cColorMode == 0)        // Normal color mode
                        {
                            TDE_vFastDrawMemorySpriteAbsolute
                                (p_stViewAttrib, &(pLetter[c]->stBLetter), pTextBox->p_stClipRect);
                        }
                        else                        // Negative color mode
                        {
                            TDE_vFastDrawMemorySpriteAbsoluteInvert
                                (p_stViewAttrib, &(pLetter[c]->stBLetter), pTextBox->p_stClipRect);
                        }
                        // If the current position is the position of the cursor...
                        if (i == lCursorIndex)
                        {
                            // If the flicking state is set as 'show'...
                            if (TDE_g_cFlick)
                            {
                                // Set coordinates of the insert cursor
                                pLetter[TDE_kINSERTCURSOR]->stBLetter.stModifiedMatrix.stTranslateVertex.xX
                                    = xHOffset - xHalfWidthChar;
                                pLetter[TDE_kINSERTCURSOR]->stBLetter.stModifiedMatrix.stTranslateVertex.xY
                                    = xVOffset - 0.5*(pLetter[TDE_kINSERTCURSOR]->stBLetter.p_stSprite->stDim.xY) +
                                        (TDE_tdxValue)(pLetter[TDE_kINSERTCURSOR]->usVAlign);
                                // Draw the insert cursor
                                TDE_vFastDrawMemorySpriteAbsolute
                                    (p_stViewAttrib, &(pLetter[TDE_kINSERTCURSOR]->stBLetter), pTextBox->p_stClipRect);
                            }
                        }
                        break;
                    default:
                        break;
                    } // switch
                    // Move horizontally to the beginning of next letter
                    xHOffset += xHalfWidthChar + xHSpacing;
                } // if the current character is defined
        } // loop on the characters in the current line
        // Update current character-index and vertical offset
        lCharIndex  =  lEndCharIndex;
        xVOffset    += xHeightLine;
    } // loop on each line
}


/**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~**
 NAME : TDE_vDrawBitmapTextWithRectAdjustment
 VERSION : 2.0 / Yan
           1.0 / Franck

 AIM : Set the height of a format rect depending on what you want to put into ....
 
**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~**/
void TDE_vTDE_vAdjustTextBoxFormatRect( TDE_tdsTextBox *pTextBox)
{
    TDE_tdsBitmapFont   *pFont;                 // Pointer to the bitmap font
    long                lNbLines;               // Number of displayable lines
    long                lCharIndex;             // Char index in the string
    long                lEndCharIndex;          // Char index of end of current line in the string
    char                *pString;               // Text string
    TDE_tdxValue        xHOffset;
    TDE_tdxValue        xHeightLine;            // Height of a line
    long                lTextLenght;
    
#ifdef TDE_DEBUG
    // Tests for reliability
    if (p_stViewAttrib == NULL)                 // NULL pointer to viewport attributes
        return;
    if (pTextBox == NULL)                       // NULL pointer to text box
        return;
    if (pTextBox->eFontType != TDE_eFT_BITMAP)  // Not a bitmap font
        return;
    if (pTextBox->p_stBFont == NULL)            // NULL pointer to font
        return;
#endif

    // Shortcuts
    pString         = pTextBox->p_cText;            // Pointer to the string
    if (pString == NULL)        // Test if the string is NULL
        return;
    lTextLenght = strlen(pString);
    if ( lTextLenght == 0 )
        return;

    pFont       = pTextBox->p_stBFont;          // Pointer to the font    
    xHeightLine = (TDE_tdxValue) (pFont->usVertSep + pFont->usHMax + pFont->usVAMax);  // Height of a line
    lCharIndex  = 0;
    lNbLines    = 0;

    do
    {
        // Compute initial horizontal offset for the current line
        xHOffset = TDE_xGetHorizontalOffset (pTextBox, lCharIndex, &lEndCharIndex);
        // Update current character-index and vertical offset
        lCharIndex  =  lEndCharIndex;
        lNbLines++;
        
    }while ( lEndCharIndex<lTextLenght );

    pTextBox->p_stFormatRect->tdsSommet[2].xY = pTextBox->p_stFormatRect->tdsSommet[0].xY + (lNbLines*xHeightLine);
    pTextBox->p_stFormatRect->tdsSommet[3].xY = pTextBox->p_stFormatRect->tdsSommet[2].xY;
}


/**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~**
 NAME : TDE_vDrawTrueTypeText
 VERSION : 2.0 / Yan
           1.0 / Franck

 AIM : True type font rendering.
**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~**/
void TDE_vDrawTrueTypeText (GLD_tdpstViewportAttributes   p_stViewAttrib,
                            TDE_tdsTextBox                *pTextBox)
{
    char                *pString;               // Text string
    TDE_tdsRect        *pFormatRect;            // Pointer to format rectangle (TDE structure)
    TDE_tdsRect        *pClipRect;              // Pointer to clipping rectangle (TDE structure)
    RECT                stFormatRect;           // Format rectangle (WINDOWS structure)
    RECT                stClipRect;             // Clipping rectangle (WINDOWS structure)
    LPDIRECTDRAWSURFACE lpBackSurf;             // Direct draw surface on which we must draw
    HDC                 hdc = NULL;             // Handle to DC (Display Context)
    TDE_tdsTrueTypeFont *pFont;                 // Pointer to the true type font

#ifdef TDE_DEBUG
    // Tests for reliability
    if (p_stViewAttrib == NULL)                 // NULL pointer to viewport attributes
        return;
    if (pTextBox == NULL)                       // NULL pointer to text box
        return;
    if (pTextBox->eFontType != TDE_eFT_TRUETYPE)// Not a true type font
        return;
    if (pTextBox->p_stTFont == NULL)            // NULL pointer to font
        return;
    if (pTextBox->p_stFormatRect == NULL)       // NULL pointer to format rectangle
        return;
    if (pTextBox->p_stClipRect == NULL)         // NULL pointer to clipping rectangle
        return;
#endif

    // Pointer to the string
    pString = pTextBox->p_cText;            // Pointer to the string
    if (pString == NULL)        // Test if the string is NULL
        return;
    pFont = pTextBox->p_stTFont;
    // Format rectangle
    pFormatRect         = pTextBox->p_stFormatRect;
    stFormatRect.top    = (long) pFormatRect->tdsSommet[0].xY;
    stFormatRect.bottom = (long) pFormatRect->tdsSommet[2].xY;
    stFormatRect.left   = (long) pFormatRect->tdsSommet[0].xX;
    stFormatRect.right  = (long) pFormatRect->tdsSommet[1].xX;
    // Clipping rectangle
    pClipRect           = pTextBox->p_stClipRect;
    stClipRect.top      = (long) pClipRect->tdsSommet[0].xY;
    stClipRect.bottom   = (long) pClipRect->tdsSommet[2].xY;
    stClipRect.left     = (long) pClipRect->tdsSommet[0].xX;
    stClipRect.right    = (long) pClipRect->tdsSommet[1].xX;
    // Get DC
    lpBackSurf = (LPDIRECTDRAWSURFACE)p_stViewAttrib->p_vReserved;
    IDirectDrawSurface_GetDC(lpBackSurf, &hdc);
    if (!hdc) return;
    // Set boundaries
    // SetBoundsRect (hdc, &stClipRect, DCB_RESET|DCB_ACCUMULATE);
    // Configure the DC to render text
    SetMapMode      (hdc, MM_TEXT);
    SetBkMode       (hdc, TRANSPARENT);
    // Select the font
    SelectObject    (hdc, (HGDIOBJ)pFont->hFont);
    // Select the color
    if (pTextBox->cColorMode == 0)              // Normal color mode
        SetTextColor    (hdc, pFont->lColor);
    else                                        // Reverse color mode
        SetTextColor    (hdc, ~(pFont->lColor));        
    // Let Windows do the job for us
    DrawText (hdc, pTextBox->p_cText, -1, &stFormatRect, pTextBox->ulStyle);
    // Release DC
    IDirectDrawSurface_ReleaseDC(lpBackSurf, hdc);
}

/**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~**
 NAME : TDE_vDrawTextInABox
 VERSION : 2.0 / Yan
           1.0 / Franck

 AIM : Display a text in a box.
 Formatting flags :
        DT_BOTTOM
        DT_CENTER
        DT_LEFT
        DT_RIGHT
        DT_SINGLELINE
        DT_TOP
        DT_VCENTER
        DT_WORDBREAK
 
**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~**/
void TDE_vDrawTextInABox (GLD_tdpstViewportAttributes   p_stViewAttrib,
                          TDE_tdsSuperObject            *p_stSuperObject,
                          BOOL                          bViewPortLocked)
{
    TDE_tdsTextBox      *pTextBox;              // Pointer to the text box
    
#ifdef TDE_DEBUG
    // Tests for reliability
    if (p_stSuperObject == NULL)                    // NULL pointer to super object
        return;
    if (p_stViewAttrib == NULL)                     // NULL pointer to viewport attributes
        return;
    if (p_stSuperObject->eType != TDE_eOT_TEXTBOX)  // The super object is not a text box
        return;
    if (p_stSuperObject->p_stTextBox == NULL)       // NULL pointer to text box
        return;
#endif

    pTextBox = p_stSuperObject->p_stTextBox;
    switch (pTextBox->eFontType)
    {
    case TDE_eFT_BITMAP:
        if (bViewPortLocked)    // Viewport must be locked
            TDE_vDrawBitmapText (p_stViewAttrib, pTextBox);
        break;
    case TDE_eFT_TRUETYPE:
        if (!bViewPortLocked)   // Viewport must not be locked
            TDE_vDrawTrueTypeText (p_stViewAttrib, pTextBox);
        break;
    }
}

