[PATCH 09/11] [WinHelp]: instead of loading all pages at once, allow to browse them one by one
Eric Pouech
eric.pouech at orange.fr
Fri Apr 18 14:34:36 CDT 2008
A+
---
programs/winhelp/hlpfile.c | 128 ++++++++++++++++++++++++++++++++++++--------
programs/winhelp/hlpfile.h | 3 +
programs/winhelp/winhelp.c | 2 +
3 files changed, 110 insertions(+), 23 deletions(-)
diff --git a/programs/winhelp/hlpfile.c b/programs/winhelp/hlpfile.c
index 050ce53..c6ad220 100644
--- a/programs/winhelp/hlpfile.c
+++ b/programs/winhelp/hlpfile.c
@@ -72,8 +72,8 @@ static BOOL HLPFILE_Uncompress_Topic(HLPFILE*);
static BOOL HLPFILE_GetContext(HLPFILE*);
static BOOL HLPFILE_GetKeywords(HLPFILE*);
static BOOL HLPFILE_GetMap(HLPFILE*);
-static BOOL HLPFILE_AddPage(HLPFILE*, BYTE*, BYTE*, unsigned);
-static BOOL HLPFILE_AddParagraph(HLPFILE*, BYTE *, BYTE*, unsigned*);
+static BOOL HLPFILE_AddPage(HLPFILE*, BYTE*, BYTE*, unsigned, unsigned);
+static BOOL HLPFILE_SkipParagraph(HLPFILE*, BYTE *, BYTE*, unsigned*);
static void HLPFILE_Uncompress2(HLPFILE*, const BYTE*, const BYTE*, BYTE*, const BYTE*);
static BOOL HLPFILE_Uncompress3(HLPFILE*, char*, const char*, const BYTE*, const BYTE*);
static void HLPFILE_UncompressRLE(const BYTE* src, const BYTE* end, BYTE** dst, unsigned dstsz);
@@ -343,13 +343,13 @@ static BOOL HLPFILE_DoReadHlpFile(HLPFILE *hlpfile, LPCSTR lpszPath)
switch (buf[0x14])
{
case 0x02:
- if (!HLPFILE_AddPage(hlpfile, buf, end, index * 0x8000L + offs)) return FALSE;
+ if (!HLPFILE_AddPage(hlpfile, buf, end, ref, index * 0x8000L + offs)) return FALSE;
break;
case 0x01:
case 0x20:
case 0x23:
- if (!HLPFILE_AddParagraph(hlpfile, buf, end, &len)) return FALSE;
+ if (!HLPFILE_SkipParagraph(hlpfile, buf, end, &len)) return FALSE;
offs += len;
break;
@@ -377,7 +377,7 @@ static BOOL HLPFILE_DoReadHlpFile(HLPFILE *hlpfile, LPCSTR lpszPath)
*
* HLPFILE_AddPage
*/
-static BOOL HLPFILE_AddPage(HLPFILE *hlpfile, BYTE *buf, BYTE *end, unsigned offset)
+static BOOL HLPFILE_AddPage(HLPFILE *hlpfile, BYTE *buf, BYTE *end, unsigned ref, unsigned offset)
{
HLPFILE_PAGE* page;
BYTE* title;
@@ -433,6 +433,7 @@ static BOOL HLPFILE_AddPage(HLPFILE *hlpfile, BYTE *buf, BYTE *end, unsigned off
page->first_macro = NULL;
page->wNumber = GET_UINT(buf, 0x21);
page->offset = offset;
+ page->reference = ref;
page->browse_bwd = GET_UINT(buf, 0x19);
page->browse_fwd = GET_UINT(buf, 0x1D);
@@ -534,6 +535,28 @@ static unsigned short fetch_ushort(BYTE** ptr)
return ret;
}
+/***********************************************************************
+ *
+ * HLPFILE_SkipParagraph
+ */
+static BOOL HLPFILE_SkipParagraph(HLPFILE *hlpfile, BYTE *buf, BYTE *end, unsigned* len)
+{
+ BYTE *tmp;
+
+ if (!hlpfile->first_page) {WINE_WARN("no page\n"); return FALSE;};
+ if (buf + 0x19 > end) {WINE_WARN("header too small\n"); return FALSE;};
+
+ tmp = buf + 0x15;
+ if (buf[0x14] == 0x20 || buf[0x14] == 0x23)
+ {
+ fetch_long(&tmp);
+ *len = fetch_ushort(&tmp);
+ }
+ else *len = end-buf-15;
+
+ return TRUE;
+}
+
/******************************************************************
* HLPFILE_DecompressGfx
*
@@ -848,11 +871,10 @@ static HLPFILE_LINK* HLPFILE_AllocLink(int cookie, const char* str, LONG h
/***********************************************************************
*
- * HLPFILE_AddParagraph
+ * HLPFILE_BrowseParagraph
*/
-static BOOL HLPFILE_AddParagraph(HLPFILE *hlpfile, BYTE *buf, BYTE *end, unsigned* len)
+static BOOL HLPFILE_BrowseParagraph(HLPFILE_PAGE* page, BYTE *buf, BYTE* end)
{
- HLPFILE_PAGE *page;
HLPFILE_PARAGRAPH *paragraph, **paragraphptr;
UINT textsize;
BYTE *format, *format_end;
@@ -861,8 +883,6 @@ static BOOL HLPFILE_AddParagraph(HLPFILE *hlpfile, BYTE *buf, BYTE *end, unsigne
unsigned short bits;
unsigned nc, ncol = 1;
- if (!hlpfile->last_page) {WINE_WARN("no page\n"); return FALSE;};
- page = hlpfile->last_page;
for (paragraphptr = &page->first_paragraph; *paragraphptr;
paragraphptr = &(*paragraphptr)->next) /* Nothing */;
@@ -876,10 +896,10 @@ static BOOL HLPFILE_AddParagraph(HLPFILE *hlpfile, BYTE *buf, BYTE *end, unsigne
if (size > blocksize - datalen)
{
/* need to decompress */
- if (hlpfile->hasPhrases)
- HLPFILE_Uncompress2(hlpfile, buf + datalen, end, (BYTE*)text, (BYTE*)text + size);
- else if (hlpfile->hasPhrases40)
- HLPFILE_Uncompress3(hlpfile, text, text + size, buf + datalen, end);
+ if (page->file->hasPhrases)
+ HLPFILE_Uncompress2(page->file, buf + datalen, end, (BYTE*)text, (BYTE*)text + size);
+ else if (page->file->hasPhrases40)
+ HLPFILE_Uncompress3(page->file, text, text + size, buf + datalen, end);
else
{
WINE_FIXME("Text size is too long, splitting\n");
@@ -898,9 +918,8 @@ static BOOL HLPFILE_AddParagraph(HLPFILE *hlpfile, BYTE *buf, BYTE *end, unsigne
if (buf[0x14] == 0x20 || buf[0x14] == 0x23)
{
fetch_long(&format);
- *len = fetch_ushort(&format);
+ fetch_ushort(&format);
}
- else *len = end-buf-15;
if (buf[0x14] == 0x23)
{
@@ -1055,14 +1074,14 @@ static BOOL HLPFILE_AddParagraph(HLPFILE *hlpfile, BYTE *buf, BYTE *end, unsigne
switch (GET_SHORT(format, 0))
{
case 0:
- HLPFILE_LoadGfxByIndex(hlpfile, GET_SHORT(format, 2),
+ HLPFILE_LoadGfxByIndex(page->file, GET_SHORT(format, 2),
paragraph);
break;
case 1:
WINE_FIXME("does it work ??? %x<%lu>#%u\n",
GET_SHORT(format, 0),
size, GET_SHORT(format, 2));
- HLPFILE_LoadGfxByAddr(hlpfile, format + 2, size - 4,
+ HLPFILE_LoadGfxByAddr(page->file, format + 2, size - 4,
paragraph);
break;
default:
@@ -1115,7 +1134,7 @@ static BOOL HLPFILE_AddParagraph(HLPFILE *hlpfile, BYTE *buf, BYTE *end, unsigne
WINE_WARN("jump topic 1 => %u\n", GET_UINT(format, 1));
HLPFILE_FreeLink(attributes.link);
attributes.link = HLPFILE_AllocLink((*format & 1) ? hlp_link_link : hlp_link_popup,
- hlpfile->lpszPath,
+ page->file->lpszPath,
GET_UINT(format, 1)-16,
1, -1);
@@ -1129,7 +1148,7 @@ static BOOL HLPFILE_AddParagraph(HLPFILE *hlpfile, BYTE *buf, BYTE *end, unsigne
case 0xE7:
HLPFILE_FreeLink(attributes.link);
attributes.link = HLPFILE_AllocLink((*format & 1) ? hlp_link_link : hlp_link_popup,
- hlpfile->lpszPath,
+ page->file->lpszPath,
GET_UINT(format, 1),
!(*format & 4), -1);
format += 5;
@@ -1150,12 +1169,12 @@ static BOOL HLPFILE_AddParagraph(HLPFILE *hlpfile, BYTE *buf, BYTE *end, unsigne
wnd = *ptr;
/* fall through */
case 0:
- ptr = hlpfile->lpszPath;
+ ptr = page->file->lpszPath;
break;
case 6:
- for (wnd = hlpfile->numWindows - 1; wnd >= 0; wnd--)
+ for (wnd = page->file->numWindows - 1; wnd >= 0; wnd--)
{
- if (!strcmp(ptr, hlpfile->windows[wnd].name)) break;
+ if (!strcmp(ptr, page->file->windows[wnd].name)) break;
}
if (wnd == -1)
WINE_WARN("Couldn't find window info for %s\n", ptr);
@@ -1186,6 +1205,69 @@ static BOOL HLPFILE_AddParagraph(HLPFILE *hlpfile, BYTE *buf, BYTE *end, unsigne
}
/******************************************************************
+ * HLPFILE_BrowsePage
+ *
+ */
+BOOL HLPFILE_BrowsePage(HLPFILE_PAGE* page)
+{
+ HLPFILE *hlpfile = page->file;
+ BYTE *buf, *end;
+ DWORD ref = page->reference;
+ unsigned index, old_index = -1, offset, count = 0;
+
+ do
+ {
+ if (hlpfile->version <= 16)
+ {
+ index = (ref - 0x0C) / hlpfile->dsize;
+ offset = (ref - 0x0C) % hlpfile->dsize;
+ }
+ else
+ {
+ index = (ref - 0x0C) >> 14;
+ offset = (ref - 0x0C) & 0x3FFF;
+ }
+
+ if (hlpfile->version <= 16 && index != old_index && index != 0)
+ {
+ /* we jumped to the next block, adjust pointers */
+ ref -= 12;
+ offset -= 12;
+ }
+
+ if (index >= hlpfile->topic_maplen) {WINE_WARN("maplen\n"); break;}
+ buf = hlpfile->topic_map[index] + offset;
+ if (buf + 0x15 >= hlpfile->topic_end) {WINE_WARN("extra\n"); break;}
+ end = min(buf + GET_UINT(buf, 0), hlpfile->topic_end);
+ if (index != old_index) {old_index = index;}
+
+ switch (buf[0x14])
+ {
+ case 0x02:
+ if (count++) goto done;
+ break;
+ case 0x01:
+ case 0x20:
+ case 0x23:
+ if (!HLPFILE_BrowseParagraph(page, buf, end)) return FALSE;
+ break;
+ default:
+ WINE_ERR("buf[0x14] = %x\n", buf[0x14]);
+ }
+ if (hlpfile->version <= 16)
+ {
+ ref += GET_UINT(buf, 0xc);
+ if (GET_UINT(buf, 0xc) == 0)
+ break;
+ }
+ else
+ ref = GET_UINT(buf, 0xc);
+ } while (ref != 0xffffffff);
+done:
+ return TRUE;
+}
+
+/******************************************************************
* HLPFILE_ReadFont
*
*
diff --git a/programs/winhelp/hlpfile.h b/programs/winhelp/hlpfile.h
index 4d4dfce..87d87a3 100644
--- a/programs/winhelp/hlpfile.h
+++ b/programs/winhelp/hlpfile.h
@@ -94,6 +94,7 @@ typedef struct tagHlpFilePage
unsigned wNumber;
unsigned offset;
+ DWORD reference;
struct tagHlpFilePage* next;
struct tagHlpFilePage* prev;
@@ -196,3 +197,5 @@ void HLPFILE_FreeHlpFile(HLPFILE*);
void* HLPFILE_BPTreeSearch(BYTE*, const void*, HLPFILE_BPTreeCompare);
void HLPFILE_BPTreeEnum(BYTE*, HLPFILE_BPTreeCallback cb, void *cookie);
+
+BOOL HLPFILE_BrowsePage(HLPFILE_PAGE*);
diff --git a/programs/winhelp/winhelp.c b/programs/winhelp/winhelp.c
index 5f3fada..fbc9066 100644
--- a/programs/winhelp/winhelp.c
+++ b/programs/winhelp/winhelp.c
@@ -584,6 +584,8 @@ BOOL WINHELP_CreateHelpWindow(HLPFILE_PAGE* page, HLPFILE_WINDOWINFO* wi,
bPrimary = !lstrcmpi(wi->name, "main");
bPopup = !bPrimary && (wi->win_style & WS_POPUP);
+ if (page && !page->first_paragraph) HLPFILE_BrowsePage(page);
+
/* Initialize WINHELP_WINDOW struct */
win = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
sizeof(WINHELP_WINDOW) + strlen(wi->name) + 1);
More information about the wine-patches
mailing list