Usermode/libc - Fix strchr and strrchr behavior
[tpg/acess2.git] / Usermode / Applications / axwin3_src / WM / wm_render_text.c
index 362669b..01b82ff 100644 (file)
@@ -8,6 +8,8 @@
 #include <common.h>
 #include <wm_internals.h>
 #include <stdlib.h>
+#include <unicode.h>
+#include <limits.h>    // INT_MAX
 
 // === TYPES ===
 typedef struct sGlyph  tGlyph;
@@ -51,12 +53,11 @@ struct sFont
 
 
 // === PROTOTYPES ===
- int   WM_Render_DrawText(tWindow *Window, int X, int Y, int W, int H, tFont *Font, tColour Color, const char *Text);
-void   WM_Render_GetTextDims(tFont *Font, const char *Text, int *W, int *H);
+ int   WM_Render_DrawText(tWindow *Window, int X, int Y, int W, int H, tFont *Font, tColour Color, const char *Text, int MaxLen);
+void   WM_Render_GetTextDims(tFont *Font, const char *Text, int MaxLen, int *W, int *H);
 tGlyph *_GetGlyph(tFont *Font, uint32_t Codepoint);
-void   _RenderGlyph(tWindow *Window, short X, short Y, tGlyph *Glyph, uint32_t Color);
+void   _RenderGlyph(tWindow *Window, short X, short Y, short ClipW, short ClipH, tGlyph *Glyph, uint32_t Color);
 tGlyph *_SystemFont_CacheGlyph(tFont *Font, uint32_t Codepoint);
- int   ReadUTF8(const char *Input, uint32_t *Output);
 
 // === GLOBALS ===
 tFont  gSystemFont = {
@@ -67,7 +68,7 @@ tFont gSystemFont = {
 /**
  * \brief Draw text to the screen
  */
-int WM_Render_DrawText(tWindow *Window, int X, int Y, int W, int H, tFont *Font, tColour Colour, const char *Text)
+int WM_Render_DrawText(tWindow *Window, int X, int Y, int W, int H, tFont *Font, tColour Colour, const char *Text, int MaxLen)
 {
         int    xOfs = 0;
        tGlyph  *glyph;
@@ -78,46 +79,61 @@ int WM_Render_DrawText(tWindow *Window, int X, int Y, int W, int H, tFont *Font,
        
        if(!Text)       return 0;
 
+       if(MaxLen < 0)  MaxLen = INT_MAX;
+
+       X += Window->BorderL;
+       Y += Window->BorderT;
+
        // Check the bounds
-       if(W < 0 || X < 0 || X >= Window->W)    return 0;
-       if(X + W > Window->W)   W = Window->W - X;
+       if(W < 0 || X < 0 || X >= Window->RealW)        return 0;
+       if(X + W > Window->RealW)       W = Window->RealW - X;
        
-       if(H < 0 || Y < 0 || Y >= Window->H)    return 0;
-       if(Y + H > Window->H)   H = Window->H - Y;
+       if(H < 0 || Y < 0 || Y >= Window->RealH)        return 0;
+       if(Y + H > Window->RealH)       H = Window->RealH - Y;
        
+       // TODO: Catch trampling of decorations
+
        // Handle NULL font (system default monospace)
        if( !Font )     Font = &gSystemFont;
        
-       while( *Text )
+       while( MaxLen > 0 && *Text )
        {
+                int    len;
                // Read character
-               Text += ReadUTF8(Text, &ch);
+               len = ReadUTF8(Text, &ch);
+               Text += len;
+               MaxLen -= len;
                
                // Find (or load) the glyph
                glyph = _GetGlyph(Font, ch);
                if( !glyph )    continue ;      // If not found, just don't render it
                
-               // End render if it will overflow the provided range
-               if( xOfs + glyph->TrueWidth > W )
+               // End render if it will not fit at all
+               if( xOfs >= W )
                        break;
                
-               _RenderGlyph(Window, X + xOfs, Y, glyph, Colour);
+               _RenderGlyph(Window, X + xOfs, Y, W-xOfs, H, glyph, Colour);
                xOfs += glyph->Width;
        }
        
        return xOfs;
 }
 
-void WM_Render_GetTextDims(tFont *Font, const char *Text, int *W, int *H)
+void WM_Render_GetTextDims(tFont *Font, const char *Text, int MaxLen, int *W, int *H)
 {
         int    w=0, h=0;
        uint32_t        ch;
        tGlyph  *glyph;
        if( !Font )     Font = &gSystemFont;
        
-       while( *Text )
+       if(MaxLen < 0)  MaxLen = INT_MAX;
+
+       while( MaxLen > 0 && *Text )
        {
-               Text += ReadUTF8(Text, &ch);
+                int    len;
+               len = ReadUTF8(Text, &ch);
+               Text += len;
+               MaxLen -= len;
                glyph = _GetGlyph(Font, ch);
                if( !glyph )    continue;
                
@@ -156,7 +172,7 @@ tGlyph *_GetGlyph(tFont *Font, uint32_t Codepoint)
                                 prev = next, next = next->Next
                                 );
                        
-                       if( next->Codepoint == Codepoint )
+                       if( next && next->Codepoint == Codepoint )
                                return next;
                        
                }
@@ -170,7 +186,7 @@ tGlyph *_GetGlyph(tFont *Font, uint32_t Codepoint)
                                 prev && prev->Codepoint > Codepoint;
                                 next = prev, prev = prev->Prev
                                 );
-                       if( prev->Codepoint == Codepoint )
+                       if( prev && prev->Codepoint == Codepoint )
                                return prev;
                }
        }
@@ -219,7 +235,7 @@ tGlyph *_GetGlyph(tFont *Font, uint32_t Codepoint)
 
 /**
  */
-void _RenderGlyph(tWindow *Window, short X, short Y, tGlyph *Glyph, uint32_t Color)
+void _RenderGlyph(tWindow *Window, short X, short Y, short ClipW, short ClipH, tGlyph *Glyph, uint32_t Color)
 {
         int    xStart = 0, yStart = 0;
         int    x, y, dst_x;
@@ -239,16 +255,16 @@ void _RenderGlyph(tWindow *Window, short X, short Y, tGlyph *Glyph, uint32_t Col
        }
 
 //     _SysDebug("X = %i, Y = %i", X, Y);
-       outBuf = (uint32_t*)Window->RenderBuffer + Y*Window->W + X;
+       outBuf = (uint32_t*)Window->RenderBuffer + Y*Window->RealW + X;
        inBuf = Glyph->Bitmap + yStart*Glyph->TrueWidth;
 
-       for( y = yStart; y < Glyph->TrueHeight; y ++ )
+       for( y = yStart; y < Glyph->TrueHeight && ClipH--; y ++ )
        {
-               for( x = xStart, dst_x = 0; x < Glyph->TrueWidth; x ++, dst_x ++ )
+               for( x = xStart, dst_x = 0; x < Glyph->TrueWidth && dst_x < ClipW; x ++, dst_x ++ )
                {
                        outBuf[dst_x] = Video_AlphaBlend( outBuf[dst_x], Color, inBuf[x] );
                }
-               outBuf += Window->W;
+               outBuf += Window->RealW;
                inBuf += Glyph->TrueWidth;
        }
 }
@@ -310,67 +326,3 @@ tGlyph *_SystemFont_CacheGlyph(tFont *Font, uint32_t Codepoint)
        return ret;
 }
 
-
-/**
- * \fn int ReadUTF8(char *Input, uint32_t *Val)
- * \brief Read a UTF-8 character from a string
- */
-int ReadUTF8(const char *Input, uint32_t *Val)
-{
-       const uint8_t   *str = (const uint8_t *)Input;
-       *Val = 0xFFFD;  // Assume invalid character
-       
-       // ASCII
-       if( !(*str & 0x80) ) {
-               *Val = *str;
-               return 1;
-       }
-       
-       // Middle of a sequence
-       if( (*str & 0xC0) == 0x80 ) {
-               return 1;
-       }
-       
-       // Two Byte
-       if( (*str & 0xE0) == 0xC0 ) {
-               *Val = (*str & 0x1F) << 6;      // Upper 6 Bits
-               str ++;
-               if( (*str & 0xC0) != 0x80)      return -1;      // Validity check
-               *Val |= (*str & 0x3F);  // Lower 6 Bits
-               return 2;
-       }
-       
-       // Three Byte
-       if( (*str & 0xF0) == 0xE0 ) {
-               *Val = (*str & 0x0F) << 12;     // Upper 4 Bits
-               str ++;
-               if( (*str & 0xC0) != 0x80)      return -1;      // Validity check
-               *Val |= (*str & 0x3F) << 6;     // Middle 6 Bits
-               str ++;
-               if( (*str & 0xC0) != 0x80)      return -1;      // Validity check
-               *Val |= (*str & 0x3F);  // Lower 6 Bits
-               return 3;
-       }
-       
-       // Four Byte
-       if( (*str & 0xF1) == 0xF0 ) {
-               *Val = (*str & 0x07) << 18;     // Upper 3 Bits
-               str ++;
-               if( (*str & 0xC0) != 0x80)      return -1;      // Validity check
-               *Val |= (*str & 0x3F) << 12;    // Middle-upper 6 Bits
-               str ++;
-               if( (*str & 0xC0) != 0x80)      return -1;      // Validity check
-               *Val |= (*str & 0x3F) << 6;     // Middle-lower 6 Bits
-               str ++;
-               if( (*str & 0xC0) != 0x80)      return -1;      // Validity check
-               *Val |= (*str & 0x3F);  // Lower 6 Bits
-               return 4;
-       }
-       
-       // UTF-8 Doesn't support more than four bytes
-       return 4;
-}
-
-
-
-

UCC git Repository :: git.ucc.asn.au