Kirill K. Smirnov : winhelp: Correctly deal with various TopicBlockSize/ Compression combinations. Simplify HLPFILE_Uncompress_Topic function.

Alexandre Julliard julliard at winehq.org
Mon Dec 3 09:17:53 CST 2007


Module: wine
Branch: master
Commit: 1fdd01966c28301c9f76db3f66e8644baf67b4d7
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=1fdd01966c28301c9f76db3f66e8644baf67b4d7

Author: Kirill K. Smirnov <lich at math.spbu.ru>
Date:   Sat Dec  1 18:57:24 2007 +0300

winhelp: Correctly deal with various TopicBlockSize/Compression combinations. Simplify HLPFILE_Uncompress_Topic function.

---

 programs/winhelp/hlpfile.c |   84 ++++++++++++++++++++++++++------------------
 programs/winhelp/hlpfile.h |    3 ++
 2 files changed, 53 insertions(+), 34 deletions(-)

diff --git a/programs/winhelp/hlpfile.c b/programs/winhelp/hlpfile.c
index 3c34a06..e94dbfd 100644
--- a/programs/winhelp/hlpfile.c
+++ b/programs/winhelp/hlpfile.c
@@ -3,6 +3,7 @@
  *
  * Copyright    1996 Ulrich Schmid
  *              2002 Eric Pouech
+ *              2007 Kirill K. Smirnov
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -337,9 +338,8 @@ static BOOL HLPFILE_DoReadHlpFile(HLPFILE *hlpfile, LPCSTR lpszPath)
     {
         BYTE*   end;
 
-        /* FIXME this depends on the blocksize, can be 2k in some cases */
-        index  = (ref - 0x0C) >> 14;
-        offset = (ref - 0x0C) & 0x3fff;
+        index  = (ref - 0x0C) / hlpfile->dsize;
+        offset = (ref - 0x0C) % hlpfile->dsize;
 
         WINE_TRACE("ref=%08x => [%u/%u]\n", ref, index, offset);
 
@@ -1387,8 +1387,31 @@ static BOOL HLPFILE_SystemCommands(HLPFILE* hlpfile)
                magic, major, minor, flags);
     if (magic != 0x036C || major != 1)
     {WINE_WARN("Wrong system header\n"); return FALSE;}
-    if (minor <= 16) {WINE_WARN("too old file format (NIY)\n"); return FALSE;}
-    if (flags & 8) {WINE_WARN("Unsupported yet page size\n"); return FALSE;}
+    if (minor <= 16)
+    {
+        hlpfile->tbsize = 0x800;
+        hlpfile->compressed = 0;
+    }
+    else if (flags == 0)
+    {
+        hlpfile->tbsize = 0x1000;
+        hlpfile->compressed = 0;
+    }
+    else if (flags == 4)
+    {
+        hlpfile->tbsize = 0x1000;
+        hlpfile->compressed = 1;
+    }
+    else
+    {
+        hlpfile->tbsize = 0x800;
+        hlpfile->compressed = 1;
+    }
+
+    if (hlpfile->compressed)
+        hlpfile->dsize = 0x4000;
+    else
+        hlpfile->dsize = hlpfile->tbsize - 0x0C;
 
     hlpfile->version = minor;
     hlpfile->flags = flags;
@@ -1654,29 +1677,27 @@ static BOOL HLPFILE_Uncompress_Topic(HLPFILE* hlpfile)
 {
     BYTE *buf, *ptr, *end, *newptr;
     unsigned int i, newsize = 0;
+    unsigned int topic_size;
 
     if (!HLPFILE_FindSubFile("|TOPIC", &buf, &end))
     {WINE_WARN("topic0\n"); return FALSE;}
 
-    switch (hlpfile->flags & (8|4))
+    buf += 9; /* Skip file header */
+    topic_size = end - buf;
+    if (hlpfile->compressed)
     {
-    case 8:
-        WINE_FIXME("Unsupported format\n");
-        return FALSE;
-    case 4:
-        buf += 9;
-        topic.wMapLen = (end - buf - 1) / 0x1000 + 1;
-        
+        topic.wMapLen = (topic_size - 1) / hlpfile->tbsize + 1;
+
         for (i = 0; i < topic.wMapLen; i++)
         {
-            ptr = buf + i * 0x1000;
-            
+            ptr = buf + i * hlpfile->tbsize;
+
             /* I don't know why, it's necessary for printman.hlp */
             if (ptr + 0x44 > end) ptr = end - 0x44;
 
-            newsize += HLPFILE_UncompressedLZ77_Size(ptr + 0xc, min(end, ptr + 0x1000));
+            newsize += HLPFILE_UncompressedLZ77_Size(ptr + 0xc, min(end, ptr + hlpfile->tbsize));
         }
-        
+
         topic.map = HeapAlloc(GetProcessHeap(), 0,
                               topic.wMapLen * sizeof(topic.map[0]) + newsize);
         if (!topic.map) return FALSE;
@@ -1685,35 +1706,30 @@ static BOOL HLPFILE_Uncompress_Topic(HLPFILE* hlpfile)
 
         for (i = 0; i < topic.wMapLen; i++)
         {
-            ptr = buf + i * 0x1000;
+            ptr = buf + i * hlpfile->tbsize;
             if (ptr + 0x44 > end) ptr = end - 0x44;
 
             topic.map[i] = newptr;
-            newptr = HLPFILE_UncompressLZ77(ptr + 0xc, min(end, ptr + 0x1000), newptr);
+            newptr = HLPFILE_UncompressLZ77(ptr + 0xc, min(end, ptr + hlpfile->tbsize), newptr);
         }
-        break;
-    case 0:
-        /* basically, we need to copy the 0x1000 byte pages (removing the first 0x0C) in
-         * one single are in memory
+    }
+    else
+    {
+        /* basically, we need to copy the TopicBlockSize byte pages
+         * (removing the first 0x0C) in one single area in memory
          */
-#define DST_LEN (0x1000 - 0x0C)
-        buf += 9;
-        newsize = end - buf;
-        /* number of destination pages */
-        topic.wMapLen = (newsize - 1) / DST_LEN + 1;
+        topic.wMapLen = (topic_size - 1) / hlpfile->tbsize + 1;
         topic.map = HeapAlloc(GetProcessHeap(), 0,
-                              topic.wMapLen * (sizeof(topic.map[0]) + DST_LEN));
+                              topic.wMapLen * (sizeof(topic.map[0]) + hlpfile->dsize));
         if (!topic.map) return FALSE;
         newptr = (BYTE*)(topic.map + topic.wMapLen);
-        topic.end = newptr + newsize;
+        topic.end = newptr + topic_size;
 
         for (i = 0; i < topic.wMapLen; i++)
         {
-            topic.map[i] = newptr + i * DST_LEN;
-            memcpy(topic.map[i], buf + i * 0x1000 + 0x0C, DST_LEN);
+            topic.map[i] = newptr + i * hlpfile->dsize;
+            memcpy(topic.map[i], buf + i * hlpfile->tbsize + 0x0C, hlpfile->dsize);
         }
-#undef DST_LEN
-        break;
     }
     return TRUE;
 }
diff --git a/programs/winhelp/hlpfile.h b/programs/winhelp/hlpfile.h
index 4d62cdd..3c6b6b9 100644
--- a/programs/winhelp/hlpfile.h
+++ b/programs/winhelp/hlpfile.h
@@ -141,6 +141,9 @@ typedef struct tagHlpFileFile
 
     unsigned short              version;
     unsigned short              flags;
+    unsigned short              tbsize;     /* topic block size */
+    unsigned short              dsize;      /* decompress size */
+    unsigned short              compressed;
     unsigned                    hasPhrases; /* Phrases or PhrIndex/PhrImage */
 
     unsigned                    numBmps;




More information about the wine-cvs mailing list