Usermode/AxWin3 - Added delete support to text input
authorJohn Hodge <[email protected]>
Mon, 21 Nov 2011 04:38:18 +0000 (12:38 +0800)
committerJohn Hodge <[email protected]>
Mon, 21 Nov 2011 04:38:18 +0000 (12:38 +0800)
- Moved UTF-8 code out from wm_render_text.c
- Added max bytes to text render functions
 > Note: They have a Feature-Bug where it will over-read by up to 3 bytes
 > Due to the UTF-8 parsing code, and is useful in some cases.
- Added INT_MIN and INT_MAX

12 files changed:
Usermode/Applications/axwin3_src/WM/Makefile
Usermode/Applications/axwin3_src/WM/decorator.c
Usermode/Applications/axwin3_src/WM/include/utf8.h [new file with mode: 0644]
Usermode/Applications/axwin3_src/WM/include/wm.h
Usermode/Applications/axwin3_src/WM/input.c
Usermode/Applications/axwin3_src/WM/renderers/menu.c
Usermode/Applications/axwin3_src/WM/renderers/widget/disptext.c
Usermode/Applications/axwin3_src/WM/renderers/widget/textinput.c
Usermode/Applications/axwin3_src/WM/utf-8.c [new file with mode: 0644]
Usermode/Applications/axwin3_src/WM/wm_input.c
Usermode/Applications/axwin3_src/WM/wm_render_text.c
Usermode/include/stdint.h

index a8d77cf..f0f9321 100644 (file)
@@ -6,7 +6,7 @@ CPPFLAGS += -I include/ -I ../include/
 
 DIR := Apps/AxWin/3.0
 BIN := AxWinWM
-OBJ := main.o input.o video.o ipc.o image.o
+OBJ := main.o input.o video.o ipc.o image.o utf-8.o
 OBJ += wm.o wm_input.o wm_render.o wm_render_text.o
 OBJ += decorator.o
 OBJ += renderers/passthru.o
index f91c0ca..937fb18 100644 (file)
@@ -83,7 +83,7 @@ void Decorator_Redraw(tWindow *Window)
 
        WM_Render_GetTextDims(
                NULL,   // TODO: Select font
-               Window->Title ? Window->Title : "jI",
+               Window->Title ? Window->Title : "jI", -1,
                &text_width, &text_height
                );
        WM_Render_DrawText(Window,
@@ -91,7 +91,7 @@ void Decorator_Redraw(tWindow *Window)
                Window->W - ciTitlebarHeight - 4, text_height,
                NULL,   // TODO: Select font
                (bActive ? cColourActive_TitleText : cColourInactive_TitleText),
-               Window->Title ? Window->Title : "--"
+               Window->Title ? Window->Title : "--", -1
                );
        
        // Maximized windows don't have any other borders
diff --git a/Usermode/Applications/axwin3_src/WM/include/utf8.h b/Usermode/Applications/axwin3_src/WM/include/utf8.h
new file mode 100644 (file)
index 0000000..3ecaeb0
--- /dev/null
@@ -0,0 +1,18 @@
+/*
+ * Acess2 GUI (AxWin) Version 3
+ * - By John Hodge (thePowersGang)
+ *
+ * utf8.h
+ * - UTF-8 Parsing header
+ */
+#ifndef _UTF8_H_
+#define _UTF8_H_
+
+#include <stdint.h>
+
+extern int     ReadUTF8(const char *Input, uint32_t *Val);
+extern int     ReadUTF8Rev(const char *Base, int Offset, uint32_t *Val);
+extern int     WriteUTF8(char *buf, uint32_t Val);
+
+#endif
+
index ad67f23..7807c90 100644 (file)
@@ -57,8 +57,32 @@ extern int   WM_SendMessage(tWindow *Source, tWindow *Dest, int MessageID, int Len
 // --- Rendering
 extern void    WM_Render_FillRect(tWindow *Window, int X, int Y, int W, int H, tColour Colour);
 extern void    WM_Render_DrawRect(tWindow *Window, int X, int Y, int W, int H, tColour Colour);
-extern int     WM_Render_DrawText(tWindow *Window, int X, int Y, int W, int H, tFont *Font, tColour Colour, const char *Text);
-extern void    WM_Render_GetTextDims(tFont *Font, const char *Text, int *W, int *H);
+/**
+ * \brief Draw text to a window
+ * \param Window       Destination Window
+ * \param X    X coordinate (Left)
+ * \param Y    Y coordinate (Top)
+ * \param W    Width of destination region
+ * \param H    Height of destination region
+ * \param Font Font to use
+ * \param Colour       Text foreground colour
+ * \param Text UTF-8 string to render
+ * \param MaxLen       Number of bytes in \a Text to read (Note: A final multi-byte sequence can exceed this count)
+ *
+ * \note As as noted in the \a MaxLen parameter, up to 3 more bytes may be read
+ *       if the final character is a multi-byte UTF-8 sequence. This allows 1
+ *       to be passed to only render a single character.
+ */
+extern int     WM_Render_DrawText(tWindow *Window, int X, int Y, int W, int H, tFont *Font, tColour Colour, const char *Text, int MaxLen);
+/**
+ * \brief Get the dimensions of a string if it was rendered
+ * \param Font Font to use
+ * \param Text UTF-8 string to be processed
+ * \param MaxLen       Number of bytes in \a Text to read (same caveat as WM_Render_DrawText applies)
+ * \param W    Pointer to an integer to store the width of the rendered text
+ * \param H    Pointer to an integer to store the height of the rendered text
+ */
+extern void    WM_Render_GetTextDims(tFont *Font, const char *Text, int MaxLen, int *W, int *H);
 extern void    WM_Render_DrawImage(tWindow *Window, int X, int Y, int W, int H, tImage *Image);
 extern void    WM_Render_SetTextCursor(tWindow *Window, int X, int Y, int W, int H, tColour Colour);
 // NOTE: Should really be elsewhere
index 4598502..da5b0d3 100644 (file)
@@ -74,17 +74,20 @@ void Input_HandleSelect(fd_set *set)
                if( read(giTerminalFD, &codepoint, sizeof(codepoint)) != sizeof(codepoint) )
                {
                        // oops, error
+                       _SysDebug("Terminal read failed?");
                }
        
+//             _SysDebug("Keypress 0x%x", codepoint);
+       
                switch(codepoint & 0xC0000000)
                {
                case 0x00000000:        // Key pressed
                        WM_Input_KeyDown(codepoint & KEY_CODEPOINT_MASK, scancode);
-               case 0x40000000:        // Key refire
+               case 0x80000000:        // Key release
                        WM_Input_KeyFire(codepoint & KEY_CODEPOINT_MASK, scancode);
                        scancode = 0;
                        break;
-               case 0x80000000:        // Key release
+               case 0x40000000:        // Key refire
                        WM_Input_KeyUp(codepoint & KEY_CODEPOINT_MASK, scancode);
                        scancode = 0;
                        break;
@@ -92,9 +95,6 @@ void Input_HandleSelect(fd_set *set)
                        scancode = codepoint & KEY_CODEPOINT_MASK;
                        break;
                }
-       
-               // TODO: pass on to message handler
-               _SysDebug("Keypress 0x%x", codepoint);
        }
 
        if(FD_ISSET(giMouseFD, set))
index 7e28670..ffd1db0 100644 (file)
@@ -168,7 +168,7 @@ void Renderer_Menu_Redraw(tWindow *Window)
                        w, ciMenu_ItemHeight,
                        gMenu_Font,
                        cMenu_LabelColour,
-                       item->Label
+                       item->Label, -1
                        );
                // Underline
                if(item->UnderlineW)
@@ -188,7 +188,7 @@ void Renderer_Menu_Redraw(tWindow *Window)
                                w, ciMenu_ItemHeight,
                                gMenu_Font,
                                cMenu_ShortcutColour,
-                               item->Shortcut
+                               item->Shortcut, -1
                                );
                }
                
@@ -277,23 +277,20 @@ int Renderer_Menu_int_AddItem(tWindow *Window, int Length, const tMenuMsg_AddIte
        {
                char    tmp = item->Label[item->KeyOffset];
                // Get width of preceding substring
-               item->Label[item->KeyOffset] = '\0';
-               WM_Render_GetTextDims(NULL, item->Label, &item->UnderlineX, NULL);
+               WM_Render_GetTextDims(NULL, item->Label, item->KeyOffset, &item->UnderlineX, NULL);
                // Get the width of the underlined character
-               // TODO: Fix for high UTF-8 characters
                item->Label[item->KeyOffset] = tmp;
-               tmp = item->Label[item->KeyOffset+1];
-               item->Label[item->KeyOffset+1] = '\0';
+               // NOTE: 1 makes only one character be parsed, even if it is >1 byte long
                WM_Render_GetTextDims(
-                       NULL, item->Label+item->KeyOffset,
+                       NULL, item->Label+item->KeyOffset, 1,
                        &item->UnderlineW, NULL
                        );
                item->Label[item->KeyOffset+1] = tmp;
        }
        // - Labels
-       WM_Render_GetTextDims(NULL, item->Label, &item->LabelWidth, NULL);
+       WM_Render_GetTextDims(NULL, item->Label, -1, &item->LabelWidth, NULL);
        if(item->Shortcut)
-               WM_Render_GetTextDims(NULL, item->Shortcut, &item->ShortcutWidth, NULL);
+               WM_Render_GetTextDims(NULL, item->Shortcut, -1, &item->ShortcutWidth, NULL);
        else
                item->ShortcutWidth = 0;
        
index dfdb358..d3abdea 100644 (file)
@@ -17,7 +17,7 @@ void Widget_DispText_Render(tWindow *Window, tElement *Element)
                Element->CachedX+1, Element->CachedY+1,
                Element->CachedW-2, Element->CachedH-2,
                NULL, TEXT_COLOUR,
-               Element->Text
+               Element->Text, -1
                );
 }
 
@@ -28,7 +28,7 @@ void Widget_DispText_UpdateText(tElement *Element, const char *Text)
        if(Element->Text)       free(Element->Text);
        Element->Text = strdup(Text);
 
-       WM_Render_GetTextDims(NULL, Element->Text, &w, &h);
+       WM_Render_GetTextDims(NULL, Element->Text, -1, &w, &h);
 
        // Apply edge padding
        w += 2; h += 2;
index 7c07700..2e21e78 100644 (file)
 #include <common.h>
 #include "./common.h"
 #include "./colours.h"
+#include <utf8.h>
+#include <string.h>
 
 struct sTextInputInfo
 {
         int    DrawOfs;        // Byte offset for the leftmost character
         int    CursorXOfs;     // Pixel offset of the cursor
+       
+        int    CursorByteOfs;
+        int    Length;
 };
 
+// === CONSTANTS ===
+const int      ciTextInput_MarginT = 3;
+const int      ciTextInput_MarginB = 3;
+const int      ciTextInput_MarginV = 6;        // Sum of above
+const int      ciTextInput_MarginL = 3;
+const int      ciTextInput_MarginR = 3;
+const int      ciTextInput_MarginH = 6;
+
+// === GLOBALS ===
+tFont  *gpTextInput_Font = NULL;
+
+// === CODE ===
 void Widget_TextInput_Render(tWindow *Window, tElement *Element)
 {
        struct sTextInputInfo   *info = (void*)Element->Data;
        struct sWidgetWin       *wininfo = Window->RendererInfo;
        
+       // Scroll view when X offset reaches either end
+       while(info->CursorXOfs >= Element->CachedW - ciTextInput_MarginH)
+       {
+                int    w;
+               uint32_t        cp;
+               info->DrawOfs += ReadUTF8( &Element->Text[info->DrawOfs], &cp );
+               WM_Render_GetTextDims(
+                       gpTextInput_Font,
+                       &Element->Text[info->DrawOfs], info->CursorByteOfs - info->DrawOfs,
+                       &w, NULL
+                       );
+               info->CursorXOfs = w;
+       }
+       if(info->CursorXOfs < 0)
+       {
+               info->DrawOfs = info->CursorByteOfs;
+               info->CursorXOfs = 0;
+       }
+       
+
+       // Borders
        WM_Render_FillRect(Window, 
                Element->CachedX, Element->CachedY,
                Element->CachedW, Element->CachedH,
@@ -39,21 +77,21 @@ void Widget_TextInput_Render(tWindow *Window, tElement *Element)
                );
        
        // Text
+       // - Pre-cursor
        WM_Render_DrawText(Window,
-               Element->CachedX+2, Element->CachedY+2,
-               Element->CachedW-4, Element->CachedW-4,
-               NULL, TEXTINPUT_TEXT,
-               &Element->Text[info->DrawOfs]
+               Element->CachedX+ciTextInput_MarginL, Element->CachedY+ciTextInput_MarginT,
+               Element->CachedW-ciTextInput_MarginH, Element->CachedH-ciTextInput_MarginV,
+               gpTextInput_Font, TEXTINPUT_TEXT,
+               &Element->Text[info->DrawOfs], -1
                );
 
-       // TODO: Determine if this element has focus
+       // Cursor
        if( wininfo->FocusedElement == Element )
        {
-               // TODO: Multiple Cursors
                WM_Render_SetTextCursor(Window,
-                       Element->CachedX+2+info->CursorXOfs,
-                       Element->CachedY+2,
-                       1, Element->CachedH-4,
+                       Element->CachedX+ciTextInput_MarginL+info->CursorXOfs,
+                       Element->CachedY+ciTextInput_MarginR,
+                       1, Element->CachedH-ciTextInput_MarginV,
                        TEXTINPUT_TEXT
                        );
        }
@@ -65,12 +103,12 @@ void Widget_TextInput_Init(tElement *Element)
         int    h;
 
        // TODO: Select font correctly  
-       WM_Render_GetTextDims(NULL, "jJ", NULL, &h);
+       WM_Render_GetTextDims(gpTextInput_Font, "jy|qJ", -1, NULL, &h);
 
-       h += 2+2;       // Border padding       
+       h += ciTextInput_MarginV;       // Border padding
 
        Element->MinH = h;
-       Element->MinW = 4;
+       Element->MinW = ciTextInput_MarginH;
 
        info = Element->Data = malloc(sizeof(*info));
        info->DrawOfs = 0;
@@ -79,9 +117,69 @@ void Widget_TextInput_Init(tElement *Element)
        // No need to explicitly update parent min dims, as the AddElement routine does that    
 }
 
-int Widget_TextInput_KeyFire(tElement *Ele, int KeySym, int Character)
+int Widget_TextInput_KeyFire(tElement *Element, int KeySym, int Character)
 {
-       _SysDebug("Key 0x%x fired ('%c')", Character, Character);
+       struct sTextInputInfo   *info = Element->Data;
+        int    len;
+        int    w;
+       char    *dest;
+       uint32_t        cp;
+
+//     _SysDebug("Key 0x%x fired ('%c')", Character, Character);
+       
+       if( Character == 0 )
+               return 0;
+
+       // TODO: Don't hard code
+       if(Character > 0x30000000)      return 0;
+
+       switch(Character)
+       {
+       case '\t':
+               return 0;
+       
+       case '\b':
+               // Check if there is anything to delete
+               if( info->CursorByteOfs == 0 )  return 0;
+               // Get character to be deleted
+               len = ReadUTF8Rev(Element->Text, info->CursorByteOfs, &cp);
+               info->CursorByteOfs -= len;
+               dest = &Element->Text[info->CursorByteOfs];
+//             _SysDebug("\\b, len = %i, removing '%.*s'", len, len, dest);
+               WM_Render_GetTextDims(gpTextInput_Font, dest, len, &w, 0);
+               // Remove from buffer
+               memmove(dest, &dest[len], info->Length - info->CursorByteOfs - len);
+               info->Length -= len;
+               Element->Text[info->Length] = '\0';
+               // Adjust cursor
+               info->CursorXOfs -= w;
+               break;
+       default:
+               if(Character >= 0x30000000)     return 0;
+               if(Character < ' ')     return 0;
+
+               // Get required length
+               len = WriteUTF8(NULL, Character);
+
+               // Create space (possibly in the middle)        
+               Element->Text = realloc(Element->Text, info->Length + len + 1);
+               dest = &Element->Text[info->CursorByteOfs];
+               memmove(&dest[len], dest, info->Length - info->CursorByteOfs);
+               // Add the character
+               WriteUTF8(dest, Character);
+               info->CursorByteOfs += len;
+               info->Length += len;
+               Element->Text[info->Length] = '\0';
+
+               // Update the cursor position
+               // - Scrolling is implemented in render function (CachedW/CachedH are invalid atm)
+               WM_Render_GetTextDims(gpTextInput_Font, dest, len, &w, NULL);
+               info->CursorXOfs += w;
+       }
+
+       // TODO: Have a Widget_ function to do this instead
+       WM_Invalidate(Element->Window);
+       
        return 0;
 }
 
diff --git a/Usermode/Applications/axwin3_src/WM/utf-8.c b/Usermode/Applications/axwin3_src/WM/utf-8.c
new file mode 100644 (file)
index 0000000..5c08828
--- /dev/null
@@ -0,0 +1,153 @@
+/*
+ * Acess2 GUI (AxWin) Version 3
+ * - By John Hodge (thePowersGang)
+ *
+ * utf-8.c
+ * - UTF-8 Parsing code
+ */
+#include <stdint.h>
+#include <utf8.h>
+
+/**
+ * \brief Read a UTF-8 character from a string
+ * \param Input        Source UTF-8 encoded string
+ * \param Val  Destination for read codepoint
+ * \return Number of bytes read/used
+ */
+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;
+}
+
+/**
+ * \brief Get the UTF-8 character before the 
+ * \
+ */
+int ReadUTF8Rev(const char *Base, int Offset, uint32_t *Val)
+{
+        int    len = 0;
+       
+       // Scan backwards for the beginning of the character
+       while( Offset > 0 && (Base[Offset--] & 0xC0) == 0x80 )
+               len ++;
+       // Invalid string (no beginning)
+       if(Offset == 0 && (Base[Offset] & 0xC0) == 0x80 )
+               return len;
+       
+       len ++; // First character
+       if( ReadUTF8(Base+Offset, Val) != len ) {
+               *Val = 0xFFFD;
+       }
+       return len;
+}
+
+/**
+ * \brief Write a UTF-8 character sequence to a string
+ * \param buf  Destination buffer (must have at least 4 bytes available)
+ * \param Val  Unicode codepoint to write
+ * \return Number of bytes written
+ * \note Does not NULL terminate the string in \a buf
+ */
+int WriteUTF8(char *buf, uint32_t Val)
+{
+       uint8_t *str = (void*)buf;
+       
+       // ASCII
+       if( Val < 128 ) {
+               if(str) {
+                       *str = Val;
+               }
+               return 1;
+       }
+       
+       // Two Byte
+       if( Val < 0x8000 ) {
+               if(str) {
+                       *str = 0xC0 | (Val >> 6);
+                       str ++;
+                       *str = 0x80 | (Val & 0x3F);
+               }
+               return 2;
+       }
+       
+       // Three Byte
+       if( Val < 0x10000 ) {
+               if(str) {
+                       *str = 0xE0 | (Val >> 12);
+                       str ++;
+                       *str = 0x80 | ((Val >> 6) & 0x3F);
+                       str ++;
+                       *str = 0x80 | (Val & 0x3F);
+               }
+               return 3;
+       }
+       
+       // Four Byte
+       if( Val < 0x110000 ) {
+               if(str) {
+                       *str = 0xF0 | (Val >> 18);
+                       str ++;
+                       *str = 0x80 | ((Val >> 12) & 0x3F);
+                       str ++;
+                       *str = 0x80 | ((Val >> 6) & 0x3F);
+                       str ++;
+                       *str = 0x80 | (Val & 0x3F);
+               }
+               return 4;
+       }
+       
+       // UTF-8 Doesn't support more than four bytes
+       return 0;
+}
+
index dc8d8ac..1fc49f8 100644 (file)
@@ -122,6 +122,9 @@ void WM_Input_KeyDown(uint32_t Character, uint32_t Scancode)
 void WM_Input_KeyFire(uint32_t Character, uint32_t Scancode)
 {
        struct sWndMsg_KeyAction        msg;
+
+       // TODO: Properly translate into KeySyms and Unicode
+
        msg.KeySym = Scancode;
        msg.UCS32 = Character;
        WM_SendMessage(NULL, gpWM_FocusedWindow, WNDMSG_KEYFIRE, sizeof(msg), &msg);
index 4ce35cb..d189e5e 100644 (file)
@@ -8,6 +8,7 @@
 #include <common.h>
 #include <wm_internals.h>
 #include <stdlib.h>
+#include <utf8.h>
 
 // === TYPES ===
 typedef struct sGlyph  tGlyph;
@@ -51,12 +52,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);
 tGlyph *_SystemFont_CacheGlyph(tFont *Font, uint32_t Codepoint);
- int   ReadUTF8(const char *Input, uint32_t *Output);
 
 // === GLOBALS ===
 tFont  gSystemFont = {
@@ -67,7 +67,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,6 +78,7 @@ 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;
@@ -94,10 +95,13 @@ int WM_Render_DrawText(tWindow *Window, int X, int Y, int W, int H, tFont *Font,
        // 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);
@@ -114,16 +118,21 @@ int WM_Render_DrawText(tWindow *Window, int X, int Y, int W, int H, tFont *Font,
        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;
                
@@ -316,67 +325,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;
-}
-
-
-
-
index 477f8eb..d0f949e 100644 (file)
@@ -3,6 +3,9 @@
 #ifndef _STDINT_H_
 #define _STDINT_H_
 
+#define INT_MIN        -0x80000000
+#define INT_MAX        0x7FFFFFFF
+
 typedef unsigned char  uint8_t;
 typedef unsigned short uint16_t;
 typedef unsigned int   uint32_t;

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