sync with trunk r46493
[reactos.git] / dll / win32 / riched20 / reader.c
index f456a09..9f88cf7 100644 (file)
@@ -109,7 +109,7 @@ int _RTFGetChar(RTF_Info *info)
                if (stream->dwSize == 0)
                        return EOF;
        }
-       ch = stream->buffer[stream->dwUsed++];
+       ch = (unsigned char)stream->buffer[stream->dwUsed++];
        if (!ch)
                 return EOF;
        return ch;
@@ -169,6 +169,39 @@ RTFDestroy(RTF_Info *info)
        }
        RTFDestroyAttrs(info);
        heap_free(info->cpOutputBuffer);
+        while (info->tableDef)
+        {
+                RTFTable *tableDef = info->tableDef;
+                info->tableDef = tableDef->parent;
+                heap_free(tableDef);
+        }
+}
+
+
+
+/* ---------------------------------------------------------------------- */
+
+/*
+ * Callback table manipulation routines
+ */
+
+
+/*
+ * Install or return a writer callback for a token class
+ */
+
+static void RTFSetClassCallback(RTF_Info *info, int class, RTFFuncPtr callback)
+{
+       if (class >= 0 && class < rtfMaxClass)
+               info->ccb[class] = callback;
+}
+
+
+static RTFFuncPtr RTFGetClassCallback(const RTF_Info *info, int class)
+{
+       if (class >= 0 && class < rtfMaxClass)
+               return info->ccb[class];
+       return NULL;
 }
 
 
@@ -186,15 +219,13 @@ void RTFInit(RTF_Info *info)
        {
                info->rtfTextBuf = heap_alloc (rtfBufSiz);
                info->pushedTextBuf = heap_alloc (rtfBufSiz);
-               if (info->rtfTextBuf == NULL || info->pushedTextBuf == NULL)
+               if (info->rtfTextBuf == NULL || info->pushedTextBuf == NULL) {
                        ERR ("Cannot allocate text buffers.\n");
+                       return;
+               }
                info->rtfTextBuf[0] = info->pushedTextBuf[0] = '\0';
        }
 
-       heap_free (info->inputName);
-       heap_free (info->outputName);
-       info->inputName = info->outputName = NULL;
-
        for (i = 0; i < rtfMaxClass; i++)
                RTFSetClassCallback (info, i, NULL);
        for (i = 0; i < rtfMaxDestination; i++)
@@ -235,68 +266,13 @@ void RTFInit(RTF_Info *info)
                info->dwMaxCPOutputCount = 0x1000;
                info->cpOutputBuffer = heap_alloc(info->dwMaxCPOutputCount);
        }
-}
-
-/*
- * Set or get the input or output file name.  These are never guaranteed
- * to be accurate, only insofar as the calling program makes them so.
- */
 
-void RTFSetInputName(RTF_Info *info, const char *name)
-{
-       info->inputName = RTFStrSave (name);
-       if (info->inputName == NULL)
-               ERR ("RTFSetInputName: out of memory\n");
-}
-
-
-char *RTFGetInputName(const RTF_Info *info)
-{
-       return (info->inputName);
+        info->tableDef = NULL;
+        info->nestingLevel = 0;
+        info->canInheritInTbl = FALSE;
+        info->borderType = 0;
 }
 
-
-void RTFSetOutputName(RTF_Info *info, const char *name)
-{
-       info->outputName = RTFStrSave (name);
-       if (info->outputName == NULL)
-               ERR ("RTFSetOutputName: out of memory\n");
-}
-
-
-char *RTFGetOutputName(const RTF_Info *info)
-{
-       return (info->outputName);
-}
-
-
-
-/* ---------------------------------------------------------------------- */
-
-/*
- * Callback table manipulation routines
- */
-
-
-/*
- * Install or return a writer callback for a token class
- */
-
-void RTFSetClassCallback(RTF_Info *info, int class, RTFFuncPtr callback)
-{
-       if (class >= 0 && class < rtfMaxClass)
-               info->ccb[class] = callback;
-}
-
-
-RTFFuncPtr RTFGetClassCallback(const RTF_Info *info, int class)
-{
-       if (class >= 0 && class < rtfMaxClass)
-               return info->ccb[class];
-       return NULL;
-}
-
-
 /*
  * Install or return a writer callback for a destination type
  */
@@ -308,7 +284,7 @@ void RTFSetDestinationCallback(RTF_Info *info, int dest, RTFFuncPtr callback)
 }
 
 
-RTFFuncPtr RTFGetDestinationCallback(const RTF_Info *info, int dest)
+static RTFFuncPtr RTFGetDestinationCallback(const RTF_Info *info, int dest)
 {
        if (dest >= 0 && dest < rtfMaxDestination)
                return info->dcb[dest];
@@ -393,6 +369,32 @@ void RTFSkipGroup(RTF_Info *info)
        }
 }
 
+/*
+ * Do no special processing on the group.
+ *
+ * This acts as a placeholder for a callback in order to indicate that it
+ * shouldn't be ignored.  Instead it will fallback on the loop in RTFRead.
+ */
+void RTFReadGroup (RTF_Info *info)
+{
+}
+
+
+/*
+ * Install or return a token reader hook.
+ */
+
+void RTFSetReadHook(RTF_Info *info, RTFFuncPtr f)
+{
+       info->readHook = f;
+}
+
+
+static RTFFuncPtr RTFGetReadHook(const RTF_Info *info)
+{
+       return (info->readHook);
+}
+
 
 /*
  * Read one token.  Call the read hook if there is one.  The
@@ -425,23 +427,7 @@ int RTFGetToken(RTF_Info *info)
 }
 
 
-/*
- * Install or return a token reader hook.
- */
-
-void RTFSetReadHook(RTF_Info *info, RTFFuncPtr f)
-{
-       info->readHook = f;
-}
-
-
-RTFFuncPtr RTFGetReadHook(const RTF_Info *info)
-{
-       return (info->readHook);
-}
-
-
-void RTFUngetToken(RTF_Info *info)
+static void RTFUngetToken(RTF_Info *info)
 {
        if (info->pushedClass >= 0)     /* there's already an ungotten token */
                ERR ("cannot unget two tokens\n");
@@ -452,14 +438,15 @@ void RTFUngetToken(RTF_Info *info)
        info->pushedMinor = info->rtfMinor;
        info->pushedParam = info->rtfParam;
        lstrcpyA (info->pushedTextBuf, info->rtfTextBuf);
-}
-
-
-int RTFPeekToken(RTF_Info *info)
-{
-       _RTFGetToken (info);
-       RTFUngetToken (info);
-       return (info->rtfClass);
+       /* The read hook decrements stackTop on rtfEndGroup, so
+        * increment the value to compensate for it being decremented
+        * twice due to the RTFUngetToken. */
+       if(RTFCheckCM (info, rtfGroup, rtfEndGroup))
+       {
+               info->stack[info->stackTop].style = info->style;
+               ME_AddRefStyle(info->style);
+               info->stackTop++;
+       }
 }
 
 
@@ -652,7 +639,7 @@ static void _RTFGetToken2(RTF_Info *info)
                }
 
                /* escaped char */
-               /*if (index (":{}\\", c) != (char *) NULL)*/ /* escaped char */
+               /*if (index (":{}\\", c) != NULL)*/ /* escaped char */
                if (c == ':' || c == '{' || c == '}' || c == '\\')
                {
                        info->rtfClass = rtfText;
@@ -767,29 +754,6 @@ static int GetChar(RTF_Info *info)
 }
 
 
-/*
- * Synthesize a token by setting the global variables to the
- * values supplied.  Typically this is followed with a call
- * to RTFRouteToken().
- *
- * If a param value other than rtfNoParam is passed, it becomes
- * part of the token text.
- */
-
-void RTFSetToken(RTF_Info *info, int class, int major, int minor, int param, const char *text)
-{
-       info->rtfClass = class;
-       info->rtfMajor = major;
-       info->rtfMinor = minor;
-       info->rtfParam = param;
-       if (param == rtfNoParam)
-               lstrcpyA(info->rtfTextBuf, text);
-       else
-               sprintf (info->rtfTextBuf, "%s%d", text, param);
-       info->rtfTextLen = lstrlenA (info->rtfTextBuf);
-}
-
-
 /* ---------------------------------------------------------------------- */
 
 /*
@@ -823,7 +787,6 @@ static void ReadFontTbl(RTF_Info *info)
        RTFFont         *fp = NULL;
        char            buf[rtfBufSiz], *bp;
        int             old = -1;
-       const char      *fn = "ReadFontTbl";
 
        for (;;)
        {
@@ -839,19 +802,21 @@ static void ReadFontTbl(RTF_Info *info)
                        else if (RTFCheckCM (info, rtfGroup, rtfBeginGroup))
                                old = 0;        /* brace */
                        else                    /* can't tell! */
-                               ERR ( "%s: Cannot determine format\n", fn);
+                               ERR ("cannot determine format\n");
                }
                if (old == 0)           /* need to find "{" here */
                {
                        if (!RTFCheckCM (info, rtfGroup, rtfBeginGroup))
-                               ERR ( "%s: missing \"{\"\n", fn);
+                               ERR ("missing \"{\"\n");
                        RTFGetToken (info);     /* yes, skip to next token */
                        if (info->rtfClass == rtfEOF)
                                break;
                }
                fp = New (RTFFont);
-               if (fp == NULL)
-                       ERR ( "%s: cannot allocate font entry\n", fn);
+               if (fp == NULL) {
+                       ERR ("cannot allocate font entry\n");
+                       break;
+               }
 
                fp->rtfNextFont = info->fontList;
                info->fontList = fp;
@@ -875,8 +840,8 @@ static void ReadFontTbl(RTF_Info *info)
                                {
                                default:
                                        /* ignore token but announce it */
-                                       WARN ("%s: unknown token \"%s\"\n",
-                                               fn, info->rtfTextBuf);
+                                       WARN ("unknown token \"%s\"\n",
+                                               info->rtfTextBuf);
                                         break;
                                case rtfFontFamily:
                                        fp->rtfFFamily = info->rtfMinor;
@@ -937,7 +902,7 @@ static void ReadFontTbl(RTF_Info *info)
                                *bp = '\0';
                                fp->rtfFName = RTFStrSave (buf);
                                if (fp->rtfFName == NULL)
-                                       ERR ( "%s: cannot allocate font name\n", fn);
+                                       ERR ("cannot allocate font name\n");
                                /* already have next token; don't read one */
                                /* at bottom of loop */
                                continue;
@@ -945,8 +910,7 @@ static void ReadFontTbl(RTF_Info *info)
                        else
                        {
                                /* ignore token but announce it */
-                               WARN ( "%s: unknown token \"%s\"\n",
-                                                       fn,info->rtfTextBuf);
+                               WARN ("unknown token \"%s\"\n", info->rtfTextBuf);
                        }
                        RTFGetToken (info);
                        if (info->rtfClass == rtfEOF)
@@ -958,7 +922,7 @@ static void ReadFontTbl(RTF_Info *info)
                {
                        RTFGetToken (info);
                        if (!RTFCheckCM (info, rtfGroup, rtfEndGroup))
-                               ERR ( "%s: missing \"}\"\n", fn);
+                               ERR ("missing \"}\"\n");
                        if (info->rtfClass == rtfEOF)
                                break;
                }
@@ -971,8 +935,8 @@ static void ReadFontTbl(RTF_Info *info)
                         TRACE("default font codepage %d\n", info->codePage);
                 }
        }
-       if (fp->rtfFNum == -1)
-               ERR( "%s: missing font number\n", fn);
+       if (!fp || (fp->rtfFNum == -1))
+               ERR("missing font number\n");
 /*
  * Could check other pieces of structure here, too, I suppose.
  */
@@ -1001,7 +965,6 @@ static void ReadColorTbl(RTF_Info *info)
 {
        RTFColor        *cp;
        int             cnum = 0;
-       const char      *fn = "ReadColorTbl";
         int group_level = 1;
 
        for (;;)
@@ -1023,26 +986,31 @@ static void ReadColorTbl(RTF_Info *info)
                 }
 
                cp = New (RTFColor);
-               if (cp == NULL)
-                       ERR ( "%s: cannot allocate color entry\n", fn);
+               if (cp == NULL) {
+                       ERR ("cannot allocate color entry\n");
+                       break;
+               }
                cp->rtfCNum = cnum++;
-               cp->rtfCRed = cp->rtfCGreen = cp->rtfCBlue = -1;
                cp->rtfNextColor = info->colorList;
                info->colorList = cp;
-               while (RTFCheckCM (info, rtfControl, rtfColorName))
-               {
-                       switch (info->rtfMinor)
-                       {
-                       case rtfRed:    cp->rtfCRed = info->rtfParam; break;
-                       case rtfGreen:  cp->rtfCGreen = info->rtfParam; break;
-                       case rtfBlue:   cp->rtfCBlue = info->rtfParam; break;
-                       }
-                       RTFGetToken (info);
+               if (!RTFCheckCM (info, rtfControl, rtfColorName))
+                       cp->rtfCRed = cp->rtfCGreen = cp->rtfCBlue = -1;
+               else {
+                       cp->rtfCRed = cp->rtfCGreen = cp->rtfCBlue = 0;
+                       do {
+                               switch (info->rtfMinor)
+                               {
+                               case rtfRed:    cp->rtfCRed = info->rtfParam & 0xFF; break;
+                               case rtfGreen:  cp->rtfCGreen = info->rtfParam & 0xFF; break;
+                               case rtfBlue:   cp->rtfCBlue = info->rtfParam & 0xFF; break;
+                               }
+                               RTFGetToken (info);
+                       } while (RTFCheckCM (info, rtfControl, rtfColorName));
                }
                if (info->rtfClass == rtfEOF)
                        break;
                if (!RTFCheckCM (info, rtfText, ';'))
-                       ERR ("%s: malformed entry\n", fn);
+                       ERR ("malformed entry\n");
        }
        RTFRouteToken (info);   /* feed "}" back to router */
 }
@@ -1058,7 +1026,6 @@ static void ReadStyleSheet(RTF_Info *info)
        RTFStyle        *sp;
        RTFStyleElt     *sep, *sepLast;
        char            buf[rtfBufSiz], *bp;
-       const char      *fn = "ReadStyleSheet";
        int             real_style;
 
        for (;;)
@@ -1069,8 +1036,10 @@ static void ReadStyleSheet(RTF_Info *info)
                if (RTFCheckCM (info, rtfGroup, rtfEndGroup))
                        break;
                sp = New (RTFStyle);
-               if (sp == NULL)
-                       ERR ( "%s: cannot allocate stylesheet entry\n", fn);
+               if (sp == NULL) {
+                       ERR ("cannot allocate stylesheet entry\n");
+                       break;
+               }
                sp->rtfSName = NULL;
                sp->rtfSNum = -1;
                sp->rtfSType = rtfParStyle;
@@ -1082,7 +1051,7 @@ static void ReadStyleSheet(RTF_Info *info)
                sp->rtfExpanding = 0;
                info->styleList = sp;
                if (!RTFCheckCM (info, rtfGroup, rtfBeginGroup))
-                       ERR ( "%s: missing \"{\"\n", fn);
+                       ERR ("missing \"{\"\n");
                real_style = TRUE;
                for (;;)
                {
@@ -1094,7 +1063,7 @@ static void ReadStyleSheet(RTF_Info *info)
                        {
                                if (RTFCheckMM (info, rtfSpecialChar, rtfOptDest)) {
                                        RTFGetToken(info);
-                                       ERR( "%s: skipping optional destination\n", fn);
+                                       ERR("skipping optional destination\n");
                                        RTFSkipGroup(info);
                                        info->rtfClass = rtfGroup;
                                        info->rtfMajor = rtfEndGroup;
@@ -1136,14 +1105,17 @@ static void ReadStyleSheet(RTF_Info *info)
                                }
                                sep = New (RTFStyleElt);
                                if (sep == NULL)
-                                       ERR ( "%s: cannot allocate style element\n", fn);
+                                {
+                                       ERR ("cannot allocate style element\n");
+                                       break;
+                               }
                                sep->rtfSEClass = info->rtfClass;
                                sep->rtfSEMajor = info->rtfMajor;
                                sep->rtfSEMinor = info->rtfMinor;
                                sep->rtfSEParam = info->rtfParam;
                                sep->rtfSEText = RTFStrSave (info->rtfTextBuf);
                                if (sep->rtfSEText == NULL)
-                                       ERR ( "%s: cannot allocate style element text\n", fn);
+                                       ERR ("cannot allocate style element text\n");
                                if (sepLast == NULL)
                                        sp->rtfSSEList = sep;   /* first element */
                                else                            /* add to end */
@@ -1157,7 +1129,7 @@ static void ReadStyleSheet(RTF_Info *info)
                                 * This passes over "{\*\keycode ... }, among
                                 * other things. A temporary (perhaps) hack.
                                 */
-                                ERR( "%s: skipping begin\n", fn);
+                               ERR("skipping begin\n");
                                RTFSkipGroup (info);
                                continue;
                        }
@@ -1178,19 +1150,18 @@ static void ReadStyleSheet(RTF_Info *info)
                                *bp = '\0';
                                sp->rtfSName = RTFStrSave (buf);
                                if (sp->rtfSName == NULL)
-                                       ERR ( "%s: cannot allocate style name\n", fn);
+                                       ERR ("cannot allocate style name\n");
                        }
                        else            /* unrecognized */
                        {
                                /* ignore token but announce it */
-                               WARN ( "%s: unknown token \"%s\"\n",
-                                                       fn, info->rtfTextBuf);
+                               WARN ("unknown token \"%s\"\n", info->rtfTextBuf);
                        }
                }
                if (real_style) {
                        RTFGetToken (info);
                        if (!RTFCheckCM (info, rtfGroup, rtfEndGroup))
-                               ERR ( "%s: missing \"}\"\n", fn);
+                               ERR ("missing \"}\"\n");
                        /*
                         * Check over the style structure.  A name is a must.
                         * If no style number was specified, check whether it's the
@@ -1202,12 +1173,12 @@ static void ReadStyleSheet(RTF_Info *info)
                         * Some German RTF writers use "Standard" instead of "Normal".
                         */
                        if (sp->rtfSName == NULL)
-                               ERR ( "%s: missing style name\n", fn);
+                               ERR ("missing style name\n");
                        if (sp->rtfSNum < 0)
                        {
                                if (strncmp (buf, "Normal", 6) != 0
                                        && strncmp (buf, "Standard", 8) != 0)
-                                       ERR ( "%s: missing style number\n", fn);
+                                       ERR ("missing style number\n");
                                sp->rtfSNum = rtfNormalStyleNum;
                        }
                        if (sp->rtfSNextPar == -1)      /* if \snext not given, */
@@ -1247,22 +1218,6 @@ static void ReadObjGroup(RTF_Info *info)
  * References to style 0 are mapped onto the Normal style.
  */
 
-
-RTFStyle *RTFGetStyle(const RTF_Info *info, int num)
-{
-       RTFStyle        *s;
-
-       if (num == -1)
-               return (info->styleList);
-       for (s = info->styleList; s != NULL; s = s->rtfNextStyle)
-       {
-               if (s->rtfSNum == num)
-                       break;
-       }
-       return (s);             /* NULL if not found */
-}
-
-
 RTFFont *RTFGetFont(const RTF_Info *info, int num)
 {
        RTFFont *f;
@@ -1293,59 +1248,6 @@ RTFColor *RTFGetColor(const RTF_Info *info, int num)
 }
 
 
-/* ---------------------------------------------------------------------- */
-
-
-/*
- * Expand style n, if there is such a style.
- */
-
-void RTFExpandStyle(RTF_Info *info, int n)
-{
-       RTFStyle        *s;
-       RTFStyleElt     *se;
-
-       if (n == -1)
-               return;
-       s = RTFGetStyle (info, n);
-       if (s == NULL)
-               return;
-       if (s->rtfExpanding != 0)
-               ERR ("Style expansion loop, style %d\n", n);
-       s->rtfExpanding = 1;    /* set expansion flag for loop detection */
-       /*
-        * Expand "based-on" style (unless it's the same as the current
-        * style -- Normal style usually gives itself as its own based-on
-        * style).  Based-on style expansion is done by synthesizing
-        * the token that the writer needs to see in order to trigger
-        * another style expansion, and feeding to token back through
-        * the router so the writer sees it.
-        */
-       if (n != s->rtfSBasedOn)
-       {
-               RTFSetToken (info, rtfControl, rtfParAttr, rtfStyleNum,
-                                                       s->rtfSBasedOn, "\\s");
-               RTFRouteToken (info);
-       }
-       /*
-        * Now route the tokens unique to this style.  RTFSetToken()
-        * isn't used because it would add the param value to the end
-        * of the token text, which already has it in.
-        */
-       for (se = s->rtfSSEList; se != NULL; se = se->rtfNextSE)
-       {
-               info->rtfClass = se->rtfSEClass;
-               info->rtfMajor = se->rtfSEMajor;
-               info->rtfMinor = se->rtfSEMinor;
-               info->rtfParam = se->rtfSEParam;
-               lstrcpyA (info->rtfTextBuf, se->rtfSEText);
-               info->rtfTextLen = lstrlenA (info->rtfTextBuf);
-               RTFRouteToken (info);
-       }
-       s->rtfExpanding = 0;    /* done - clear expansion flag */
-}
-
-
 /* ---------------------------------------------------------------------- */
 
 /*
@@ -1438,6 +1340,8 @@ static RTFKey     rtfKey[] =
        /* is this valid? */
        { rtfSpecialChar,       rtfCurHeadPict,         "chpict",       0 },
        { rtfSpecialChar,       rtfUnicode,             "u",            0 },
+       { rtfSpecialChar,       rtfNestCell,            "nestcell",     0 },
+       { rtfSpecialChar,       rtfNestRow,             "nestrow",      0 },
 
        /*
         * Character formatting attributes
@@ -1601,6 +1505,7 @@ static RTFKey     rtfKey[] =
        { rtfParAttr,   rtfDarkDiagHatchBgPat,  "bgdkdcross",   0 },
        { rtfParAttr,   rtfBgPatLineColor,      "cfpat",        0 },
        { rtfParAttr,   rtfBgPatColor,          "cbpat",        0 },
+       { rtfParAttr,   rtfNestLevel,           "itap",         0 },
 
        /*
         * Section formatting attributes
@@ -1903,6 +1808,8 @@ static RTFKey     rtfKey[] =
        { rtfDestination,       rtfIndexRange,          "rxe",          0 },
        { rtfDestination,       rtfTOC,                 "tc",           0 },
        { rtfDestination,       rtfNeXTGraphic,         "NeXTGraphic",  0 },
+       { rtfDestination,       rtfNestTableProps,      "nesttableprops", 0 },
+       { rtfDestination,       rtfNoNestTables,        "nonesttables", 0 },
 
        /*
         * Font families
@@ -2263,7 +2170,7 @@ static RTFKey     rtfKey[] =
        { rtfVersion,   -1,                     "rtf",          0 },
        { rtfDefFont,   -1,                     "deff",         0 },
 
-       { 0,            -1,                     (char *) NULL,  0 }
+       { 0,            -1,                     NULL,           0 }
 };
 #define RTF_KEY_COUNT (sizeof(rtfKey) / sizeof(RTFKey))
 
@@ -2300,7 +2207,7 @@ void LookupInit(void)
 
 void LookupCleanup(void)
 {
-       int i;
+       unsigned int i;
 
        for (i=0; i<RTF_KEY_COUNT*2; i++)
        {
@@ -2395,14 +2302,6 @@ int RTFCharToHex(char c)
 }
 
 
-int RTFHexToChar(int i)
-{
-       if (i < 10)
-               return (i + '0');
-       return (i - 10 + 'a');
-}
-
-
 /* ---------------------------------------------------------------------- */
 
 /*
@@ -2459,6 +2358,13 @@ ControlClass (RTF_Info *info)
        {
         case rtfCharAttr:
                 CharAttr(info);
+                ME_RTFCharAttrHook(info);
+                break;
+        case rtfParAttr:
+                ME_RTFParAttrHook(info);
+                break;
+        case rtfTblAttr:
+                ME_RTFTblAttrHook(info);
                 break;
         case rtfCharSet:
                 CharSet(info);
@@ -2474,6 +2380,7 @@ ControlClass (RTF_Info *info)
                 break;
        case rtfSpecialChar:
                 SpecialChar (info);
+                ME_RTFSpecialCharHook(info);
                break;
        }
 }
@@ -2605,7 +2512,6 @@ static void SpecialChar (RTF_Info *info)
             break;
        case rtfPage:
        case rtfSect:
-       case rtfRow:
        case rtfPar:
                RTFPutUnicodeChar (info, '\r');
                if (info->editor->bEmulateVersion10) RTFPutUnicodeChar (info, '\n');
@@ -2686,7 +2592,7 @@ RTFFlushCPOutputBuffer(RTF_Info *info)
         info->dwCPOutputCount = 0;
 
         RTFPutUnicodeString(info, buffer, length);
-        heap_free((char *)buffer);
+        heap_free(buffer);
 }
 
 void