winhelp: Added support for hotspot links in graphical objects.
This commit is contained in:
parent
14d51867fe
commit
3d0475eb4d
|
@ -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;
|
||||
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,31 +1128,35 @@ 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");
|
||||
if (bHotSpot)
|
||||
link->cpMax = rd->char_pos;
|
||||
else
|
||||
rd->current_link = link;
|
||||
|
||||
WINE_TRACE("Link[%d] to %s@%08x:%d\n",
|
||||
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue