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
*
* 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;
BOOL clrImportant = FALSE;
BOOL ret = FALSE;
char tmp[256];
+ unsigned hs_size, hs_offset;
bi = HeapAlloc(GetProcessHeap(), 0, sizeof(*bi));
if (!bi) return FALSE;
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)
* 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;
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;
{
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;
}
*/
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);
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;
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;
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;
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;