- 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
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 = ¶graph->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 = ¶graph->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;