From: Eric Pouech Date: Sat, 19 Sep 2009 10:53:01 +0000 (+0200) Subject: winhelp: Added support for hotspot links in graphical objects. X-Git-Tag: wine-1.1.30~144 X-Git-Url: http://git.etersoft.ru/projects/?a=commitdiff_plain;h=3d0475eb4d267d95f5f922cbc229723ce39d34b1;p=wine%2Feterwine.git winhelp: Added support for hotspot links in graphical objects. --- diff --git a/programs/winhlp32/hlpfile.c b/programs/winhlp32/hlpfile.c index d9bdc7ec0c..f6c11373a3 100644 --- a/programs/winhlp32/hlpfile.c +++ b/programs/winhlp32/hlpfile.c @@ -761,6 +761,69 @@ static BOOL HLPFILE_RtfAddHexBytes(struct RtfData* rd, const void* _ptr, unsigne return TRUE; } +static HLPFILE_LINK* HLPFILE_AllocLink(struct RtfData* rd, int cookie, + const char* str, unsigned len, LONG hash, + unsigned clrChange, unsigned bHotSpot, unsigned wnd); + +/****************************************************************** + * HLPFILE_AddHotSpotLinks + * + */ +static void HLPFILE_AddHotSpotLinks(struct RtfData* rd, HLPFILE* file, + const BYTE* start, ULONG hs_size, ULONG hs_offset) +{ + unsigned i, hs_num; + ULONG hs_macro; + const char* str; + + if (hs_size == 0 || hs_offset == 0) return; + + start += hs_offset; + /* always 1 ?? */ + hs_num = GET_USHORT(start, 1); + hs_macro = GET_UINT(start, 3); + + str = (const char*)start + 7 + 15 * hs_num + hs_macro; + /* FIXME: should use hs_size to prevent out of bounds reads */ + for (i = 0; i < hs_num; i++) + { + HLPFILE_HOTSPOTLINK* hslink; + + WINE_TRACE("%02x-%02x%02x {%s,%s}\n", + start[7 + 15 * i + 0], start[7 + 15 * i + 1], start[7 + 15 * i + 2], + str, str + strlen(str) + 1); + /* str points to two null terminated strings: + * hotspot name, then link name + */ + str += strlen(str) + 1; /* skip hotspot name */ + + switch (start[7 + 15 * i + 0]) + /* The next two chars always look like 0x04 0x00 ??? + * What are they for ? + */ + { + case 0xE6: + case 0xE7: + hslink = (HLPFILE_HOTSPOTLINK*) + HLPFILE_AllocLink(rd, (start[7 + 15 * i + 0] & 1) ? hlp_link_link : hlp_link_popup, + file->lpszPath, -1, HLPFILE_Hash(str), + 0, 1, -1); + if (hslink) + { + hslink->x = GET_USHORT(start, 7 + 15 * i + 3); + hslink->y = GET_USHORT(start, 7 + 15 * i + 5); + hslink->width = GET_USHORT(start, 7 + 15 * i + 7); + hslink->height = GET_USHORT(start, 7 + 15 * i + 9); + /* target = GET_UINT(start, 7 + 15 * i + 11); */ + } + break; + default: + WINE_FIXME("unknown hotsport target 0x%x\n", start[7 + 15 * i + 0]); + } + str += strlen(str) + 1; + } +} + /****************************************************************** * HLPFILE_RtfAddTransparentBitmap * @@ -848,7 +911,7 @@ static BOOL HLPFILE_RtfAddTransparentBitmap(struct RtfData* rd, const BITMAPINFO * HLPFILE_RtfAddBitmap * */ -static BOOL HLPFILE_RtfAddBitmap(struct RtfData* rd, const BYTE* beg, BYTE type, BYTE pack) +static BOOL HLPFILE_RtfAddBitmap(struct RtfData* rd, HLPFILE* file, const BYTE* beg, BYTE type, BYTE pack) { const BYTE* ptr; const BYTE* pict_beg; @@ -859,6 +922,7 @@ static BOOL HLPFILE_RtfAddBitmap(struct RtfData* rd, const BYTE* beg, BYTE type, BOOL clrImportant = FALSE; BOOL ret = FALSE; char tmp[256]; + unsigned hs_size, hs_offset; bi = HeapAlloc(GetProcessHeap(), 0, sizeof(*bi)); if (!bi) return FALSE; @@ -884,10 +948,11 @@ static BOOL HLPFILE_RtfAddBitmap(struct RtfData* rd, const BYTE* beg, BYTE type, bi->bmiHeader.biWidth, bi->bmiHeader.biHeight); csz = fetch_ulong(&ptr); - fetch_ulong(&ptr); /* hotspot size */ + hs_size = fetch_ulong(&ptr); - off = GET_UINT(ptr, 0); ptr += 4; - /* GET_UINT(ptr, 0); hotspot offset */ ptr += 4; + off = GET_UINT(ptr, 0); ptr += 4; + hs_offset = GET_UINT(ptr, 0); ptr += 4; + HLPFILE_AddHotSpotLinks(rd, file, beg, hs_size, hs_offset); /* now read palette info */ if (type == 0x06) @@ -947,9 +1012,9 @@ done: * HLPFILE_RtfAddMetaFile * */ -static BOOL HLPFILE_RtfAddMetaFile(struct RtfData* rd, const BYTE* beg, BYTE pack) +static BOOL HLPFILE_RtfAddMetaFile(struct RtfData* rd, HLPFILE* file, const BYTE* beg, BYTE pack) { - ULONG size, csize, off, hsoff; + ULONG size, csize, off, hs_offset, hs_size; const BYTE* ptr; const BYTE* bits; BYTE* alloc = NULL; @@ -969,13 +1034,15 @@ static BOOL HLPFILE_RtfAddMetaFile(struct RtfData* rd, const BYTE* beg, BYTE size = fetch_ulong(&ptr); /* decompressed size */ csize = fetch_ulong(&ptr); /* compressed size */ - fetch_ulong(&ptr); /* hotspot size */ + hs_size = fetch_ulong(&ptr); /* hotspot size */ off = GET_UINT(ptr, 0); - hsoff = GET_UINT(ptr, 4); + hs_offset = GET_UINT(ptr, 4); ptr += 8; - WINE_TRACE("sz=%u csz=%u offs=%u/%u,%u\n", - size, csize, off, (ULONG)(ptr - beg), hsoff); + HLPFILE_AddHotSpotLinks(rd, file, beg, hs_size, hs_offset); + + WINE_TRACE("sz=%u csz=%u offs=%u/%u,%u/%u\n", + size, csize, off, (ULONG)(ptr - beg), hs_size, hs_offset); bits = HLPFILE_DecompressGfx(beg + off, csize, size, pack, &alloc); if (!bits) return FALSE; @@ -1016,10 +1083,10 @@ static BOOL HLPFILE_RtfAddGfxByAddr(struct RtfData* rd, HLPFILE *hlpfile, { case 5: /* device dependent bmp */ case 6: /* device independent bmp */ - HLPFILE_RtfAddBitmap(rd, beg, type, pack); + HLPFILE_RtfAddBitmap(rd, hlpfile, beg, type, pack); break; case 8: - HLPFILE_RtfAddMetaFile(rd, beg, pack); + HLPFILE_RtfAddMetaFile(rd, hlpfile, beg, pack); break; default: WINE_FIXME("Unknown type %u\n", type); return FALSE; } @@ -1061,32 +1128,36 @@ static BOOL HLPFILE_RtfAddGfxByIndex(struct RtfData* rd, HLPFILE *hlpfile, */ static HLPFILE_LINK* HLPFILE_AllocLink(struct RtfData* rd, int cookie, const char* str, unsigned len, LONG hash, - unsigned clrChange, unsigned wnd) + unsigned clrChange, unsigned bHotSpot, unsigned wnd) { HLPFILE_LINK* link; char* link_str; + unsigned asz = bHotSpot ? sizeof(HLPFILE_HOTSPOTLINK) : sizeof(HLPFILE_LINK); /* FIXME: should build a string table for the attributes.link.lpszPath * they are reallocated for each link */ if (len == -1) len = strlen(str); - link = HeapAlloc(GetProcessHeap(), 0, sizeof(HLPFILE_LINK) + len + 1); + link = HeapAlloc(GetProcessHeap(), 0, asz + len + 1); if (!link) return NULL; link->cookie = cookie; - link->string = link_str = (char*)(link + 1); + link->string = link_str = (char*)link + asz; memcpy(link_str, str, len); link_str[len] = '\0'; link->hash = hash; link->bClrChange = clrChange ? 1 : 0; + link->bHotSpot = bHotSpot; link->window = wnd; link->next = rd->first_link; rd->first_link = link; link->cpMin = rd->char_pos; - link->cpMax = 0; rd->force_color = clrChange; if (rd->current_link) WINE_FIXME("Pending link\n"); - rd->current_link = link; + if (bHotSpot) + link->cpMax = rd->char_pos; + else + rd->current_link = link; WINE_TRACE("Link[%d] to %s@%08x:%d\n", link->cookie, link->string, link->hash, link->window); @@ -1495,7 +1566,7 @@ static BOOL HLPFILE_BrowseParagraph(HLPFILE_PAGE* page, struct RtfData* rd, case 0xCC: WINE_TRACE("macro => %s\n", format + 3); HLPFILE_AllocLink(rd, hlp_link_macro, (const char*)format + 3, - GET_USHORT(format, 1), 0, !(*format & 4), -1); + GET_USHORT(format, 1), 0, !(*format & 4), 0, -1); format += 3 + GET_USHORT(format, 1); break; @@ -1503,7 +1574,7 @@ static BOOL HLPFILE_BrowseParagraph(HLPFILE_PAGE* page, struct RtfData* rd, case 0xE1: WINE_WARN("jump topic 1 => %u\n", GET_UINT(format, 1)); HLPFILE_AllocLink(rd, (*format & 1) ? hlp_link_link : hlp_link_popup, - page->file->lpszPath, -1, GET_UINT(format, 1), 1, -1); + page->file->lpszPath, -1, GET_UINT(format, 1), 1, 0, -1); format += 5; @@ -1515,7 +1586,7 @@ static BOOL HLPFILE_BrowseParagraph(HLPFILE_PAGE* page, struct RtfData* rd, case 0xE7: HLPFILE_AllocLink(rd, (*format & 1) ? hlp_link_link : hlp_link_popup, page->file->lpszPath, -1, GET_UINT(format, 1), - !(*format & 4), -1); + !(*format & 4), 0, -1); format += 5; break; @@ -1552,7 +1623,7 @@ static BOOL HLPFILE_BrowseParagraph(HLPFILE_PAGE* page, struct RtfData* rd, break; } HLPFILE_AllocLink(rd, (*format & 1) ? hlp_link_link : hlp_link_popup, - ptr, -1, GET_UINT(format, 4), !(*format & 4), wnd); + ptr, -1, GET_UINT(format, 4), !(*format & 4), 0, wnd); } format += 3 + GET_USHORT(format, 1); break; diff --git a/programs/winhlp32/hlpfile.h b/programs/winhlp32/hlpfile.h index 0e3f35e896..f2c5b12fd2 100644 --- a/programs/winhlp32/hlpfile.h +++ b/programs/winhlp32/hlpfile.h @@ -41,12 +41,22 @@ typedef struct tagHlpFileLink LPCSTR string; /* name of the file to for the link (NULL if same file) */ LONG hash; /* topic index */ unsigned bClrChange : 1; /* true if the link is green & underlined */ + unsigned bHotSpot : 1; /* true if the link is an hotspot (actually HLPFILE_HOTSPOTLINK) */ unsigned window; /* window number for displaying the link (-1 is current) */ DWORD cpMin; DWORD cpMax; struct tagHlpFileLink* next; } HLPFILE_LINK; +typedef struct tagHlpFileHotSpotLink +{ + HLPFILE_LINK link; + unsigned x; + unsigned y; + unsigned width; + unsigned height; +} HLPFILE_HOTSPOTLINK; + typedef struct tagHlpFileMacro { LPCSTR lpszMacro; diff --git a/programs/winhlp32/winhelp.c b/programs/winhlp32/winhelp.c index 4c2d1ff6f9..ae7d58dbf3 100644 --- a/programs/winhlp32/winhelp.c +++ b/programs/winhlp32/winhelp.c @@ -646,6 +646,16 @@ static HLPFILE_LINK* WINHELP_FindLink(WINHELP_WINDOW* win, LPARAM pos) (LPARAM)&char_ptl, cp); SendMessageW(GetDlgItem(win->hMainWnd, CTL_ID_TEXT), EM_POSFROMCHAR, (LPARAM)&char_next_ptl, cp + 1); + if (link->bHotSpot) + { + HLPFILE_HOTSPOTLINK* hslink = (HLPFILE_HOTSPOTLINK*)link; + if ((mouse_ptl.x < char_ptl.x + hslink->x) || + (mouse_ptl.x >= char_ptl.x + hslink->x + hslink->width) || + (mouse_ptl.y < char_ptl.y + hslink->y) || + (mouse_ptl.y >= char_ptl.y + hslink->y + hslink->height)) + continue; + break; + } if (char_next_ptl.y != char_ptl.y || mouse_ptl.x >= char_next_ptl.x) link = NULL; break;