hlpfile.c

来自「ReactOS是一些高手根据Windows XP的内核编写出的类XP。内核实现机」· C语言 代码 · 共 2,066 行 · 第 1/5 页

C
2,066
字号
/* * Help Viewer * * Copyright    1996 Ulrich Schmid *              2002 Eric Pouech * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */#include <stdarg.h>#include <stdio.h>#include <string.h>#include "windef.h"#include "winbase.h"#include "wingdi.h"#include "winuser.h"#include "winhelp.h"#include "wine/debug.h"WINE_DEFAULT_DEBUG_CHANNEL(winhelp);static inline unsigned short GET_USHORT(const BYTE* buffer, unsigned i){    return (BYTE)buffer[i] + 0x100 * (BYTE)buffer[i + 1];}static inline short GET_SHORT(const BYTE* buffer, unsigned i){    return (BYTE)buffer[i] + 0x100 * (signed char)buffer[i+1];}static inline unsigned GET_UINT(const BYTE* buffer, unsigned i){    return GET_USHORT(buffer, i) + 0x10000 * GET_USHORT(buffer, i + 2);}static HLPFILE *first_hlpfile = 0;static BYTE    *file_buffer;static struct{    UINT        num;    unsigned*   offsets;    char*       buffer;} phrases;static struct{    BYTE**      map;    BYTE*       end;    UINT        wMapLen;} topic;static struct{    UINT                wFont;    UINT                wIndent;    UINT                wHSpace;    UINT                wVSpace;    HLPFILE_LINK*       link;} attributes;static BOOL  HLPFILE_DoReadHlpFile(HLPFILE*, LPCSTR);static BOOL  HLPFILE_ReadFileToBuffer(HFILE);static BOOL  HLPFILE_FindSubFile(LPCSTR name, BYTE**, BYTE**);static BOOL  HLPFILE_SystemCommands(HLPFILE*);static INT   HLPFILE_UncompressedLZ77_Size(BYTE *ptr, BYTE *end);static BYTE* HLPFILE_UncompressLZ77(BYTE *ptr, BYTE *end, BYTE *newptr);static BOOL  HLPFILE_UncompressLZ77_Phrases(HLPFILE*);static BOOL  HLPFILE_Uncompress_Phrases40(HLPFILE*);static BOOL  HLPFILE_Uncompress_Topic(HLPFILE*);static BOOL  HLPFILE_GetContext(HLPFILE*);static BOOL  HLPFILE_GetMap(HLPFILE*);static BOOL  HLPFILE_AddPage(HLPFILE*, BYTE*, BYTE*, unsigned);static BOOL  HLPFILE_AddParagraph(HLPFILE*, BYTE *, BYTE*, unsigned*);static void  HLPFILE_Uncompress2(const BYTE*, const BYTE*, BYTE*, const BYTE*);static BOOL  HLPFILE_Uncompress3(char*, const char*, const BYTE*, const BYTE*);static void  HLPFILE_UncompressRLE(const BYTE* src, const BYTE* end, BYTE** dst, unsigned dstsz);static BOOL  HLPFILE_ReadFont(HLPFILE* hlpfile);#if 0/*********************************************************************** * *           HLPFILE_PageByNumber */static HLPFILE_PAGE *HLPFILE_PageByNumber(LPCSTR lpszPath, UINT wNum){    HLPFILE_PAGE *page;    HLPFILE *hlpfile = HLPFILE_ReadHlpFile(lpszPath);    if (!hlpfile) return 0;    WINE_TRACE("[%s/%u]\n", lpszPath, wNum);    for (page = hlpfile->first_page; page && wNum; page = page->next) wNum--;    /* HLPFILE_FreeHlpFile(lpszPath); */    return page;}#endif/* FIXME: * this finds the page containing the offset. The offset can either * refer to the top of the page (offset == page->offset), or * to some paragraph inside the page... * As of today, we only return the page... we should also return * a paragraph, and then, while opening a new page, compute the * y-offset of the paragraph to be shown and scroll the window * accordinly *//****************************************************************** *		HLPFILE_PageByOffset * * */HLPFILE_PAGE *HLPFILE_PageByOffset(HLPFILE* hlpfile, LONG offset){    HLPFILE_PAGE*       page;    HLPFILE_PAGE*       found;    if (!hlpfile) return 0;    WINE_TRACE("<%s>[%x]\n", hlpfile->lpszPath, offset);    if (offset == 0xFFFFFFFF) return NULL;    page = NULL;    for (found = NULL, page = hlpfile->first_page; page; page = page->next)    {        if (page->offset <= offset && (!found || found->offset < page->offset))            found = page;    }    if (!found)        WINE_ERR("Page of offset %u not found in file %s\n",                 offset, hlpfile->lpszPath);    return found;}/*********************************************************************** * *           HLPFILE_HlpFilePageByHash */HLPFILE_PAGE *HLPFILE_PageByHash(HLPFILE* hlpfile, LONG lHash){    int                 i;    if (!hlpfile) return 0;    WINE_TRACE("<%s>[%x]\n", hlpfile->lpszPath, lHash);    for (i = 0; i < hlpfile->wContextLen; i++)    {        if (hlpfile->Context[i].lHash == lHash)            return HLPFILE_PageByOffset(hlpfile, hlpfile->Context[i].offset);    }    WINE_ERR("Page of hash %x not found in file %s\n", lHash, hlpfile->lpszPath);    return NULL;}/*********************************************************************** * *           HLPFILE_PageByMap */HLPFILE_PAGE *HLPFILE_PageByMap(HLPFILE* hlpfile, LONG lMap){    int                 i;    if (!hlpfile) return 0;    WINE_TRACE("<%s>[%x]\n", hlpfile->lpszPath, lMap);    for (i = 0; i < hlpfile->wMapLen; i++)    {        if (hlpfile->Map[i].lMap == lMap)            return HLPFILE_PageByOffset(hlpfile, hlpfile->Map[i].offset);    }    WINE_ERR("Page of Map %x not found in file %s\n", lMap, hlpfile->lpszPath);    return NULL;}/*********************************************************************** * *           HLPFILE_Contents */HLPFILE_PAGE* HLPFILE_Contents(HLPFILE *hlpfile){    HLPFILE_PAGE*       page = NULL;    if (!hlpfile) return NULL;    page = HLPFILE_PageByOffset(hlpfile, hlpfile->contents_start);    if (!page) page = hlpfile->first_page;    return page;}/*********************************************************************** * *           HLPFILE_Hash */LONG HLPFILE_Hash(LPCSTR lpszContext){    LONG lHash = 0;    CHAR c;    while ((c = *lpszContext++))    {        CHAR x = 0;        if (c >= 'A' && c <= 'Z') x = c - 'A' + 17;        if (c >= 'a' && c <= 'z') x = c - 'a' + 17;        if (c >= '1' && c <= '9') x = c - '0';        if (c == '0') x = 10;        if (c == '.') x = 12;        if (c == '_') x = 13;        if (x) lHash = lHash * 43 + x;    }    return lHash;}/*********************************************************************** * *           HLPFILE_ReadHlpFile */HLPFILE *HLPFILE_ReadHlpFile(LPCSTR lpszPath){    HLPFILE*      hlpfile;    for (hlpfile = first_hlpfile; hlpfile; hlpfile = hlpfile->next)    {        if (!strcmp(lpszPath, hlpfile->lpszPath))        {            hlpfile->wRefCount++;            return hlpfile;        }    }    hlpfile = HeapAlloc(GetProcessHeap(), 0, sizeof(HLPFILE) + lstrlen(lpszPath) + 1);    if (!hlpfile) return 0;    hlpfile->lpszPath           = (char*)hlpfile + sizeof(HLPFILE);    hlpfile->lpszTitle          = NULL;    hlpfile->lpszCopyright      = NULL;    hlpfile->first_page         = NULL;    hlpfile->first_macro        = NULL;    hlpfile->wContextLen        = 0;    hlpfile->Context            = NULL;    hlpfile->wMapLen            = 0;    hlpfile->Map                = NULL;    hlpfile->contents_start     = 0xFFFFFFFF;    hlpfile->prev               = NULL;    hlpfile->next               = first_hlpfile;    hlpfile->wRefCount          = 1;    hlpfile->numBmps            = 0;    hlpfile->bmps               = NULL;    hlpfile->numFonts           = 0;    hlpfile->fonts              = NULL;    hlpfile->numWindows         = 0;    hlpfile->windows            = NULL;    strcpy(hlpfile->lpszPath, lpszPath);    first_hlpfile = hlpfile;    if (hlpfile->next) hlpfile->next->prev = hlpfile;    phrases.offsets = NULL;    phrases.buffer = NULL;    topic.map = NULL;    topic.end = NULL;    file_buffer = NULL;    if (!HLPFILE_DoReadHlpFile(hlpfile, lpszPath))    {        HLPFILE_FreeHlpFile(hlpfile);        hlpfile = 0;    }    HeapFree(GetProcessHeap(), 0, phrases.offsets);    HeapFree(GetProcessHeap(), 0, phrases.buffer);    HeapFree(GetProcessHeap(), 0, topic.map);    HeapFree(GetProcessHeap(), 0, file_buffer);    return hlpfile;}/*********************************************************************** * *           HLPFILE_DoReadHlpFile */static BOOL HLPFILE_DoReadHlpFile(HLPFILE *hlpfile, LPCSTR lpszPath){    BOOL        ret;    HFILE       hFile;    OFSTRUCT    ofs;    BYTE*       buf;    DWORD       ref = 0x0C;    unsigned    index, old_index, offset, len, offs;    hFile = OpenFile(lpszPath, &ofs, OF_READ);    if (hFile == HFILE_ERROR) return FALSE;    ret = HLPFILE_ReadFileToBuffer(hFile);    _lclose(hFile);    if (!ret) return FALSE;    if (!HLPFILE_SystemCommands(hlpfile)) return FALSE;    /* load phrases support */    if (!HLPFILE_UncompressLZ77_Phrases(hlpfile))        HLPFILE_Uncompress_Phrases40(hlpfile);    if (!HLPFILE_Uncompress_Topic(hlpfile)) return FALSE;    if (!HLPFILE_ReadFont(hlpfile)) return FALSE;    buf = topic.map[0];    old_index = -1;    offs = 0;    do    {        BYTE*   end;        /* FIXME this depends on the blocksize, can be 2k in some cases */        index  = (ref - 0x0C) >> 14;        offset = (ref - 0x0C) & 0x3fff;        WINE_TRACE("ref=%08x => [%u/%u]\n", ref, index, offset);        if (index >= topic.wMapLen) {WINE_WARN("maplen\n"); break;}        buf = topic.map[index] + offset;        if (buf + 0x15 >= topic.end) {WINE_WARN("extra\n"); break;}        end = min(buf + GET_UINT(buf, 0), topic.end);        if (index != old_index) {offs = 0; old_index = index;}        switch (buf[0x14])	{	case 0x02:            if (!HLPFILE_AddPage(hlpfile, buf, end, index * 0x8000L + offs)) return FALSE;            break;	case 0x20:            if (!HLPFILE_AddParagraph(hlpfile, buf, end, &len)) return FALSE;            offs += len;            break;	case 0x23:            if (!HLPFILE_AddParagraph(hlpfile, buf, end, &len)) return FALSE;            offs += len;            break;	default:            WINE_ERR("buf[0x14] = %x\n", buf[0x14]);	}        ref = GET_UINT(buf, 0xc);    } while (ref != 0xffffffff);    HLPFILE_GetMap(hlpfile);    return HLPFILE_GetContext(hlpfile);}/*********************************************************************** * *           HLPFILE_AddPage */static BOOL HLPFILE_AddPage(HLPFILE *hlpfile, BYTE *buf, BYTE *end, unsigned offset){    HLPFILE_PAGE* page;    BYTE*         title;    UINT          titlesize;    char*         ptr;    HLPFILE_MACRO*macro;    if (buf + 0x31 > end) {WINE_WARN("page1\n"); return FALSE;};    title = buf + GET_UINT(buf, 0x10);    if (title > end) {WINE_WARN("page2\n"); return FALSE;};    titlesize = GET_UINT(buf, 4);    page = HeapAlloc(GetProcessHeap(), 0, sizeof(HLPFILE_PAGE) + titlesize + 1);    if (!page) return FALSE;    page->lpszTitle = (char*)page + sizeof(HLPFILE_PAGE);    if (hlpfile->hasPhrases)    {        HLPFILE_Uncompress2(title, end, (BYTE*)page->lpszTitle, (BYTE*)page->lpszTitle + titlesize);    }    else    {        if (GET_UINT(buf, 0x4) > GET_UINT(buf, 0) - GET_UINT(buf, 0x10))        {            /* need to decompress */            HLPFILE_Uncompress3(page->lpszTitle, page->lpszTitle + titlesize,                                 title, end);        }        else        {            memcpy(page->lpszTitle, title, titlesize);

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?