/*
 * Copyright 2005 James Hawkins
 * Copyright 2007 Jacek Caban for CodeWeavers
 *
 * 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
 */

#ifndef HHCTRL_H
#define HHCTRL_H

#include <stdarg.h>

#define COBJMACROS

#include "windef.h"
#include "winbase.h"
#include "winternl.h"
#include "winuser.h"
#include "winnls.h"
#include "htmlhelp.h"
#include "ole2.h"
#include "exdisp.h"
#include "mshtmhst.h"
#include "commctrl.h"

#ifdef INIT_GUID
#include "initguid.h"
#endif

#include "wine/itss.h"
#include "wine/list.h"

#define WB_GOBACK     0
#define WB_GOFORWARD  1
#define WB_GOHOME     2
#define WB_SEARCH     3
#define WB_REFRESH    4
#define WB_STOP       5
#define WB_PRINT      6

typedef struct {
    LPWSTR chm_file;
    LPWSTR chm_index;
} ChmPath;

typedef struct ContentItem {
    struct ContentItem *parent;
    struct ContentItem *child;
    struct ContentItem *next;

    HTREEITEM id;

    LPWSTR name;
    LPWSTR local;
    ChmPath merge;
} ContentItem;

typedef struct IndexSubItem {
    LPWSTR name;
    LPWSTR local;
} IndexSubItem;

typedef struct IndexItem {
    struct IndexItem *next;

    HTREEITEM id;
    LPWSTR keyword;
    ChmPath merge;

    int nItems;
    int itemFlags;
    int indentLevel;
    IndexSubItem *items;
} IndexItem;

typedef struct SearchItem {
    struct SearchItem *next;

    HTREEITEM id;
    LPWSTR title;
    LPWSTR filename;
} SearchItem;

typedef struct CHMInfo
{
    IITStorage *pITStorage;
    IStorage *pStorage;
    WCHAR *szFile;

    IStream *strings_stream;
    char **strings;
    DWORD strings_size;

    WCHAR *compiledFile;
    WCHAR *defWindow;
    WCHAR *defTopic;
    WCHAR *defTitle;
    WCHAR *defToc;

    UINT codePage;
} CHMInfo;

#define TAB_CONTENTS   0
#define TAB_INDEX      1
#define TAB_SEARCH     2
#define TAB_FAVORITES  3
#define TAB_NUMTABS    TAB_FAVORITES

typedef struct {
    HWND hwnd;
    DWORD id;
} HHTab;

typedef struct {
    HWND hwndList;
    HWND hwndPopup;
    HWND hwndCallback;
} IndexPopup;

typedef struct {
    SearchItem *root;
    HWND hwndEdit;
    HWND hwndList;
    HWND hwndContainer;
} SearchTab;

typedef struct {
    HIMAGELIST hImageList;
} ContentsTab;

struct wintype_stringsW {
    WCHAR *pszType;
    WCHAR *pszCaption;
    WCHAR *pszToc;
    WCHAR *pszIndex;
    WCHAR *pszFile;
    WCHAR *pszHome;
    WCHAR *pszJump1;
    WCHAR *pszJump2;
    WCHAR *pszUrlJump1;
    WCHAR *pszUrlJump2;
    WCHAR *pszCustomTabs;
};

struct wintype_stringsA {
    char *pszType;
    char *pszCaption;
    char *pszToc;
    char *pszIndex;
    char *pszFile;
    char *pszHome;
    char *pszJump1;
    char *pszJump2;
    char *pszUrlJump1;
    char *pszUrlJump2;
    char *pszCustomTabs;
};

typedef struct {
    IOleClientSite IOleClientSite_iface;
    IOleInPlaceSite IOleInPlaceSite_iface;
    IOleInPlaceFrame IOleInPlaceFrame_iface;
    IDocHostUIHandler IDocHostUIHandler_iface;

    LONG ref;

    IOleObject *ole_obj;
    IWebBrowser2 *web_browser;
    HWND hwndWindow;
} WebBrowserContainer;

typedef struct {
    WebBrowserContainer *web_browser;

    HH_WINTYPEW WinType;

    struct wintype_stringsA stringsA;
    struct wintype_stringsW stringsW;

    struct list entry;
    CHMInfo *pCHMInfo;
    ContentItem *content;
    IndexItem *index;
    IndexPopup popup;
    SearchTab search;
    ContentsTab contents;
    HWND hwndTabCtrl;
    HWND hwndSizeBar;
    HFONT hFont;

    HHTab tabs[TAB_FAVORITES+1];
    int viewer_initialized;
    DWORD current_tab;
} HHInfo;

BOOL InitWebBrowser(HHInfo*,HWND) DECLSPEC_HIDDEN;
void ReleaseWebBrowser(HHInfo*) DECLSPEC_HIDDEN;
void ResizeWebBrowser(HHInfo*,DWORD,DWORD) DECLSPEC_HIDDEN;
void DoPageAction(WebBrowserContainer*,DWORD) DECLSPEC_HIDDEN;

void InitContent(HHInfo*) DECLSPEC_HIDDEN;
void ReleaseContent(HHInfo*) DECLSPEC_HIDDEN;
void ActivateContentTopic(HWND,LPCWSTR,ContentItem *) DECLSPEC_HIDDEN;

void InitIndex(HHInfo*) DECLSPEC_HIDDEN;
void ReleaseIndex(HHInfo*) DECLSPEC_HIDDEN;

CHMInfo *OpenCHM(LPCWSTR szFile) DECLSPEC_HIDDEN;
BOOL LoadWinTypeFromCHM(HHInfo *info) DECLSPEC_HIDDEN;
CHMInfo *CloseCHM(CHMInfo *pCHMInfo) DECLSPEC_HIDDEN;
void SetChmPath(ChmPath*,LPCWSTR,LPCWSTR) DECLSPEC_HIDDEN;
IStream *GetChmStream(CHMInfo*,LPCWSTR,ChmPath*) DECLSPEC_HIDDEN;
LPWSTR FindContextAlias(CHMInfo*,DWORD) DECLSPEC_HIDDEN;
WCHAR *GetDocumentTitle(CHMInfo*,LPCWSTR) DECLSPEC_HIDDEN;

extern struct list window_list DECLSPEC_HIDDEN;
HHInfo *CreateHelpViewer(HHInfo*,LPCWSTR,HWND) DECLSPEC_HIDDEN;
void ReleaseHelpViewer(HHInfo*) DECLSPEC_HIDDEN;
BOOL NavigateToUrl(HHInfo*,LPCWSTR) DECLSPEC_HIDDEN;
BOOL NavigateToChm(HHInfo*,LPCWSTR,LPCWSTR) DECLSPEC_HIDDEN;
void MergeChmProperties(HH_WINTYPEW*,HHInfo*,BOOL) DECLSPEC_HIDDEN;
void UpdateHelpWindow(HHInfo *info) DECLSPEC_HIDDEN;

void InitSearch(HHInfo *info, const char *needle) DECLSPEC_HIDDEN;
void ReleaseSearch(HHInfo *info) DECLSPEC_HIDDEN;

LPCWSTR skip_schema(LPCWSTR url) DECLSPEC_HIDDEN;
void wintype_stringsA_free(struct wintype_stringsA *stringsA) DECLSPEC_HIDDEN;
void wintype_stringsW_free(struct wintype_stringsW *stringsW) DECLSPEC_HIDDEN;
WCHAR *decode_html(const char *html_fragment, int html_fragment_len, UINT code_page) DECLSPEC_HIDDEN;
HHInfo *find_window(const WCHAR *window) DECLSPEC_HIDDEN;

/* memory allocation functions */

static inline LPWSTR strdupnAtoW(LPCSTR str, LONG lenA)
{
    LPWSTR ret;
    DWORD len;

    if(!str)
        return NULL;

    if (lenA > 0)
    {
        /* find length of string */
        LPCSTR eos = memchr(str, 0, lenA);
	if (eos) lenA = eos - str;
    }

    len = MultiByteToWideChar(CP_ACP, 0, str, lenA, NULL, 0)+1; /* +1 for null pad */
    ret = malloc(len * sizeof(WCHAR));
    MultiByteToWideChar(CP_ACP, 0, str, lenA, ret, len);
    ret[len-1] = 0;

    return ret;
}

static inline LPWSTR strdupAtoW(LPCSTR str)
{
    return strdupnAtoW(str, -1);
}

static inline LPSTR strdupWtoA(LPCWSTR str)
{
    LPSTR ret;
    DWORD len;

    if(!str)
        return NULL;

    len = WideCharToMultiByte(CP_ACP, 0, str, -1, NULL, 0, NULL, NULL);
    ret = malloc(len);
    WideCharToMultiByte(CP_ACP, 0, str, -1, ret, len, NULL, NULL);
    return ret;
}


extern HINSTANCE hhctrl_hinstance DECLSPEC_HIDDEN;
extern BOOL hh_process DECLSPEC_HIDDEN;

#endif
