/* * Help Viewer * * Copyright 1996 Ulrich Schmid * Copyright 2002, 2008 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 */ #define WIN32_LEAN_AND_MEAN #include <stdio.h> #include "windows.h" #include "commdlg.h" #include "shellapi.h" #include "winhelp.h" #include "wine/debug.h" WINE_DEFAULT_DEBUG_CHANNEL(winhelp); /**************************************************/ /* Macro table */ /**************************************************/ struct MacroDesc { const char* name; const char* alias; BOOL isBool; const char* arguments; void *fn; }; static struct MacroDesc*MACRO_Loaded /* = NULL */; static unsigned MACRO_NumLoaded /* = 0 */; /******* helper functions *******/ static char* StrDup(const char* str) { char* dst; dst=HeapAlloc(GetProcessHeap(),0,strlen(str)+1); strcpy(dst, str); return dst; } static WINHELP_BUTTON** MACRO_LookupButton(WINHELP_WINDOW* win, LPCSTR name) { WINHELP_BUTTON** b; for (b = &win->first_button; *b; b = &(*b)->next) if (!lstrcmpiA(name, (*b)->lpszID)) break; return b; } /******* some forward declarations *******/ static void CALLBACK MACRO_JumpID(LPCSTR lpszPathWindow, LPCSTR topic_id); /******* real macro implementation *******/ void CALLBACK MACRO_CreateButton(LPCSTR id, LPCSTR name, LPCSTR macro) { WINHELP_WINDOW *win = MACRO_CurrentWindow(); WINHELP_BUTTON *button, **b; LONG size; LPSTR ptr; WINE_TRACE("(%s, %s, %s)\n", debugstr_a(id), debugstr_a(name), debugstr_a(macro)); size = sizeof(WINHELP_BUTTON) + strlen(id) + strlen(name) + strlen(macro) + 3; button = HeapAlloc(GetProcessHeap(), 0, size); if (!button) return; button->next = 0; button->hWnd = 0; ptr = (char*)button + sizeof(WINHELP_BUTTON); strcpy(ptr, id); button->lpszID = ptr; ptr += strlen(id) + 1; strcpy(ptr, name); button->lpszName = ptr; ptr += strlen(name) + 1; strcpy(ptr, macro); button->lpszMacro = ptr; button->wParam = WH_FIRST_BUTTON; for (b = &win->first_button; *b; b = &(*b)->next) button->wParam = max(button->wParam, (*b)->wParam + 1); *b = button; WINHELP_LayoutMainWindow(win); } static void CALLBACK MACRO_DestroyButton(LPCSTR str) { WINE_FIXME("(%s)\n", debugstr_a(str)); } void CALLBACK MACRO_DisableButton(LPCSTR id) { WINHELP_BUTTON** b; WINE_TRACE("(%s)\n", debugstr_a(id)); b = MACRO_LookupButton(MACRO_CurrentWindow(), id); if (!*b) {WINE_FIXME("Couldn't find button %s\n", debugstr_a(id)); return;} EnableWindow((*b)->hWnd, FALSE); } static void CALLBACK MACRO_EnableButton(LPCSTR id) { WINHELP_BUTTON** b; WINE_TRACE("(%s)\n", debugstr_a(id)); b = MACRO_LookupButton(MACRO_CurrentWindow(), id); if (!*b) {WINE_FIXME("Couldn't find button %s\n", debugstr_a(id)); return;} EnableWindow((*b)->hWnd, TRUE); } void CALLBACK MACRO_JumpContents(LPCSTR lpszPath, LPCSTR lpszWindow) { HLPFILE* hlpfile; WINE_TRACE("(%s, %s)\n", debugstr_a(lpszPath), debugstr_a(lpszWindow)); if ((hlpfile = WINHELP_LookupHelpFile(lpszPath))) WINHELP_OpenHelpWindow(HLPFILE_PageByHash, hlpfile, 0, WINHELP_GetWindowInfo(hlpfile, lpszWindow), SW_NORMAL); } void CALLBACK MACRO_About(void) { WCHAR name[256]; HICON icon = LoadImageW( Globals.hInstance, MAKEINTRESOURCEW(IDI_WINHELP), IMAGE_ICON, 48, 48, LR_SHARED ); LoadStringW( Globals.hInstance, STID_WINE_HELP, name, ARRAY_SIZE( name )); ShellAboutW( MACRO_CurrentWindow()->hMainWnd, name, NULL, icon ); } static void CALLBACK MACRO_AddAccelerator(LONG u1, LONG u2, LPCSTR str) { WINE_FIXME("(%u, %u, %s)\n", u1, u2, debugstr_a(str)); } static void CALLBACK MACRO_ALink(LPCSTR str1, LONG u, LPCSTR str2) { WINE_FIXME("(%s, %u, %s)\n", debugstr_a(str1), u, debugstr_a(str2)); } void CALLBACK MACRO_Annotate(void) { WINE_FIXME("()\n"); } static void CALLBACK MACRO_AppendItem(LPCSTR str1, LPCSTR str2, LPCSTR str3, LPCSTR str4) { WINE_FIXME("(%s, %s, %s, %s)\n", debugstr_a(str1), debugstr_a(str2), debugstr_a(str3), debugstr_a(str4)); } static void CALLBACK MACRO_Back(void) { WINHELP_WINDOW* win = MACRO_CurrentWindow(); WINE_TRACE("()\n"); if (win && win->back.index >= 2) WINHELP_CreateHelpWindow(&win->back.set[--win->back.index - 1], SW_SHOW, FALSE); } static void CALLBACK MACRO_BackFlush(void) { WINHELP_WINDOW* win = MACRO_CurrentWindow(); WINE_TRACE("()\n"); if (win) WINHELP_DeleteBackSet(win); } void CALLBACK MACRO_BookmarkDefine(void) { WINE_FIXME("()\n"); } static void CALLBACK MACRO_BookmarkMore(void) { WINE_FIXME("()\n"); } static void CALLBACK MACRO_BrowseButtons(void) { HLPFILE_PAGE* page = MACRO_CurrentWindow()->page; ULONG relative; WINE_TRACE("()\n"); MACRO_CreateButton("BTN_PREV", "&<<", "Prev()"); MACRO_CreateButton("BTN_NEXT", "&>>", "Next()"); if (!HLPFILE_PageByOffset(page->file, page->browse_bwd, &relative)) MACRO_DisableButton("BTN_PREV"); if (!HLPFILE_PageByOffset(page->file, page->browse_fwd, &relative)) MACRO_DisableButton("BTN_NEXT"); } static void CALLBACK MACRO_ChangeButtonBinding(LPCSTR id, LPCSTR macro) { WINHELP_WINDOW* win = MACRO_CurrentWindow(); WINHELP_BUTTON* button; WINHELP_BUTTON** b; LONG size; LPSTR ptr; WINE_TRACE("(%s, %s)\n", debugstr_a(id), debugstr_a(macro)); b = MACRO_LookupButton(win, id); if (!*b) {WINE_FIXME("Couldn't find button %s\n", debugstr_a(id)); return;} size = sizeof(WINHELP_BUTTON) + strlen(id) + strlen((*b)->lpszName) + strlen(macro) + 3; button = HeapAlloc(GetProcessHeap(), 0, size); if (!button) return; button->next = (*b)->next; button->hWnd = (*b)->hWnd; button->wParam = (*b)->wParam; ptr = (char*)button + sizeof(WINHELP_BUTTON); strcpy(ptr, id); button->lpszID = ptr; ptr += strlen(id) + 1; strcpy(ptr, (*b)->lpszName); button->lpszName = ptr; ptr += strlen((*b)->lpszName) + 1; strcpy(ptr, macro); button->lpszMacro = ptr; *b = button; WINHELP_LayoutMainWindow(win); } static void CALLBACK MACRO_ChangeEnable(LPCSTR id, LPCSTR macro) { WINE_TRACE("(%s, %s)\n", debugstr_a(id), debugstr_a(macro)); MACRO_ChangeButtonBinding(id, macro); MACRO_EnableButton(id); } static void CALLBACK MACRO_ChangeItemBinding(LPCSTR str1, LPCSTR str2) { WINE_FIXME("(%s, %s)\n", debugstr_a(str1), debugstr_a(str2)); } static void CALLBACK MACRO_CheckItem(LPCSTR str) { WINE_FIXME("(%s)\n", debugstr_a(str)); } static void CALLBACK MACRO_CloseSecondarys(void) { WINHELP_WINDOW *win; WINHELP_WINDOW *next; WINE_TRACE("()\n"); for (win = Globals.win_list; win; win = next) { next = win->next; if (lstrcmpiA(win->info->name, "main")) WINHELP_ReleaseWindow(win); } } static void CALLBACK MACRO_CloseWindow(LPCSTR lpszWindow) { WINHELP_WINDOW *win; WINHELP_WINDOW *next; WINE_TRACE("(%s)\n", debugstr_a(lpszWindow)); if (!lpszWindow || !lpszWindow[0]) lpszWindow = "main"; for (win = Globals.win_list; win; win = next) { next = win->next; if (!lstrcmpiA(win->info->name, lpszWindow)) WINHELP_ReleaseWindow(win); } } static void CALLBACK MACRO_Compare(LPCSTR str) { WINE_FIXME("(%s)\n", debugstr_a(str)); } static void CALLBACK MACRO_Contents(void) { HLPFILE_PAGE* page = MACRO_CurrentWindow()->page; WINE_TRACE("()\n"); if (page) MACRO_JumpContents(page->file->lpszPath, NULL); } static void CALLBACK MACRO_ControlPanel(LPCSTR str1, LPCSTR str2, LONG u) { WINE_FIXME("(%s, %s, %u)\n", debugstr_a(str1), debugstr_a(str2), u); } void CALLBACK MACRO_CopyDialog(void) { WINE_FIXME("()\n"); } static void CALLBACK MACRO_CopyTopic(void) { WINE_FIXME("()\n"); } static void CALLBACK MACRO_DeleteItem(LPCSTR str) { WINE_FIXME("(%s)\n", debugstr_a(str)); } static void CALLBACK MACRO_DeleteMark(LPCSTR str) { WINE_FIXME("(%s)\n", debugstr_a(str)); } static void CALLBACK MACRO_DisableItem(LPCSTR str) { WINE_FIXME("(%s)\n", debugstr_a(str)); } static void CALLBACK MACRO_EnableItem(LPCSTR str) { WINE_FIXME("(%s)\n", debugstr_a(str)); } static void CALLBACK MACRO_EndMPrint(void) { WINE_FIXME("()\n"); } static void CALLBACK MACRO_ExecFile(LPCSTR pgm, LPCSTR args, LONG cmd_show, LPCSTR topic) { HINSTANCE ret; WINE_TRACE("(%s, %s, %u, %s)\n", debugstr_a(pgm), debugstr_a(args), cmd_show, debugstr_a(topic)); ret = ShellExecuteA(Globals.active_win ? Globals.active_win->hMainWnd : NULL, "open", pgm, args, ".", cmd_show); if ((DWORD_PTR)ret < 32) { WINE_WARN("Failed with %p\n", ret); if (topic) MACRO_JumpID(NULL, topic); } } static void CALLBACK MACRO_ExecProgram(LPCSTR str, LONG u) { WINE_FIXME("(%s, %u)\n", debugstr_a(str), u); } void CALLBACK MACRO_Exit(void) { WINE_TRACE("()\n"); while (Globals.win_list) WINHELP_ReleaseWindow(Globals.win_list); } static void CALLBACK MACRO_ExtAbleItem(LPCSTR str, LONG u) { WINE_FIXME("(%s, %u)\n", debugstr_a(str), u); } static void CALLBACK MACRO_ExtInsertItem(LPCSTR str1, LPCSTR str2, LPCSTR str3, LPCSTR str4, LONG u1, LONG u2) { WINE_FIXME("(%s, %s, %s, %s, %u, %u)\n", debugstr_a(str1), debugstr_a(str2), debugstr_a(str3), debugstr_a(str4), u1, u2); } static void CALLBACK MACRO_ExtInsertMenu(LPCSTR str1, LPCSTR str2, LPCSTR str3, LONG u1, LONG u2) { WINE_FIXME("(%s, %s, %s, %u, %u)\n", debugstr_a(str1), debugstr_a(str2), debugstr_a(str3), u1, u2); } static BOOL CALLBACK MACRO_FileExist(LPCSTR str) { WINE_TRACE("(%s)\n", debugstr_a(str)); return GetFileAttributesA(str) != INVALID_FILE_ATTRIBUTES; } void CALLBACK MACRO_FileOpen(void) { char szFile[MAX_PATH]; if (WINHELP_GetOpenFileName(szFile, MAX_PATH)) { MACRO_JumpContents(szFile, "main"); } } static void CALLBACK MACRO_Find(void) { WINE_FIXME("()\n"); } static void CALLBACK MACRO_Finder(void) { WINHELP_CreateIndexWindow(FALSE); } static void CALLBACK MACRO_FloatingMenu(void) { WINE_FIXME("()\n"); } static void CALLBACK MACRO_Flush(void) { WINE_FIXME("()\n"); } static void CALLBACK MACRO_FocusWindow(LPCSTR lpszWindow) { WINHELP_WINDOW *win; WINE_TRACE("(%s)\n", debugstr_a(lpszWindow)); if (!lpszWindow || !lpszWindow[0]) lpszWindow = "main"; for (win = Globals.win_list; win; win = win->next) if (!lstrcmpiA(win->info->name, lpszWindow)) SetFocus(win->hMainWnd); } static void CALLBACK MACRO_Generate(LPCSTR str, LONG w, LONG l) { WINE_FIXME("(%s, %x, %x)\n", debugstr_a(str), w, l); } static void CALLBACK MACRO_GotoMark(LPCSTR str) { WINE_FIXME("(%s)\n", debugstr_a(str)); } void CALLBACK MACRO_HelpOn(void) { WINHELP_WINDOW *win = MACRO_CurrentWindow(); LPCSTR file = NULL; WINE_TRACE("()\n"); if (win && win->page && win->page->file) file = win->page->file->help_on_file; if (!file) file = (Globals.wVersion > 4) ? "winhlp32.hlp" : "winhelp.hlp"; MACRO_JumpContents(file, NULL); } void CALLBACK MACRO_HelpOnTop(void) { static BOOL on_top = FALSE; WINHELP_WINDOW *win; HWND main_wnd = NULL; HMENU menu; for (win = Globals.win_list; win; win = win->next) if (!lstrcmpiA(win->info->name, "main")) main_wnd = win->hMainWnd; if (!main_wnd) { WINE_ERR("could not find the main window!\n"); return; } menu = GetMenu(main_wnd); on_top = !on_top; if (on_top) { CheckMenuItem(menu, MNID_HELP_HELPTOP, MF_BYCOMMAND|MF_CHECKED); SetWindowPos(main_wnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE); } else { CheckMenuItem(menu, MNID_HELP_HELPTOP, MF_BYCOMMAND|MF_UNCHECKED); SetWindowPos(main_wnd, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE); } } void CALLBACK MACRO_History(void) { WINE_TRACE("()\n"); if (Globals.active_win && !Globals.active_win->hHistoryWnd) { HWND hWnd = CreateWindowA(HISTORY_WIN_CLASS_NAME, "History", WS_OVERLAPPEDWINDOW, 0, 0, 0, 0, 0, 0, Globals.hInstance, Globals.active_win); ShowWindow(hWnd, SW_NORMAL); } } static void CALLBACK MACRO_IfThen(BOOL b, LPCSTR t) { if (b) MACRO_ExecuteMacro(MACRO_CurrentWindow(), t); } static void CALLBACK MACRO_IfThenElse(BOOL b, LPCSTR t, LPCSTR f) { if (b) MACRO_ExecuteMacro(MACRO_CurrentWindow(), t); else MACRO_ExecuteMacro(MACRO_CurrentWindow(), f); } static BOOL CALLBACK MACRO_InitMPrint(void) { WINE_FIXME("()\n"); return FALSE; } static void CALLBACK MACRO_InsertItem(LPCSTR str1, LPCSTR str2, LPCSTR str3, LPCSTR str4, LONG u) { WINE_FIXME("(%s, %s, %s, %s, %u)\n", debugstr_a(str1), debugstr_a(str2), debugstr_a(str3), debugstr_a(str4), u); } static void CALLBACK MACRO_InsertMenu(LPCSTR str1, LPCSTR str2, LONG u) { WINE_FIXME("(%s, %s, %u)\n", debugstr_a(str1), debugstr_a(str2), u); } static BOOL CALLBACK MACRO_IsBook(void) { WINE_TRACE("()\n"); return Globals.isBook; } static BOOL CALLBACK MACRO_IsMark(LPCSTR str) { WINE_FIXME("(%s)\n", debugstr_a(str)); return FALSE; } static BOOL CALLBACK MACRO_IsNotMark(LPCSTR str) { WINE_FIXME("(%s)\n", debugstr_a(str)); return TRUE; } void CALLBACK MACRO_JumpContext(LPCSTR lpszPath, LPCSTR lpszWindow, LONG context) { HLPFILE* hlpfile; WINE_TRACE("(%s, %s, %d)\n", debugstr_a(lpszPath), debugstr_a(lpszWindow), context); if ((hlpfile = WINHELP_LookupHelpFile(lpszPath))) /* Some madness: what user calls 'context', hlpfile calls 'map' */ WINHELP_OpenHelpWindow(HLPFILE_PageByMap, hlpfile, context, WINHELP_GetWindowInfo(hlpfile, lpszWindow), SW_NORMAL); } void CALLBACK MACRO_JumpHash(LPCSTR lpszPath, LPCSTR lpszWindow, LONG lHash) { HLPFILE* hlpfile; WINE_TRACE("(%s, %s, %u)\n", debugstr_a(lpszPath), debugstr_a(lpszWindow), lHash); if (!lpszPath || !lpszPath[0]) hlpfile = MACRO_CurrentWindow()->page->file; else hlpfile = WINHELP_LookupHelpFile(lpszPath); if (hlpfile) WINHELP_OpenHelpWindow(HLPFILE_PageByHash, hlpfile, lHash, WINHELP_GetWindowInfo(hlpfile, lpszWindow), SW_NORMAL); } static void CALLBACK MACRO_JumpHelpOn(void) { WINE_FIXME("()\n"); } static void CALLBACK MACRO_JumpID(LPCSTR lpszPathWindow, LPCSTR topic_id) { LPSTR ptr; WINE_TRACE("(%s, %s)\n", debugstr_a(lpszPathWindow), debugstr_a(topic_id)); if (lpszPathWindow && (ptr = strchr(lpszPathWindow, '>')) != NULL) { LPSTR tmp; size_t sz; tmp = HeapAlloc(GetProcessHeap(), 0, strlen(lpszPathWindow) + 1); if (tmp) { strcpy(tmp, lpszPathWindow); tmp[ptr - lpszPathWindow] = '\0'; ptr += tmp - lpszPathWindow; /* ptr now points to '>' in tmp buffer */ /* in some cases, we have a trailing space that we need to get rid of */ /* FIXME: check if it has to be done in lexer rather than here */ for (sz = strlen(ptr + 1); sz >= 1 && ptr[sz] == ' '; sz--) ptr[sz] = '\0'; MACRO_JumpHash(tmp, ptr + 1, HLPFILE_Hash(topic_id)); HeapFree(GetProcessHeap(), 0, tmp); } } else MACRO_JumpHash(lpszPathWindow, NULL, HLPFILE_Hash(topic_id)); } /* FIXME: this macros is wrong * it should only contain 2 strings, path & window are coded as path>window */ static void CALLBACK MACRO_JumpKeyword(LPCSTR lpszPath, LPCSTR lpszWindow, LPCSTR keyword) { WINE_FIXME("(%s, %s, %s)\n", debugstr_a(lpszPath), debugstr_a(lpszWindow), debugstr_a(keyword)); } static void CALLBACK MACRO_KLink(LPCSTR str1, LONG u, LPCSTR str2, LPCSTR str3) { WINE_FIXME("(%s, %u, %s, %s)\n", debugstr_a(str1), u, debugstr_a(str2), debugstr_a(str3)); } static void CALLBACK MACRO_Menu(void) { WINE_FIXME("()\n"); } static void CALLBACK MACRO_MPrintHash(LONG u) { WINE_FIXME("(%u)\n", u); } static void CALLBACK MACRO_MPrintID(LPCSTR str) { WINE_FIXME("(%s)\n", debugstr_a(str)); } static void CALLBACK MACRO_Next(void) { WINHELP_WNDPAGE wp; WINE_TRACE("()\n"); wp.page = MACRO_CurrentWindow()->page; wp.page = HLPFILE_PageByOffset(wp.page->file, wp.page->browse_fwd, &wp.relative); if (wp.page) { wp.page->file->wRefCount++; wp.wininfo = MACRO_CurrentWindow()->info; WINHELP_CreateHelpWindow(&wp, SW_NORMAL, TRUE); } } static void CALLBACK MACRO_NoShow(void) { WINE_FIXME("()\n"); } void CALLBACK MACRO_PopupContext(LPCSTR str, LONG u) { WINE_FIXME("(%s, %u)\n", debugstr_a(str), u); } static void CALLBACK MACRO_PopupHash(LPCSTR str, LONG u) { WINE_FIXME("(%s, %u)\n", debugstr_a(str), u); } static void CALLBACK MACRO_PopupId(LPCSTR str1, LPCSTR str2) { WINE_FIXME("(%s, %s)\n", debugstr_a(str1), debugstr_a(str2)); } static void CALLBACK MACRO_PositionWindow(LONG i1, LONG i2, LONG u1, LONG u2, LONG u3, LPCSTR str) { WINE_FIXME("(%i, %i, %u, %u, %u, %s)\n", i1, i2, u1, u2, u3, debugstr_a(str)); } static void CALLBACK MACRO_Prev(void) { WINHELP_WNDPAGE wp; WINE_TRACE("()\n"); wp.page = MACRO_CurrentWindow()->page; wp.page = HLPFILE_PageByOffset(wp.page->file, wp.page->browse_bwd, &wp.relative); if (wp.page) { wp.page->file->wRefCount++; wp.wininfo = MACRO_CurrentWindow()->info; WINHELP_CreateHelpWindow(&wp, SW_NORMAL, TRUE); } } void CALLBACK MACRO_Print(void) { PRINTDLGW printer; WINE_TRACE("()\n"); printer.lStructSize = sizeof(printer); printer.hwndOwner = MACRO_CurrentWindow()->hMainWnd; printer.hInstance = Globals.hInstance; printer.hDevMode = 0; printer.hDevNames = 0; printer.hDC = 0; printer.Flags = 0; printer.nFromPage = 0; printer.nToPage = 0; printer.nMinPage = 0; printer.nMaxPage = 0; printer.nCopies = 0; printer.lCustData = 0; printer.lpfnPrintHook = 0; printer.lpfnSetupHook = 0; printer.lpPrintTemplateName = 0; printer.lpSetupTemplateName = 0; printer.hPrintTemplate = 0; printer.hSetupTemplate = 0; if (PrintDlgW(&printer)) { WINE_FIXME("Print()\n"); } } void CALLBACK MACRO_PrinterSetup(void) { WINE_FIXME("()\n"); } static void CALLBACK MACRO_RegisterRoutine(LPCSTR dll_name, LPCSTR proc, LPCSTR args) { void *fn = NULL; int size; WINHELP_DLL* dll; WINE_TRACE("(%s, %s, %s)\n", debugstr_a(dll_name), debugstr_a(proc), debugstr_a(args)); /* FIXME: are the registered DLLs global or linked to the current file ??? * We assume globals (as we did for macros, but is this really the case ???) */ for (dll = Globals.dlls; dll; dll = dll->next) { if (!strcmp(dll->name, dll_name)) break; } if (!dll) { HANDLE hLib = LoadLibraryA(dll_name); /* FIXME: the library will not be unloaded until exit of program * We don't send the DW_TERM message */ WINE_TRACE("Loading %s\n", debugstr_a(dll_name)); /* FIXME: should look in the directory where current hlpfile * is loaded from */ if (hLib == NULL) { /* FIXME: internationalisation for error messages */ WINE_FIXME("Cannot find dll %s\n", debugstr_a(dll_name)); } else if ((dll = HeapAlloc(GetProcessHeap(), 0, sizeof(*dll)))) { dll->hLib = hLib; dll->name = StrDup(dll_name); /* FIXME: never freed */ dll->next = Globals.dlls; Globals.dlls = dll; dll->handler = (WINHELP_LDLLHandler)GetProcAddress(dll->hLib, "LDLLHandler"); dll->class = dll->handler ? (dll->handler)(DW_WHATMSG, 0, 0) : DC_NOMSG; WINE_TRACE("Got class %x for DLL %s\n", dll->class, debugstr_a(dll_name)); if (dll->class & DC_INITTERM) dll->handler(DW_INIT, 0, 0); if (dll->class & DC_CALLBACKS) dll->handler(DW_CALLBACKS, (LONG_PTR)&Callbacks, 0); } else WINE_WARN("OOM\n"); } if (dll && !(fn = GetProcAddress(dll->hLib, proc))) { /* FIXME: internationalisation for error messages */ WINE_FIXME("Cannot find proc %s in dll %s\n", debugstr_a(dll_name), debugstr_a(proc)); } size = ++MACRO_NumLoaded * sizeof(struct MacroDesc); if (!MACRO_Loaded) MACRO_Loaded = HeapAlloc(GetProcessHeap(), 0, size); else MACRO_Loaded = HeapReAlloc(GetProcessHeap(), 0, MACRO_Loaded, size); MACRO_Loaded[MACRO_NumLoaded - 1].name = StrDup(proc); /* FIXME: never freed */ MACRO_Loaded[MACRO_NumLoaded - 1].alias = NULL; MACRO_Loaded[MACRO_NumLoaded - 1].isBool = FALSE; MACRO_Loaded[MACRO_NumLoaded - 1].arguments = StrDup(args); /* FIXME: never freed */ MACRO_Loaded[MACRO_NumLoaded - 1].fn = fn; WINE_TRACE("Added %s(%s) at %p\n", debugstr_a(proc), debugstr_a(args), fn); } static void CALLBACK MACRO_RemoveAccelerator(LONG u1, LONG u2) { WINE_FIXME("(%u, %u)\n", u1, u2); } static void CALLBACK MACRO_ResetMenu(void) { WINE_FIXME("()\n"); } static void CALLBACK MACRO_SaveMark(LPCSTR str) { WINE_FIXME("(%s)\n", debugstr_a(str)); } static void CALLBACK MACRO_Search(void) { WINHELP_CreateIndexWindow(TRUE); } void CALLBACK MACRO_SetContents(LPCSTR str, LONG u) { WINE_FIXME("(%s, %u)\n", debugstr_a(str), u); } static void CALLBACK MACRO_SetHelpOnFile(LPCSTR str) { HLPFILE_PAGE* page = MACRO_CurrentWindow()->page; WINE_TRACE("(%s)\n", debugstr_a(str)); HeapFree(GetProcessHeap(), 0, page->file->help_on_file); page->file->help_on_file = HeapAlloc(GetProcessHeap(), 0, strlen(str) + 1); if (page->file->help_on_file) strcpy(page->file->help_on_file, str); } static void CALLBACK MACRO_SetPopupColor(LONG r, LONG g, LONG b) { HLPFILE_PAGE* page = MACRO_CurrentWindow()->page; WINE_TRACE("(%x, %x, %x)\n", r, g, b); page->file->has_popup_color = TRUE; page->file->popup_color = RGB(r, g, b); } static void CALLBACK MACRO_ShellExecute(LPCSTR str1, LPCSTR str2, LONG u1, LONG u2, LPCSTR str3, LPCSTR str4) { WINE_FIXME("(%s, %s, %u, %u, %s, %s)\n", debugstr_a(str1), debugstr_a(str2), u1, u2, debugstr_a(str3), debugstr_a(str4)); } static void CALLBACK MACRO_ShortCut(LPCSTR str1, LPCSTR str2, LONG w, LONG l, LPCSTR str) { WINE_FIXME("(%s, %s, %x, %x, %s)\n", debugstr_a(str1), debugstr_a(str2), w, l, debugstr_a(str)); } static void CALLBACK MACRO_TCard(LONG u) { WINE_FIXME("(%u)\n", u); } static void CALLBACK MACRO_Test(LONG u) { WINE_FIXME("(%u)\n", u); } static BOOL CALLBACK MACRO_TestALink(LPCSTR str) { WINE_FIXME("(%s)\n", debugstr_a(str)); return FALSE; } static BOOL CALLBACK MACRO_TestKLink(LPCSTR str) { WINE_FIXME("(%s)\n", debugstr_a(str)); return FALSE; } static void CALLBACK MACRO_UncheckItem(LPCSTR str) { WINE_FIXME("(%s)\n", debugstr_a(str)); } static void CALLBACK MACRO_UpdateWindow(LPCSTR str1, LPCSTR str2) { WINE_FIXME("(%s, %s)\n", debugstr_a(str1), debugstr_a(str2)); } /**************************************************/ /* Macro table */ /**************************************************/ /* types: * U: 32 bit unsigned int * I: 32 bit signed int * S: string * v: unknown (32 bit entity) */ static struct MacroDesc MACRO_Builtins[] = { {"About", NULL, 0, "", MACRO_About}, {"AddAccelerator", "AA", 0, "UUS", MACRO_AddAccelerator}, {"ALink", "AL", 0, "SUS", MACRO_ALink}, {"Annotate", NULL, 0, "", MACRO_Annotate}, {"AppendItem", NULL, 0, "SSSS", MACRO_AppendItem}, {"Back", NULL, 0, "", MACRO_Back}, {"BackFlush", "BF", 0, "", MACRO_BackFlush}, {"BookmarkDefine", NULL, 0, "", MACRO_BookmarkDefine}, {"BookmarkMore", NULL, 0, "", MACRO_BookmarkMore}, {"BrowseButtons", NULL, 0, "", MACRO_BrowseButtons}, {"ChangeButtonBinding", "CBB",0, "SS", MACRO_ChangeButtonBinding}, {"ChangeEnable", "CE", 0, "SS", MACRO_ChangeEnable}, {"ChangeItemBinding", "CIB",0, "SS", MACRO_ChangeItemBinding}, {"CheckItem", "CI", 0, "S", MACRO_CheckItem}, {"CloseSecondarys", "CS", 0, "", MACRO_CloseSecondarys}, {"CloseWindow", "CW", 0, "S", MACRO_CloseWindow}, {"Compare", NULL, 0, "S", MACRO_Compare}, {"Contents", NULL, 0, "", MACRO_Contents}, {"ControlPanel", NULL, 0, "SSU", MACRO_ControlPanel}, {"CopyDialog", NULL, 0, "", MACRO_CopyDialog}, {"CopyTopic", "CT", 0, "", MACRO_CopyTopic}, {"CreateButton", "CB", 0, "SSS", MACRO_CreateButton}, {"DeleteItem", NULL, 0, "S", MACRO_DeleteItem}, {"DeleteMark", NULL, 0, "S", MACRO_DeleteMark}, {"DestroyButton", NULL, 0, "S", MACRO_DestroyButton}, {"DisableButton", "DB", 0, "S", MACRO_DisableButton}, {"DisableItem", "DI", 0, "S", MACRO_DisableItem}, {"EnableButton", "EB", 0, "S", MACRO_EnableButton}, {"EnableItem", "EI", 0, "S", MACRO_EnableItem}, {"EndMPrint", NULL, 0, "", MACRO_EndMPrint}, {"ExecFile", "EF", 0, "SSUS", MACRO_ExecFile}, {"ExecProgram", "EP", 0, "SU", MACRO_ExecProgram}, {"Exit", NULL, 0, "", MACRO_Exit}, {"ExtAbleItem", NULL, 0, "SU", MACRO_ExtAbleItem}, {"ExtInsertItem", NULL, 0, "SSSSUU", MACRO_ExtInsertItem}, {"ExtInsertMenu", NULL, 0, "SSSUU", MACRO_ExtInsertMenu}, {"FileExist", "FE", 1, "S", MACRO_FileExist}, {"FileOpen", "FO", 0, "", MACRO_FileOpen}, {"Find", NULL, 0, "", MACRO_Find}, {"Finder", "FD", 0, "", MACRO_Finder}, {"FloatingMenu", NULL, 0, "", MACRO_FloatingMenu}, {"Flush", "FH", 0, "", MACRO_Flush}, {"FocusWindow", NULL, 0, "S", MACRO_FocusWindow}, {"Generate", NULL, 0, "SUU", MACRO_Generate}, {"GotoMark", NULL, 0, "S", MACRO_GotoMark}, {"HelpOn", NULL, 0, "", MACRO_HelpOn}, {"HelpOnTop", NULL, 0, "", MACRO_HelpOnTop}, {"History", NULL, 0, "", MACRO_History}, {"InitMPrint", NULL, 1, "", MACRO_InitMPrint}, {"InsertItem", NULL, 0, "SSSSU", MACRO_InsertItem}, {"InsertMenu", NULL, 0, "SSU", MACRO_InsertMenu}, {"IfThen", "IF", 0, "BS", MACRO_IfThen}, {"IfThenElse", "IE", 0, "BSS", MACRO_IfThenElse}, {"IsBook", NULL, 1, "", MACRO_IsBook}, {"IsMark", NULL, 1, "S", MACRO_IsMark}, {"IsNotMark", "NM", 1, "S", MACRO_IsNotMark}, {"JumpContents", NULL, 0, "SS", MACRO_JumpContents}, {"JumpContext", "JC", 0, "SSU", MACRO_JumpContext}, {"JumpHash", "JH", 0, "SSU", MACRO_JumpHash}, {"JumpHelpOn", NULL, 0, "", MACRO_JumpHelpOn}, {"JumpID", "JI", 0, "SS", MACRO_JumpID}, {"JumpKeyword", "JK", 0, "SSS", MACRO_JumpKeyword}, {"KLink", "KL", 0, "SUSS", MACRO_KLink}, {"Menu", "MU", 0, "", MACRO_Menu}, {"MPrintHash", NULL, 0, "U", MACRO_MPrintHash}, {"MPrintID", NULL, 0, "S", MACRO_MPrintID}, {"Next", NULL, 0, "", MACRO_Next}, {"NoShow", "NS", 0, "", MACRO_NoShow}, {"PopupContext", "PC", 0, "SU", MACRO_PopupContext}, {"PopupHash", NULL, 0, "SU", MACRO_PopupHash}, {"PopupId", "PI", 0, "SS", MACRO_PopupId}, {"PositionWindow", "PW", 0, "IIUUUS", MACRO_PositionWindow}, {"Prev", NULL, 0, "", MACRO_Prev}, {"Print", NULL, 0, "", MACRO_Print}, {"PrinterSetup", NULL, 0, "", MACRO_PrinterSetup}, {"RegisterRoutine", "RR", 0, "SSS", MACRO_RegisterRoutine}, {"RemoveAccelerator", "RA", 0, "UU", MACRO_RemoveAccelerator}, {"ResetMenu", NULL, 0, "", MACRO_ResetMenu}, {"SaveMark", NULL, 0, "S", MACRO_SaveMark}, {"Search", NULL, 0, "", MACRO_Search}, {"SetContents", NULL, 0, "SU", MACRO_SetContents}, {"SetHelpOnFile", NULL, 0, "S", MACRO_SetHelpOnFile}, {"SetPopupColor", "SPC",0, "UUU", MACRO_SetPopupColor}, {"ShellExecute", "SE", 0, "SSUUSS", MACRO_ShellExecute}, {"ShortCut", "SH", 0, "SSUUS", MACRO_ShortCut}, {"TCard", NULL, 0, "U", MACRO_TCard}, {"Test", NULL, 0, "U", MACRO_Test}, {"TestALink", NULL, 1, "S", MACRO_TestALink}, {"TestKLink", NULL, 1, "S", MACRO_TestKLink}, {"UncheckItem", "UI", 0, "S", MACRO_UncheckItem}, {"UpdateWindow", "UW", 0, "SS", MACRO_UpdateWindow}, {NULL, NULL, 0, NULL, NULL} }; static int MACRO_DoLookUp(struct MacroDesc* start, const char* name, struct lexret* lr, unsigned len) { struct MacroDesc* md; for (md = start; md->name && len != 0; md++, len--) { if (strcasecmp(md->name, name) == 0 || (md->alias != NULL && strcasecmp(md->alias, name) == 0)) { lr->proto = md->arguments; lr->function = md->fn; return md->isBool ? BOOL_FUNCTION : VOID_FUNCTION; } } return EMPTY; } int MACRO_Lookup(const char* name, struct lexret* lr) { int ret; if ((ret = MACRO_DoLookUp(MACRO_Builtins, name, lr, -1)) != EMPTY) return ret; if (MACRO_Loaded && (ret = MACRO_DoLookUp(MACRO_Loaded, name, lr, MACRO_NumLoaded)) != EMPTY) return ret; if (!strcmp(name, "hwndApp")) { WINHELP_WINDOW* win; lr->integer = 0; for (win = Globals.win_list; win; win = win->next) { if (!strcmp(win->info->name, "main")) { lr->integer = (LONG_PTR)win->hMainWnd; break; } } return INTEGER; } if (!strcmp(name, "hwndContext")) { lr->integer = Globals.active_win ? (LONG_PTR)Globals.active_win->hMainWnd : 0; return INTEGER; } if (!strcmp(name, "qchPath") || !strcmp(name, "qError") || !strcmp(name, "lTopicNo") || !strcmp(name, "hfs") || !strcmp(name, "coForeground") || !strcmp(name, "coBackground")) { WINE_FIXME("keyword %s not substituted in macro parsing\n", debugstr_a(name)); return EMPTY; } lr->string = name; return IDENTIFIER; }