WinHelp

Eric Pouech eric.pouech at wanadoo.fr
Sun Dec 15 12:21:13 CST 2002


this patch fixes a couple of issues with winhelp:
- a link can spread across several elements (paragraphs, images...). 
current implementation only set the link on the first element. this is 
now corrected
- better management of link information: it's no longer copied from file 
parser to content presentation. this will lower memory usage
- finally, some metafiles should be displayed now (as graphical objects)

A+
-- 
Eric Pouech
-------------- next part --------------
Name:          wh_xxx
ChangeLog:
	- links can now spread across several elements
	- link information is now shared between file & presentation
	- first try at handling metafiles
License:       X11
GenDate:       2002/12/15 18:18:12 UTC
ModifiedFiles: programs/winhelp/hlp2sgml.c programs/winhelp/hlpfile.c programs/winhelp/hlpfile.h programs/winhelp/winhelp.c programs/winhelp/winhelp.h
AddedFiles:    
===================================================================
RCS file: /home/cvs/cvsroot/wine/wine/programs/winhelp/hlp2sgml.c,v
retrieving revision 1.8
diff -u -u -r1.8 hlp2sgml.c
--- programs/winhelp/hlp2sgml.c	30 Aug 2002 00:01:37 -0000	1.8
+++ programs/winhelp/hlp2sgml.c	8 Dec 2002 16:49:50 -0000
@@ -257,7 +257,8 @@
                 if (paragraph->u.text.wFont)
                     printf(format.end_boldface);
                 break;
-            case para_image:
+            case para_bitmap:
+            case para_metafile:
                 break;
             }
 	}
@@ -332,7 +333,22 @@
     return 0;
 }
 
+HMETAFILE WINAPI SetMetaFileBitsEx(UINT cbBuffer, CONST BYTE *lpbBuffer)
+{
+    return 0;
+}
+
+BOOL WINAPI DeleteMetaFile(HMETAFILE h)
+{
+    return 0;
+}
+
 HDC WINAPI GetDC(HWND h)
+{
+    return 0;
+}
+
+int WINAPI ReleaseDC(HWND h, HDC hdc)
 {
     return 0;
 }
Index: programs/winhelp/hlpfile.c
===================================================================
RCS file: /home/cvs/cvsroot/wine/wine/programs/winhelp/hlpfile.c,v
retrieving revision 1.15
diff -u -u -r1.15 hlpfile.c
--- programs/winhelp/hlpfile.c	20 Nov 2002 19:46:18 -0000	1.15
+++ programs/winhelp/hlpfile.c	8 Dec 2002 21:13:53 -0000
@@ -30,12 +30,20 @@
 
 WINE_DEFAULT_DEBUG_CHANNEL(winhelp);
 
-#define GET_USHORT(buffer, i)\
-(((BYTE)((buffer)[(i)]) + 0x100 * (BYTE)((buffer)[(i)+1])))
-#define GET_SHORT(buffer, i)\
-(((BYTE)((buffer)[(i)]) + 0x100 * (signed char)((buffer)[(i)+1])))
-#define GET_UINT(buffer, i)\
-GET_USHORT(buffer, i) + 0x10000 * GET_USHORT(buffer, i+2)
+static inline unsigned short GET_USHORT(const BYTE* buffer, unsigned i)
+{
+    return (BYTE)buffer[i] + 0x100 * (BYTE)buffer[i + 1];
+}
+
+static inline short GET_SHORT(const BYTE* buffer, unsigned i)
+{
+    return (BYTE)buffer[i] + 0x100 * (signed char)buffer[i+1];
+}
+
+static inline unsigned GET_UINT(const BYTE* buffer, unsigned i)
+{
+    return GET_USHORT(buffer, i) + 0x10000 * GET_USHORT(buffer, i + 2);
+}
 
 static HLPFILE *first_hlpfile = 0;
 static BYTE    *file_buffer;
@@ -56,15 +64,11 @@
 
 static struct
 {
-    UINT                bDebug;
     UINT                wFont;
     UINT                wIndent;
     UINT                wHSpace;
     UINT                wVSpace;
-    UINT                wVBackSpace;
-    HLPFILE_LINK        link;
-    HBITMAP             hBitmap;
-    UINT                bmpPos;
+    HLPFILE_LINK*       link;
 } attributes;
 
 static BOOL  HLPFILE_DoReadHlpFile(HLPFILE*, LPCSTR);
@@ -99,6 +103,8 @@
 
     for (page = hlpfile->first_page; page && wNum; page = page->next) wNum--;
 
+    /* HLPFILE_FreeHlpFile(lpszPath); */
+
     return page;
 }
 
@@ -209,7 +215,7 @@
 
     for (hlpfile = first_hlpfile; hlpfile; hlpfile = hlpfile->next)
     {
-        if (!lstrcmp(hlpfile->lpszPath, lpszPath))
+        if (!strcmp(lpszPath, hlpfile->lpszPath))
         {
             hlpfile->wRefCount++;
             return hlpfile;
@@ -463,7 +469,7 @@
         (*ptr) += 2;
     }
     return ret;
-}
+}    
 
 static short fetch_short(BYTE** ptr)
 {
@@ -500,155 +506,228 @@
 }
 
 /******************************************************************
- *		HLPFILE_LoadPictureByAddr
+ *		HLPFILE_DecompressGfx
+ *
+ * Decompress the data part of a bitmap or a metafile
+ */
+static BYTE*    HLPFILE_DecompressGfx(BYTE* src, unsigned csz, unsigned sz, BYTE packing)
+{
+    BYTE*       dst;
+    BYTE*       tmp;
+    BYTE*       tmp2;
+    unsigned    sz77;
+
+    WINE_TRACE("Unpacking (%d) from %u bytes to %u bytes\n", packing, csz, sz);
+
+    switch (packing)
+    {
+    case 0: /* uncompressed */
+        if (sz != csz)
+            WINE_WARN("Bogus gfx sizes: %u / %u\n", sz, csz);
+        dst = src;
+        break;
+    case 1: /* RunLen */
+        tmp = dst = HeapAlloc(GetProcessHeap(), 0, sz);
+        if (!dst) return NULL;
+        HLPFILE_UncompressRLE(src, csz, &tmp);
+        if (tmp - dst != sz)
+            WINE_FIXME("Bogus gfx sizes: %u/%u\n", tmp - dst, sz);
+        break;
+    case 2: /* LZ77 */
+        sz77 = HLPFILE_UncompressedLZ77_Size(src, src + csz);
+        dst = HeapAlloc(GetProcessHeap(), 0, sz77);
+        if (!dst) return NULL;
+        HLPFILE_UncompressLZ77(src, src + csz, dst);
+        if (sz77 != sz)
+            WINE_WARN("Bogus gfx sizes: %u / %u\n", sz77, sz);
+        break;
+    case 3: /* LZ77 then RLE */
+        sz77 = HLPFILE_UncompressedLZ77_Size(src, src + csz);
+        tmp = HeapAlloc(GetProcessHeap(), 0, sz/*sz77*/);
+        if (!tmp) return FALSE;
+        HLPFILE_UncompressLZ77(src, src + csz, tmp);
+        dst = tmp2 = HeapAlloc(GetProcessHeap(), 0, sz);
+        if (!dst) return FALSE;
+        HLPFILE_UncompressRLE(tmp, sz77, &tmp2);
+        if (tmp2 - dst != sz)
+            WINE_WARN("Bogus gfx: %u / %u\n", tmp2 - dst, sz);
+        HeapFree(GetProcessHeap(), 0, tmp);
+        break;
+    default:
+        WINE_FIXME("Unsupported packing %u\n", packing);
+        return NULL;
+    }
+    return dst;
+}
+
+/******************************************************************
+ *		HLPFILE_LoadBitmap
+ *
+ *
+ */
+static BOOL HLPFILE_LoadBitmap(BYTE* beg, BYTE type, BYTE pack, 
+                               HLPFILE_PARAGRAPH* paragraph)
+{
+    BYTE*               ptr;
+    BYTE*               pict_beg;
+    BITMAPINFO*         bi;
+    unsigned long       off, csz;
+    HDC                 hdc;
+
+    bi = HeapAlloc(GetProcessHeap(), 0, sizeof(*bi));
+    if (!bi) return FALSE;
+
+    ptr = beg + 2; /* for type and pack */
+
+    bi->bmiHeader.biSize          = sizeof(bi->bmiHeader);
+    bi->bmiHeader.biXPelsPerMeter = fetch_ulong(&ptr);
+    bi->bmiHeader.biYPelsPerMeter = fetch_ulong(&ptr);
+    bi->bmiHeader.biPlanes        = fetch_ushort(&ptr);
+    bi->bmiHeader.biBitCount      = fetch_ushort(&ptr);
+    bi->bmiHeader.biWidth         = fetch_ulong(&ptr);
+    bi->bmiHeader.biHeight        = fetch_ulong(&ptr);
+    bi->bmiHeader.biClrUsed       = fetch_ulong(&ptr);
+    bi->bmiHeader.biClrImportant  = fetch_ulong(&ptr);
+    bi->bmiHeader.biCompression   = BI_RGB;
+    if (bi->bmiHeader.biBitCount > 32) WINE_FIXME("Unknown bit count %u\n", bi->bmiHeader.biBitCount);
+    if (bi->bmiHeader.biPlanes != 1) WINE_FIXME("Unsupported planes %u\n", bi->bmiHeader.biPlanes);
+    bi->bmiHeader.biSizeImage = (((bi->bmiHeader.biWidth * bi->bmiHeader.biBitCount + 31) & ~31) / 8) * bi->bmiHeader.biHeight;
+
+    csz = fetch_ulong(&ptr);
+    fetch_ulong(&ptr); /* hotspot size */
+
+    off = GET_UINT(ptr, 0);     ptr += 4;
+    /* GET_UINT(ptr, 0); hotspot offset */ ptr += 4;
+    
+    /* now read palette info */
+    if (type == 0x06)
+    {
+        unsigned nc = bi->bmiHeader.biClrUsed;
+        unsigned i;
+        
+        /* not quite right, especially for bitfields type of compression */
+        if (!nc && bi->bmiHeader.biBitCount <= 8)
+            nc = 1 << bi->bmiHeader.biBitCount;
+        
+        bi = HeapReAlloc(GetProcessHeap(), 0, bi, sizeof(*bi) + nc * sizeof(RGBQUAD));
+        if (!bi) return FALSE;
+        for (i = 0; i < nc; i++)
+        {
+            bi->bmiColors[i].rgbBlue     = ptr[0];
+            bi->bmiColors[i].rgbGreen    = ptr[1];
+            bi->bmiColors[i].rgbRed      = ptr[2];
+            bi->bmiColors[i].rgbReserved = 0;
+            ptr += 4;
+        }
+    }
+    pict_beg = HLPFILE_DecompressGfx(beg + off, csz, bi->bmiHeader.biSizeImage, pack);
+    
+    paragraph->u.gfx.u.bmp.hBitmap = CreateDIBitmap(hdc = GetDC(0), &bi->bmiHeader, 
+                                                    CBM_INIT, pict_beg, 
+                                                    bi, DIB_RGB_COLORS);
+    ReleaseDC(0, hdc);      
+    if (!paragraph->u.gfx.u.bmp.hBitmap)
+        WINE_ERR("Couldn't create bitmap\n");
+    
+    HeapFree(GetProcessHeap(), 0, bi);
+    if (pict_beg != beg + off) HeapFree(GetProcessHeap(), 0, pict_beg);
+
+    return TRUE;
+}
+
+/******************************************************************
+ *		HLPFILE_LoadMetaFile
+ *
+ *
+ */
+static BOOL     HLPFILE_LoadMetaFile(BYTE* beg, BYTE pack, HLPFILE_PARAGRAPH* paragraph)
+{
+    BYTE*               ptr;
+    unsigned long       size, csize;
+    unsigned long       off, hsoff;
+    BYTE*               bits;
+    METAFILEPICT        mfp;
+
+    WINE_TRACE("Loading metafile\n");
+
+    ptr = beg + 2; /* for type and pack */
+
+    mfp.mm = fetch_ushort(&ptr); /* mapping mode */
+
+    mfp.xExt = GET_USHORT(ptr, 0);
+    mfp.yExt = GET_USHORT(ptr, 2);
+    ptr += 4;
+
+    size = fetch_ulong(&ptr); /* decompressed size */
+    csize = fetch_ulong(&ptr); /* compressed size */
+    fetch_ulong(&ptr); /* hotspot size */
+    off = GET_UINT(ptr, 0);
+    hsoff = GET_UINT(ptr, 4);
+    ptr += 8;
+
+    WINE_FIXME("sz=%lu csz=%lu (%ld,%ld) offs=%lu/%u,%lu\n", 
+               size, csize, mfp.xExt, mfp.yExt, off, ptr - beg, hsoff);
+
+    bits = HLPFILE_DecompressGfx(beg + off, csize, size, pack);
+    if (!bits) return FALSE;
+
+    paragraph->cookie = para_metafile;
+
+    mfp.hMF = NULL;
+
+    paragraph->u.gfx.u.mf.hMetaFile = SetMetaFileBitsEx(size, bits);
+
+    if (!paragraph->u.gfx.u.mf.hMetaFile)
+        WINE_FIXME("Couldn't load metafile\n");
+
+    if (bits != beg + off) HeapFree(GetProcessHeap(), 0, bits);
+
+    paragraph->u.gfx.u.mf.mfSize.cx = mfp.xExt;
+    paragraph->u.gfx.u.mf.mfSize.cy = mfp.yExt;
+
+    return TRUE;
+}
+
+/******************************************************************
+ *		HLPFILE_LoadGfxByAddr
  *
  *
  */
-static  BOOL    HLPFILE_LoadPictureByAddr(HLPFILE *hlpfile, char* ref,
-                                          unsigned long size, unsigned pos)
+static  BOOL    HLPFILE_LoadGfxByAddr(HLPFILE *hlpfile, BYTE* ref,
+                                      unsigned long size, 
+                                      HLPFILE_PARAGRAPH* paragraph)
 {
     unsigned    i, numpict;
 
-    numpict = *(unsigned short*)(ref + 2);
+    numpict = GET_USHORT(ref, 2);
     WINE_TRACE("Got picture magic=%04x #=%d\n", 
-               *(unsigned short*)ref, numpict);
+               GET_USHORT(ref, 0), numpict);
 
     for (i = 0; i < numpict; i++)
     {
-        BYTE                    *beg, *ptr;
-        BYTE                    *pict_beg;
-        BYTE                    type, pack;
-        BITMAPINFO*             bi;
-        unsigned long           off, sz;
+        BYTE*   beg;
+        BYTE*   ptr;
+        BYTE    type, pack;
 
-        WINE_TRACE("Offset[%d] = %lx\n", i, ((unsigned long*)ref)[1 + i]);
-        ptr = beg = ref + ((unsigned long*)ref)[1 + i];
+        WINE_TRACE("Offset[%d] = %x\n", i, GET_UINT(ref, (1 + i) * 4));
+        beg = ptr = ref + GET_UINT(ref, (1 + i) * 4);
 
         type = *ptr++;
         pack = *ptr++;
         
         switch (type)
         {
-        case 5: /* device dependent bmp */ break;
-        case 6: /* device independent bmp */ break;
-        case 8: WINE_FIXME("Unsupported metafile\n"); return FALSE;
-        default: WINE_FIXME("Unknown type %u\n", type); return FALSE;
-        }
-
-        bi = HeapAlloc(GetProcessHeap(), 0, sizeof(*bi));
-        if (!bi) return FALSE;
-
-        bi->bmiHeader.biSize = sizeof(bi->bmiHeader);
-        bi->bmiHeader.biXPelsPerMeter = fetch_ulong(&ptr);
-        bi->bmiHeader.biYPelsPerMeter = fetch_ulong(&ptr);
-        bi->bmiHeader.biPlanes        = fetch_ushort(&ptr);
-        bi->bmiHeader.biBitCount      = fetch_ushort(&ptr);
-        bi->bmiHeader.biWidth         = fetch_ulong(&ptr);
-        bi->bmiHeader.biHeight        = fetch_ulong(&ptr);
-        bi->bmiHeader.biClrUsed       = fetch_ulong(&ptr);
-        bi->bmiHeader.biClrImportant  = fetch_ulong(&ptr);
-        bi->bmiHeader.biCompression   = BI_RGB;
-        if (bi->bmiHeader.biBitCount > 32) WINE_FIXME("Unknown bit count %u\n", bi->bmiHeader.biBitCount);
-        if (bi->bmiHeader.biPlanes != 1) WINE_FIXME("Unsupported planes %u\n", bi->bmiHeader.biPlanes);
-        bi->bmiHeader.biSizeImage = (((bi->bmiHeader.biWidth * bi->bmiHeader.biBitCount + 31) & ~31) / 8) * bi->bmiHeader.biHeight;
-
-        sz = fetch_ulong(&ptr);
-        fetch_ulong(&ptr); /* hotspot size */
-
-        off = *(unsigned long*)ptr;     ptr += 4;
-        /* *(unsigned long*)ptr; hotspot offset */ ptr += 4;
-
-        /* now read palette info */
-        if (type == 0x06)
-        {
-            unsigned nc = bi->bmiHeader.biClrUsed;
-            unsigned i;
-
-            /* not quite right, especially for bitfields type of compression */
-            if (!nc && bi->bmiHeader.biBitCount <= 8)
-                nc = 1 << bi->bmiHeader.biBitCount;
-
-            bi = HeapReAlloc(GetProcessHeap(), 0, bi, sizeof(*bi) + nc * sizeof(RGBQUAD));
-            if (!bi) return FALSE;
-            for (i = 0; i < nc; i++)
-            {
-                bi->bmiColors[i].rgbBlue     = ptr[0];
-                bi->bmiColors[i].rgbGreen    = ptr[1];
-                bi->bmiColors[i].rgbRed      = ptr[2];
-                bi->bmiColors[i].rgbReserved = 0;
-                ptr += 4;
-            }
-        }
-
-        switch (pack)
-        {
-        case 0: /* uncompressed */
-            pict_beg = beg + off;
-            if (sz != bi->bmiHeader.biSizeImage)
-                WINE_WARN("Bogus image sizes: %lu / %lu [sz=(%lu,%lu) bc=%u pl=%u]\n",
-                          sz, bi->bmiHeader.biSizeImage,
-                          bi->bmiHeader.biWidth, bi->bmiHeader.biHeight,
-                          bi->bmiHeader.biBitCount, bi->bmiHeader.biPlanes);
+        case 5: /* device dependent bmp */
+        case 6: /* device independent bmp */
+            HLPFILE_LoadBitmap(beg, type, pack, paragraph);
             break;
-        case 1: /* RunLen */
-            {
-                BYTE*   dst;
-
-                dst = pict_beg = HeapAlloc(GetProcessHeap(), 0, bi->bmiHeader.biSizeImage);
-                if (!pict_beg) return FALSE;
-                HLPFILE_UncompressRLE(beg + off, sz, &dst);
-                if (dst - pict_beg != bi->bmiHeader.biSizeImage)
-                    WINE_FIXME("buffer XXX-flow (%u/%lu)\n", dst - pict_beg, bi->bmiHeader.biSizeImage);
-            }
-            break;
-        case 2: /* LZ77 */
-            {
-                unsigned long esz;
-                esz = HLPFILE_UncompressedLZ77_Size(beg + off, beg + off + sz);
-                pict_beg = HeapAlloc(GetProcessHeap(), 0, esz);
-                if (!pict_beg) return FALSE;
-                HLPFILE_UncompressLZ77(beg + off, beg + off + sz, pict_beg);
-                if (esz != bi->bmiHeader.biSizeImage)
-                    WINE_WARN("Bogus image sizes: %lu / %lu [sz=(%lu,%lu) bc=%u pl=%u]\n",
-                              esz, bi->bmiHeader.biSizeImage,
-                              bi->bmiHeader.biWidth, bi->bmiHeader.biHeight,
-                              bi->bmiHeader.biBitCount, bi->bmiHeader.biPlanes);
-            }
-            break;
-        case 3: /* LZ77 then RLE */
-            {
-                BYTE*           tmp;
-                unsigned long   sz77;
-                BYTE*           dst;
-
-                sz77 = HLPFILE_UncompressedLZ77_Size(beg + off, beg + off + sz);
-                tmp = HeapAlloc(GetProcessHeap(), 0, bi->bmiHeader.biSizeImage);
-                if (!tmp) return FALSE;
-                HLPFILE_UncompressLZ77(beg + off, beg + off + sz, tmp);
-                pict_beg = dst = HeapAlloc(GetProcessHeap(), 0, bi->bmiHeader.biSizeImage);
-                if (!pict_beg) return FALSE;
-                HLPFILE_UncompressRLE(tmp, sz77, &dst);
-                if (dst - pict_beg != bi->bmiHeader.biSizeImage)
-                    WINE_WARN("Bogus image sizes: %u / %lu [sz=(%lu,%lu) bc=%u pl=%u]\n",
-                              dst - pict_beg, bi->bmiHeader.biSizeImage,
-                              bi->bmiHeader.biWidth, bi->bmiHeader.biHeight,
-                              bi->bmiHeader.biBitCount, bi->bmiHeader.biPlanes);
-                HeapFree(GetProcessHeap(), 0, tmp);
-            }
+        case 8: 
+            HLPFILE_LoadMetaFile(beg, pack, paragraph);
             break;
-        default:
-            WINE_FIXME("Unsupported packing %u\n", pack);
-            return FALSE;
+        default: WINE_FIXME("Unknown type %u\n", type); return FALSE;
         }
 
-        attributes.hBitmap = CreateDIBitmap(GetDC(0), &bi->bmiHeader, CBM_INIT,
-                                            pict_beg, bi, DIB_RGB_COLORS);
-        if (!attributes.hBitmap)
-            WINE_ERR("Couldn't create bitmap\n");
-        attributes.bmpPos = pos;
-
-        HeapFree(GetProcessHeap(), 0, bi);
-        if (pict_beg != beg + off) HeapFree(GetProcessHeap(), 0, pict_beg);
+        /* FIXME: hotspots */
 
         /* FIXME: implement support for multiple picture format */
         if (numpict != 1) WINE_FIXME("Supporting only one bitmap format per logical bitmap (for now). Using first format\n");
@@ -658,21 +737,22 @@
 }
 
 /******************************************************************
- *		HLPFILE_LoadPictureByIndex
+ *		HLPFILE_LoadGfxByIndex
  *
  *
  */
-static  BOOL    HLPFILE_LoadPictureByIndex(HLPFILE *hlpfile, unsigned index, unsigned pos)
+static  BOOL    HLPFILE_LoadGfxByIndex(HLPFILE *hlpfile, unsigned index, 
+                                       HLPFILE_PARAGRAPH* paragraph)
 {
     char        tmp[16];
     BYTE        *ref, *end;
     BOOL        ret;
+
     WINE_TRACE("Loading picture #%d\n", index);
 
     if (index < hlpfile->numBmps && hlpfile->bmps[index] != NULL)
     {
-        attributes.hBitmap = hlpfile->bmps[index];
-        attributes.bmpPos  = pos;
+        paragraph->u.gfx.u.bmp.hBitmap = hlpfile->bmps[index];
         return TRUE;
     }
 
@@ -682,10 +762,10 @@
 
     ref += 9;
 
-    ret = HLPFILE_LoadPictureByAddr(hlpfile, ref, end - ref, pos);
+    ret = HLPFILE_LoadGfxByAddr(hlpfile, ref, end - ref, paragraph);
 
     /* cache bitmap */
-    if (ret)
+    if (ret && paragraph->cookie == para_bitmap)
     {
         if (index >= hlpfile->numBmps)
         {
@@ -693,11 +773,41 @@
             hlpfile->bmps = HeapReAlloc(GetProcessHeap(), 0, hlpfile->bmps, 
                                         hlpfile->numBmps * sizeof(hlpfile->bmps[0]));
         }
-        hlpfile->bmps[index] = attributes.hBitmap;
+        hlpfile->bmps[index] = paragraph->u.gfx.u.bmp.hBitmap;
     }
     return ret;
 }
 
+/******************************************************************
+ *		HLPFILE_AllocLink
+ *
+ *
+ */
+static HLPFILE_LINK*       HLPFILE_AllocLink(int cookie, const char* str, LONG hash,
+                                             BOOL clrChange, unsigned wnd)
+{
+    HLPFILE_LINK*  link;
+
+    /* FIXME: should build a string table for the attributes.link.lpszPath
+     * they are reallocated for each link
+     */
+    link = HeapAlloc(GetProcessHeap(), 0, sizeof(HLPFILE_LINK) + strlen(str) + 1);
+    if (!link) return NULL;
+
+    link->cookie     = cookie;
+    link->lpszString = (char*)link + sizeof(HLPFILE_LINK);
+    strcpy((char*)link->lpszString, str);
+    link->lHash      = hash;
+    link->bClrChange = clrChange ? 1 : 0;
+    link->window     = wnd;
+    link->wRefCount   = 1;
+
+    WINE_TRACE("Link[%d] to %s@%08lx:%d\n",
+               link->cookie, link->lpszString, 
+               link->lHash, link->window);
+    return link;
+}
+
 /***********************************************************************
  *
  *           HLPFILE_AddParagraph
@@ -766,7 +876,7 @@
         if (buf[0x14] == 0x23)
             format += 5;
         format += 4;
-        bits = *(unsigned short*)format; format += 2;
+        bits = GET_USHORT(format, 0); format += 2;
         if (bits & 0x0001) fetch_long(&format);
         if (bits & 0x0002) fetch_short(&format);
         if (bits & 0x0004) fetch_short(&format);
@@ -794,7 +904,7 @@
         {
             WINE_TRACE("Got text: '%s' (%p/%p - %p/%p)\n", text, text, text_end, format, format_end);
             textsize = strlen(text) + 1;
-            if (textsize > 1 || attributes.hBitmap)
+            if (textsize > 1)
             {
                 paragraph = HeapAlloc(GetProcessHeap(), 0,
                                       sizeof(HLPFILE_PARAGRAPH) + textsize);
@@ -802,55 +912,19 @@
                 *paragraphptr = paragraph;
                 paragraphptr = &paragraph->next;
 
-                paragraph->next     = NULL;
-                paragraph->link     = NULL;
+                paragraph->next            = NULL;
+                paragraph->link            = attributes.link;
+                if (paragraph->link) paragraph->link->wRefCount++;
+                paragraph->cookie          = para_normal_text;
+                paragraph->u.text.wFont    = attributes.wFont;
+                paragraph->u.text.wVSpace  = attributes.wVSpace;
+                paragraph->u.text.wHSpace  = attributes.wHSpace;
+                paragraph->u.text.wIndent  = attributes.wIndent;
+                paragraph->u.text.lpszText = (char*)paragraph + sizeof(HLPFILE_PARAGRAPH);
+                strcpy(paragraph->u.text.lpszText, text);
 
-                if (attributes.hBitmap)
-                {
-                    paragraph->cookie           = para_image;
-                    paragraph->u.image.hBitmap  = attributes.hBitmap;
-                    paragraph->u.image.pos      = attributes.bmpPos;
-                    if (attributes.wVSpace) paragraph->u.image.pos |= 0x8000;
-                }
-                else
-                {
-                    paragraph->cookie          = (attributes.bDebug) ? para_debug_text : para_normal_text;
-                    paragraph->u.text.wFont    = attributes.wFont;
-                    paragraph->u.text.wVSpace  = attributes.wVSpace;
-                    paragraph->u.text.wHSpace  = attributes.wHSpace;
-                    paragraph->u.text.wIndent  = attributes.wIndent;
-                    paragraph->u.text.lpszText = (char*)paragraph + sizeof(HLPFILE_PARAGRAPH);
-                    strcpy(paragraph->u.text.lpszText, text);
-                }
-
-                if (attributes.link.lpszString)
-                {
-                    /* FIXME: should build a string table for the attributes.link.lpszPath
-                     * they are reallocated for each link
-                     */
-                    paragraph->link = HeapAlloc(GetProcessHeap(), 0,
-                                                sizeof(HLPFILE_LINK) + strlen(attributes.link.lpszString) + 1);
-                    if (!paragraph->link) return FALSE;
-
-                    paragraph->link->cookie     = attributes.link.cookie;
-                    paragraph->link->lpszString = (char*)paragraph->link + sizeof(HLPFILE_LINK);
-                    strcpy((char*)paragraph->link->lpszString, attributes.link.lpszString);
-                    paragraph->link->lHash      = attributes.link.lHash;
-                    paragraph->link->bClrChange = attributes.link.bClrChange;
-                    paragraph->link->window     = attributes.link.window;
-
-                    WINE_TRACE("Link[%d] to %s@%08lx:%d\n",
-                               paragraph->link->cookie, paragraph->link->lpszString, 
-                               paragraph->link->lHash, paragraph->link->window);
-                }
-                attributes.hBitmap = 0;
-                attributes.link.lpszString = NULL;
-                attributes.link.bClrChange = FALSE;
-                attributes.link.lHash = 0;
-                attributes.link.window = -1;
                 attributes.wVSpace = 0;
                 attributes.wHSpace = 0;
-                attributes.wIndent = 0;
             }
             /* else: null text, keep on storing attributes */
             text += textsize;
@@ -886,8 +960,7 @@
                 break;
 
 	    case 0x82:
-                attributes.wVSpace += 2 - attributes.wVBackSpace;
-                attributes.wVBackSpace = 0;
+                attributes.wVSpace++;
                 attributes.wIndent = 0;
                 format += 1;
                 break;
@@ -914,26 +987,38 @@
                     format += 2;
                     size = fetch_long(&format);
 
+                    paragraph = HeapAlloc(GetProcessHeap(), 0,
+                                          sizeof(HLPFILE_PARAGRAPH) + textsize);
+                    if (!paragraph) return FALSE;
+                    *paragraphptr = paragraph;
+                    paragraphptr = &paragraph->next;
+
+                    paragraph->next        = NULL;
+                    paragraph->link        = attributes.link;
+                    if (paragraph->link) paragraph->link->wRefCount++;
+                    paragraph->cookie      = para_bitmap;
+                    paragraph->u.gfx.pos   = pos;
                     switch (type)
                     {
                     case 0x22:
                         fetch_ushort(&format); /* hot spot */
                         /* fall thru */
                     case 0x03:
-                        switch (*(short*)format)
+                        switch (GET_SHORT(format, 0))
                         {
                         case 0:
-                            HLPFILE_LoadPictureByIndex(hlpfile,
-                                                       *(short*)(format + 2), pos);
+                            HLPFILE_LoadGfxByIndex(hlpfile, GET_SHORT(format, 2), 
+                                                   paragraph);
                             break;
                         case 1:
                             WINE_FIXME("does it work ??? %x<%lu>#%u\n", 
-                                       *(short*)format, size, *(short*)(format+2));
-                            HLPFILE_LoadPictureByAddr(hlpfile, format + 2,
-                                                      size - 4, pos);
+                                       GET_SHORT(format, 0), 
+                                       size, GET_SHORT(format, 2));
+                            HLPFILE_LoadGfxByAddr(hlpfile, format + 2, size - 4, 
+                                                  paragraph);
                             break;
                         default:
-                            WINE_FIXME("??? %u\n", *(short*)format);
+                            WINE_FIXME("??? %u\n", GET_SHORT(format, 0));
                             break;
                         }
                         break;
@@ -944,12 +1029,15 @@
                         WINE_FIXME("Got a type %d picture\n", type);
                         break;
                     }
+                    if (attributes.wVSpace) paragraph->u.gfx.pos |= 0x8000;
+
                     format += size;
                 }
                 break;
 
 	    case 0x89:
-                attributes.wVBackSpace++;
+                HLPFILE_FreeLink(attributes.link);
+                attributes.link = NULL;
                 format += 1;
                 break;
 
@@ -968,9 +1056,9 @@
             case 0xC8:
             case 0xCC:
                 WINE_TRACE("macro => %s\n", format + 3);
-                attributes.link.bClrChange = !(*format & 4);
-                attributes.link.cookie     = hlp_link_macro;
-                attributes.link.lpszString = format + 3;
+                HLPFILE_FreeLink(attributes.link);
+                attributes.link = HLPFILE_AllocLink(hlp_link_macro, format + 3, 
+                                                    0, !(*format & 4), -1);
                 format += 3 + GET_USHORT(format, 1);
                 break;
 
@@ -982,13 +1070,13 @@
 
 	    case 0xE2:
 	    case 0xE3:
-                attributes.link.bClrChange = TRUE;
-                /* fall thru */
             case 0xE6:
             case 0xE7:
-                attributes.link.cookie     = (*format & 1) ? hlp_link_link : hlp_link_popup;
-                attributes.link.lpszString = hlpfile->lpszPath;
-                attributes.link.lHash      = GET_UINT(format, 1);
+                HLPFILE_FreeLink(attributes.link);
+                attributes.link = HLPFILE_AllocLink((*format & 1) ? hlp_link_link : hlp_link_popup,
+                                                    hlpfile->lpszPath, 
+                                                    GET_UINT(format, 1), 
+                                                    !(*format & 4), -1);
                 format += 5;
                 break;
 
@@ -997,37 +1085,32 @@
             case 0xEE:
             case 0xEF:
                 {
-                    char* ptr = format + 8;
-                    BYTE  type = format[3];
-                    
-                    attributes.link.cookie     = hlp_link_link;
-                    attributes.link.lHash      = GET_UINT(format, 4);
-                    attributes.link.bClrChange = !(*format & 1);
-                    
-                    if (type == 1) 
-                        attributes.link.window = *ptr++;
+                    char*       ptr = format + 8;
+                    BYTE        type = format[3];
+                    int         wnd = -1;
+                    char*       str;
+
+                    if (type == 1) wnd = *ptr++;
                     if (type == 4 || type == 6)
                     {
-                        attributes.link.lpszString = ptr;
+                        str = ptr;
                         ptr += strlen(ptr) + 1;
                     }
                     else
-                        attributes.link.lpszString = hlpfile->lpszPath;
+                        str = hlpfile->lpszPath;
                     if (type == 6)
                     {
-                        int     i;
-
-                        for (i = 0; i < hlpfile->numWindows; i++)
+                        for (wnd = hlpfile->numWindows - 1; wnd >= 0; wnd--)
                         {
-                            if (!strcmp(ptr, hlpfile->windows[i].name))
-                            {
-                                attributes.link.window = i;
-                                break;
-                            }
+                            if (!strcmp(ptr, hlpfile->windows[wnd].name)) break;
                         }
-                        if (attributes.link.window == -1)
+                        if (wnd == -1)
                             WINE_WARN("Couldn't find window info for %s\n", ptr);
                     }
+                    HLPFILE_FreeLink(attributes.link);
+                    attributes.link = HLPFILE_AllocLink((*format & 4) ? hlp_link_link : hlp_link_popup,
+                                                        str, GET_UINT(format, 4),
+                                                        !(*format & 1), wnd);
                 }
                 format += 3 + GET_USHORT(format, 1);
                 break;
@@ -1107,7 +1190,7 @@
         case 0x05: hlpfile->fonts[i].LogFont.lfPitchAndFamily |= FF_DECORATIVE; break;
         default: WINE_FIXME("Unknown family %u\n", family);
         }
-        idx = *(unsigned short*)(ref + dscr_offset + i * 11 + 3);
+        idx = GET_USHORT(ref, dscr_offset + i * 11 + 3);
 
         if (idx < face_num)
         {
@@ -1124,7 +1207,7 @@
                                       ref[dscr_offset + i * 11 + 6],
                                       ref[dscr_offset + i * 11 + 7]);
 #define X(b,s) ((flag & (1 << b)) ? "-"s: "")
-        WINE_TRACE("Font[%d]: flags=%02x%s%s%s%s%s%s pSize=%u family=%u face=%s[%u] color=%08lx\n",
+        WINE_TRACE("Font[%d]: flags=%02x%s%s%s%s%s%s pSize=%u family=%u face=%s[%u] color=%08x\n",
                    i, flag,
                    X(0, "bold"),
                    X(1, "italic"),
@@ -1135,7 +1218,7 @@
                    ref[dscr_offset + i * 11 + 1],
                    family,
                    hlpfile->fonts[i].LogFont.lfFaceName, idx,
-                   *(unsigned long*)(ref + dscr_offset + i * 11 + 5) & 0x00FFFFFF);
+                   GET_UINT(ref, dscr_offset + i * 11 + 5) & 0x00FFFFFF);
     }
     return TRUE;
 }
@@ -1778,6 +1861,17 @@
     return TRUE;
 }
 
+/******************************************************************
+ *		HLPFILE_DeleteLink
+ *
+ *
+ */
+void HLPFILE_FreeLink(HLPFILE_LINK* link)
+{
+    if (link && !--link->wRefCount)
+        HeapFree(GetProcessHeap(), 0, link);
+}
+
 /***********************************************************************
  *
  *           HLPFILE_DeleteParagraph
@@ -1789,7 +1883,11 @@
     while (paragraph)
     {
         next = paragraph->next;
-        if (paragraph->link) HeapFree(GetProcessHeap(), 0, paragraph->link);
+
+        if (paragraph->cookie == para_metafile)
+            DeleteMetaFile(paragraph->u.gfx.u.mf.hMetaFile);
+
+        HLPFILE_FreeLink(paragraph->link);
 
         HeapFree(GetProcessHeap(), 0, paragraph);
         paragraph = next;
Index: programs/winhelp/hlpfile.h
===================================================================
RCS file: /home/cvs/cvsroot/wine/wine/programs/winhelp/hlpfile.h,v
retrieving revision 1.7
diff -u -u -r1.7 hlpfile.h
--- programs/winhelp/hlpfile.h	20 Nov 2002 19:46:18 -0000	1.7
+++ programs/winhelp/hlpfile.h	8 Dec 2002 21:13:26 -0000
@@ -30,20 +30,21 @@
     SIZE        size;
     int         style;
     DWORD       win_style;
-    COLORREF    sr_color;          /* color for scrollable region */
+    COLORREF    sr_color;       /* color for scrollable region */
     COLORREF    nsr_color;      /* color for non scrollable region */
 } HLPFILE_WINDOWINFO;
 
 typedef struct
 {
-    enum {hlp_link_none, hlp_link_link, hlp_link_popup, hlp_link_macro} cookie;
-    LPCSTR      lpszString;
-    LONG        lHash;
-    BOOL        bClrChange;
-    unsigned    window;
+    enum {hlp_link_link, hlp_link_popup, hlp_link_macro} cookie;
+    LPCSTR      lpszString;     /* name of the file to for the link (NULL if same file) */
+    LONG        lHash;          /* topic index */
+    unsigned    bClrChange : 1, /* true if the link is green & underlined */
+                wRefCount;      /* number of internal references to this object */
+    unsigned    window;         /* window number for displaying the link (-1 is current) */
 } HLPFILE_LINK;
 
-enum para_type {para_normal_text, para_debug_text, para_image};
+enum para_type {para_normal_text, para_debug_text, para_bitmap, para_metafile};
 
 typedef struct tagHlpFileParagraph
 {
@@ -61,9 +62,20 @@
         } text;
         struct
         {
-            HBITMAP                     hBitmap;
             unsigned                    pos;    /* 0: center, 1: left, 2: right */
-        } image;
+            union 
+            {
+                struct 
+                {
+                    HBITMAP             hBitmap;
+                } bmp;
+                struct
+                {
+                    HMETAFILE           hMetaFile;
+                    SIZE                mfSize;
+                } mf;
+            } u;
+        } gfx; /* for bitmaps and metafiles */
     } u;
 
     HLPFILE_LINK*               link;
@@ -142,4 +154,5 @@
 HLPFILE_PAGE* HLPFILE_PageByHash(HLPFILE* hlpfile, LONG lHash);
 HLPFILE_PAGE* HLPFILE_PageByOffset(HLPFILE* hlpfile, LONG offset);
 LONG          HLPFILE_Hash(LPCSTR lpszContext);
+void          HLPFILE_FreeLink(HLPFILE_LINK* link);
 void          HLPFILE_FreeHlpFile(HLPFILE*);
Index: programs/winhelp/winhelp.c
===================================================================
RCS file: /home/cvs/cvsroot/wine/wine/programs/winhelp/winhelp.c,v
retrieving revision 1.23
diff -u -u -r1.23 winhelp.c
--- programs/winhelp/winhelp.c	27 Nov 2002 20:12:37 -0000	1.23
+++ programs/winhelp/winhelp.c	8 Dec 2002 21:13:37 -0000
@@ -45,7 +45,7 @@
 static void    WINHELP_DeleteLines(WINHELP_WINDOW*);
 static void    WINHELP_DeleteWindow(WINHELP_WINDOW*);
 static void    WINHELP_SetupText(HWND hWnd);
-static WINHELP_LINE_PART* WINHELP_IsOverLink(HWND hWnd, WPARAM wParam, LPARAM lParam);
+static WINHELP_LINE_PART* WINHELP_IsOverLink(WINHELP_WINDOW*, WPARAM, LPARAM);
 
 WINHELP_GLOBALS Globals = {3, 0, 0, 0, 1, 0, 0};
 
@@ -852,18 +852,27 @@
                         DeleteObject(hPen);
                     }
                     break;
-                case hlp_line_part_image:
+                case hlp_line_part_bitmap:
                     {
                         HDC hMemDC;
 
                         hMemDC = CreateCompatibleDC(hDc);
-                        SelectObject(hMemDC, part->u.image.hBitmap);
+                        SelectObject(hMemDC, part->u.bitmap.hBitmap);
                         BitBlt(hDc, part->rect.left, part->rect.top - scroll_pos,
                                part->rect.right - part->rect.left, part->rect.bottom - part->rect.top,
                                hMemDC, 0, 0, SRCCOPY);
                         DeleteDC(hMemDC);
                     }
                     break;
+                case hlp_line_part_metafile:
+                    {
+                        POINT   pt;
+
+                        SetViewportOrgEx(hDc, part->rect.left, part->rect.top - scroll_pos, &pt);
+                        PlayMetaFile(hDc, part->u.metafile.hMetaFile);
+                        SetViewportOrgEx(hDc, pt.x, pt.y, NULL);
+                    }
+                    break;
                 }
             }
         }
@@ -874,7 +883,7 @@
     case WM_MOUSEMOVE:
         win = (WINHELP_WINDOW*) GetWindowLong(hWnd, 0);
 
-        if (WINHELP_IsOverLink(hWnd, wParam, lParam))
+        if (WINHELP_IsOverLink(win, wParam, lParam))
             SetCursor(win->hHandCur); /* set to hand pointer cursor to indicate a link */
         else
             SetCursor(win->hArrowCur); /* set to hand pointer cursor to indicate a link */
@@ -887,7 +896,7 @@
         hPopupWnd = Globals.hPopupWnd;
         Globals.hPopupWnd = 0;
 
-        part = WINHELP_IsOverLink(hWnd, wParam, lParam);
+        part = WINHELP_IsOverLink(win, wParam, lParam);
         if (part)
         {
             HLPFILE*            hlpfile;
@@ -896,35 +905,33 @@
             mouse.x = LOWORD(lParam);
             mouse.y = HIWORD(lParam);
 
-            switch (part->link.cookie)
+            if (part->link) switch (part->link->cookie)
             {
-            case hlp_link_none:
-                break;
             case hlp_link_link:
-                hlpfile = WINHELP_LookupHelpFile(part->link.lpszString);
-                if (part->link.window == -1)
+                hlpfile = WINHELP_LookupHelpFile(part->link->lpszString);
+                if (part->link->window == -1)
                     wi = win->info;
-                else if (part->link.window < hlpfile->numWindows)
-                    wi = &hlpfile->windows[part->link.window];
+                else if (part->link->window < hlpfile->numWindows)
+                    wi = &hlpfile->windows[part->link->window];
                 else
                 {
-                    WINE_WARN("link to window %d/%d\n", part->link.window, hlpfile->numWindows);
+                    WINE_WARN("link to window %d/%d\n", part->link->window, hlpfile->numWindows);
                     break;
                 }
-                WINHELP_CreateHelpWindowByHash(hlpfile, part->link.lHash, wi,
+                WINHELP_CreateHelpWindowByHash(hlpfile, part->link->lHash, wi,
                                                SW_NORMAL);
                 break;
             case hlp_link_popup:
-                hlpfile = WINHELP_LookupHelpFile(part->link.lpszString);
-                WINHELP_CreateHelpWindowByHash(hlpfile, part->link.lHash, 
+                hlpfile = WINHELP_LookupHelpFile(part->link->lpszString);
+                WINHELP_CreateHelpWindowByHash(hlpfile, part->link->lHash, 
                                                WINHELP_GetPopupWindowInfo(hlpfile, hWnd, &mouse),
                                                SW_NORMAL);
                 break;
             case hlp_link_macro:
-                MACRO_ExecuteMacro(part->link.lpszString);
+                MACRO_ExecuteMacro(part->link->lpszString);
                 break;
             default:
-                WINE_FIXME("Unknown link cookie %d\n", part->link.cookie);
+                WINE_FIXME("Unknown link cookie %d\n", part->link->cookie);
             }
         }
 
@@ -1061,7 +1068,7 @@
         *line_ascent  = ascent;
 
         line = HeapAlloc(GetProcessHeap(), 0,
-                         sizeof(WINHELP_LINE) + textlen + (link ? lstrlen(link->lpszString) + 1 : 0));
+                         sizeof(WINHELP_LINE) + textlen);
         if (!line) return FALSE;
 
         line->next    = 0;
@@ -1094,8 +1101,7 @@
 	}
 
         part = HeapAlloc(GetProcessHeap(), 0,
-                         sizeof(WINHELP_LINE_PART) + textlen +
-                         (link ? lstrlen(link->lpszString) + 1 : 0));
+                         sizeof(WINHELP_LINE_PART) + textlen);
         if (!part) return FALSE;
         **partp = part;
         ptr     = (char*)part + sizeof(WINHELP_LINE_PART);
@@ -1122,16 +1128,9 @@
                part->u.text.lpsText,
                part->u.text.wTextLen,
                part->rect.left, part->rect.top, part->rect.right, part->rect.bottom);
-    if (link)
-    {
-        strcpy(ptr + textlen, link->lpszString);
-        part->link.lpszString = ptr + textlen;
-        part->link.cookie     = link->cookie;
-        part->link.lHash      = link->lHash;
-        part->link.bClrChange = link->bClrChange;
-        part->link.window     = link->window;
-    }
-    else part->link.cookie = hlp_link_none;
+
+    part->link = link;
+    if (link) link->wRefCount++;
 
     part->next          = 0;
     *partp              = &part->next;
@@ -1143,12 +1142,11 @@
 
 /***********************************************************************
  *
- *           WINHELP_AppendBitmap
+ *           WINHELP_AppendGfxObject
  */
-static BOOL WINHELP_AppendBitmap(WINHELP_LINE ***linep, WINHELP_LINE_PART ***partp,
-                                 LPSIZE space,
-                                 HBITMAP hBmp, LPSIZE bmpSize,
-                                 HLPFILE_LINK *link, unsigned pos)
+static WINHELP_LINE_PART* WINHELP_AppendGfxObject(WINHELP_LINE ***linep, WINHELP_LINE_PART ***partp,
+                                                  LPSIZE space, LPSIZE gfxSize,
+                                                  HLPFILE_LINK *link, unsigned pos)
 {
     WINHELP_LINE      *line;
     WINHELP_LINE_PART *part;
@@ -1156,9 +1154,8 @@
 
     if (!*partp || pos == 1) /* New line */
     {
-        line = HeapAlloc(GetProcessHeap(), 0,
-                         sizeof(WINHELP_LINE) + (link ? lstrlen(link->lpszString) + 1 : 0));
-        if (!line) return FALSE;
+        line = HeapAlloc(GetProcessHeap(), 0, sizeof(WINHELP_LINE));
+        if (!line) return NULL;
 
         line->next    = NULL;
         part          = &line->first_part;
@@ -1178,45 +1175,32 @@
         if (pos == 2) WINE_FIXME("Left alignment not handled\n");
         line = **linep;
 
-        part = HeapAlloc(GetProcessHeap(), 0,
-                         sizeof(WINHELP_LINE_PART) +
-                         (link ? lstrlen(link->lpszString) + 1 : 0));
-        if (!part) return FALSE;
+        part = HeapAlloc(GetProcessHeap(), 0, sizeof(WINHELP_LINE_PART));
+        if (!part) return NULL;
         **partp = part;
         ptr = (char*)part + sizeof(WINHELP_LINE_PART);
     }
 
-    part->cookie          = hlp_line_part_image;
+    /* part->cookie should be set by caller (image or metafile) */
     part->rect.left       = line->rect.right + (*partp ? space->cx : 0);
-    part->rect.right      = part->rect.left + bmpSize->cx;
+    part->rect.right      = part->rect.left + gfxSize->cx;
     line->rect.right      = part->rect.right;
-    part->rect.top        =
-        ((*partp) ? line->rect.top : line->rect.bottom);
-    part->rect.bottom     = part->rect.top + bmpSize->cy;
+    part->rect.top        = (*partp) ? line->rect.top : line->rect.bottom;
+    part->rect.bottom     = part->rect.top + gfxSize->cy;
     line->rect.bottom     = max(line->rect.bottom, part->rect.bottom);
-    part->u.image.hBitmap = hBmp;
 
-    WINE_TRACE("Appended bitmap '%d' @ (%d,%d-%d,%d)\n",
-               (unsigned)part->u.image.hBitmap,
+    WINE_TRACE("Appended gfx @ (%d,%d-%d,%d)\n",
                part->rect.left, part->rect.top, part->rect.right, part->rect.bottom);
 
-    if (link)
-    {
-        strcpy(ptr, link->lpszString);
-        part->link.lpszString = ptr;
-        part->link.cookie     = link->cookie;
-        part->link.lHash      = link->lHash;
-        part->link.bClrChange = link->bClrChange;
-        part->link.window     = link->window;
-    }
-    else part->link.cookie = hlp_link_none;
+    part->link = link;
+    if (link) link->wRefCount++;
 
     part->next            = NULL;
     *partp                = &part->next;
 
     space->cx = 0;
 
-    return TRUE;
+    return part;
 }
 
 
@@ -1286,7 +1270,7 @@
                     hFont = win->fonts[wFont];
                 }
 
-                if (p->link)
+                if (p->link && p->link->bClrChange)
                 {
                     underline = (p->link->cookie == hlp_link_popup) ? 3 : 1;
                     color = RGB(0, 0x80, 0);
@@ -1371,13 +1355,14 @@
                 }
             }
             break;
-        case para_image:
+        case para_bitmap:
+        case para_metafile:
             {
-                DIBSECTION      dibs;
-                SIZE            bmpSize;
-                INT             free_width;
+                SIZE                    gfxSize;
+                INT                     free_width;
+                WINHELP_LINE_PART*      ref_part;
 
-                if (p->u.image.pos & 0x8000)
+                if (p->u.gfx.pos & 0x8000)
                 {
                     space.cx = rect.left;
                     if (*line)
@@ -1385,10 +1370,16 @@
                     part = 0;
                 }
 
-                GetObject(p->u.image.hBitmap, sizeof(dibs), &dibs);
-                bmpSize.cx = dibs.dsBm.bmWidth;
-                bmpSize.cy = dibs.dsBm.bmHeight;
-
+                if (p->cookie == para_bitmap)
+                {
+                    DIBSECTION              dibs;
+                    
+                    GetObject(p->u.gfx.u.bmp.hBitmap, sizeof(dibs), &dibs);
+                    gfxSize.cx = dibs.dsBm.bmWidth;
+                    gfxSize.cy = dibs.dsBm.bmHeight;
+                }
+                else gfxSize = p->u.gfx.u.mf.mfSize;
+                    
                 free_width = rect.right - ((part && *line) ? (*line)->rect.right : rect.left) - space.cx;
                 if (free_width <= 0)
                 {
@@ -1396,17 +1387,25 @@
                     space.cx = rect.left;
                     space.cx = min(space.cx, rect.right - rect.left - 1);
                 }
-                if (!WINHELP_AppendBitmap(&line, &part, &space,
-                                          p->u.image.hBitmap, &bmpSize,
-                                          p->link, p->u.image.pos) ||
-                    (!newsize && (*line)->rect.bottom > rect.bottom))
+                ref_part = WINHELP_AppendGfxObject(&line, &part, &space, &gfxSize,
+                                                   p->link, p->u.gfx.pos);
+                if (!ref_part || (!newsize && (*line)->rect.bottom > rect.bottom))
                 {
                     return FALSE;
                 }
+                if (p->cookie == para_bitmap)
+                {
+                    ref_part->cookie = hlp_line_part_bitmap;
+                    ref_part->u.bitmap.hBitmap = p->u.gfx.u.bmp.hBitmap;
+                }
+                else
+                {
+                    ref_part->cookie = hlp_line_part_metafile;
+                    ref_part->u.metafile.hMetaFile = p->u.gfx.u.mf.hMetaFile;
+                }
             }
             break;
         }
-
     }
 
     if (newsize)
@@ -1452,6 +1451,7 @@
         for (part = &line->first_part; part; part = next_part)
 	{
             next_part = part->next;
+            HLPFILE_FreeLink(part->link);
             HeapFree(GetProcessHeap(), 0, part);
 	}
     }
@@ -1574,13 +1574,12 @@
  *
  *
  */
-WINHELP_LINE_PART* WINHELP_IsOverLink(HWND hWnd, WPARAM wParam, LPARAM lParam)
+WINHELP_LINE_PART* WINHELP_IsOverLink(WINHELP_WINDOW* win, WPARAM wParam, LPARAM lParam)
 {
-    WINHELP_WINDOW* win = (WINHELP_WINDOW*) GetWindowLong(hWnd, 0);
     POINT mouse;
     WINHELP_LINE      *line;
     WINHELP_LINE_PART *part;
-    int scroll_pos = GetScrollPos(hWnd, SB_VERT);
+    int scroll_pos = GetScrollPos(win->hMainWnd, SB_VERT);
 
     mouse.x = LOWORD(lParam);
     mouse.y = HIWORD(lParam);
@@ -1588,8 +1587,8 @@
     {
         for (part = &line->first_part; part; part = part->next)
         {
-            if (part->link.cookie != hlp_link_none &&
-                part->link.lpszString &&
+            if (part->link && 
+                part->link->lpszString &&
                 part->rect.left   <= mouse.x &&
                 part->rect.right  >= mouse.x &&
                 part->rect.top    <= mouse.y + scroll_pos &&
Index: programs/winhelp/winhelp.h
===================================================================
RCS file: /home/cvs/cvsroot/wine/wine/programs/winhelp/winhelp.h,v
retrieving revision 1.9
diff -u -u -r1.9 winhelp.h
--- programs/winhelp/winhelp.h	20 Nov 2002 19:46:18 -0000	1.9
+++ programs/winhelp/winhelp.h	8 Dec 2002 16:08:11 -0000
@@ -40,7 +40,7 @@
 typedef struct tagHelpLinePart
 {
     RECT      rect;
-    enum {hlp_line_part_text, hlp_line_part_image}      cookie;
+    enum {hlp_line_part_text, hlp_line_part_bitmap, hlp_line_part_metafile} cookie;
     union
     {
         struct
@@ -54,9 +54,13 @@
         struct
         {
             HBITMAP     hBitmap;
-        } image;
+        } bitmap;
+        struct
+        {
+            HMETAFILE   hMetaFile;
+        } metafile;
     } u;
-    HLPFILE_LINK        link;
+    HLPFILE_LINK*       link;
 
     struct tagHelpLinePart *next;
 } WINHELP_LINE_PART;


More information about the wine-patches mailing list