Release 960506
Mon May 6 12:56:26 1996 Alexandre Julliard <julliard@lrc.epfl.ch>
* [DEVELOPERS-HINTS]
Added paragraph on naming conventions for Win16/Win32/Winelib.
* [controls/menu.c]
Create a default system menu that is the same for all windows
instead of making a copy every time.
* [include/wintypes.h]
Added WINELIB_NAME and DECL_WINELIB_TYPE macros.
Added xx16 and xx32 definitions for most types. General clean-up.
* [memory/global.c] [memory/local.c] [*/*]
Renamed Global and Local heap functions to xxx16. Added all xxx32
versions of the same functions.
* [memory/selector.c]
Mask out lower bits of selector in FreeSelector().
* [misc/lstr.c]
Fixed wvsprintf().
* [windows/class.c]
Changed the class structure to make Win32 support easier.
* [windows/defwnd.c]
Added handling of WM_INITMENUPOPUP for system menu to gray out
invalid options.
* [windows/winpos.c]
Bug fix: the WINDOSPOS structure pointer in WM_NCCALCSIZE must be
a SEGPTR.
Sun May 5 03:51:26 1996 Huw D. M. Davies <h.davies1@physics.oxford.ac.uk>
* [memory/local.c]
Implementation of moveable and (rudimentary) support for
discardable local memory, plus several bug fixes.
Sat May 4 18:33:35 1996 Marcus Meissner <msmeissn@cip.informatik.uni-erlangen.de>
* [include/windows.h] [windows/win.c] [if1632/user.spec]
FindWindowEx() implemented (someone reported it was missing
for FrameMaker 4.1).
* [if1632/kernel32.spec] [if1632/user32.spec] [win32/memory.c]
[win32/resource.c]
Misc small stubs/small functions which bring win95 binaries
further down the road. (IsBadCodePtr, LocalReAlloc,GetCursorPos)
Small fix in WIN32_LoadAcceleratorsA.
Fri May 3 19:43:12 1996 Frans van Dorsselaer <dorssel@rulhm1.LeidenUniv.nl>
* [controls/edit.c] [controls/EDIT.TODO]
Changed / fixed some types and typecasts.
Fixed the scrollbar reset after WM_SETHANDLE / WM_SETTEXT.
Added heap initialization in WM_CREATE.
Fri May 3 19:30:02 1996 Greg Kreider <kreider@natlab.research.philips.com>
* [controls/combo.c] [controls/listbox.c]
Pass WM_[HV]SCROLL to listbox, but not combo.
Don't try to redraw non-existant scroll bars (changes dwStyle flags).
Combo box gets border.
Combo box includes button (otherwise button won't trigger dropdown).
Proper border around RectButton.
Check size consistancy of combo, listbox, and button after resizing
or before painting. These routines still aren't completely correct.
Localize size checks in separate routines.
Listboxes are white.
Thu May 2 19:21:23 1996 Albrecht Kleine <kleine@ak.sax.de>
* [controls/combo.c][include/commdlg.h][include/commdlg.c]
[resources/sysres_De.rc][resources/sysres_En.rc]
Introduced ChooseFont dialog, but needed some patches in
handling of comboboxes with edit controls.
Tue Apr 30 00:33:27 1996 Ulrich Schmid <uschmid@mail.hh.provi.de>
* [programs/winhelp/*]
Added a help viewer and a simple `.hlp' to `.sgml' converter.
Mon Apr 29 14:17:57 1996 Tristan Tarrant <tst@sthinc.demon.co.uk>
* [resources/sysres_*.rc] [misc/shell.c]
Modified size of "About" dialog boxes.
Sat Apr 27 18:10:11 Martin von Loewis <loewis@informatik.hu-berlin.de>
* [if1632/Makefile.in][loader/builtin.c]
crtdll.spec, ntdll.spec, wsock32.spec: new files.
* [loader/pe_image.c]
Fix error message if import by ordinal failed.
diff --git a/programs/Makefile.in b/programs/Makefile.in
index a954a5f..c42928d 100644
--- a/programs/Makefile.in
+++ b/programs/Makefile.in
@@ -1,4 +1,4 @@
-SUBDIRS = progman
+SUBDIRS = progman winhelp
all: $(SUBDIRS)
@@ -8,6 +8,9 @@
depend:
for i in $(SUBDIRS); do (cd $$i; $(MAKE) depend); done
+install:
+ for i in $(SUBDIRS); do (cd $$i; $(MAKE) install); done
+
clean:
for i in $(SUBDIRS); do (cd $$i; $(MAKE) clean); done
diff --git a/programs/progman/Makefile.in b/programs/progman/Makefile.in
index 37af394..8db65d2 100644
--- a/programs/progman/Makefile.in
+++ b/programs/progman/Makefile.in
@@ -6,6 +6,19 @@
LANGUAGES = En De Fr
LICENSELANG = En
+# Installation infos
+
+INSTALL = @INSTALL@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_DATA = @INSTALL_DATA@
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+bindir = @bindir@
+libdir = @libdir@
+sysconfdir = @sysconfdir@
+mandir = @mandir@/man1
+manext = .1
+
MOSTOBJS = \
dialog.o \
group.o \
@@ -30,10 +43,15 @@
progman: $(MOSTOBJS) $(STRINGOBJS) $(WINELIB)
$(CC) -o progman $(MOSTOBJS) $(LDOPTIONS) $(ALL_LIBS) $(STRINGOBJS)
+install: dummy
+ $(INSTALL_PROGRAM) progman $(bindir)/progman
+
clean::
$(RM) accel.c accel.h $(LANGUAGES:%=%.c) $(LANGUAGES:%=%.h) progman
accel.c accel.h: $(WINERC) Xx.rc
$(LANGUAGES:%=%.c) $(LANGUAGES:%=%.h): $(WINERC) Xx.rc
+dummy:
+
### Dependencies:
diff --git a/programs/winhelp/ChangeLog b/programs/winhelp/ChangeLog
new file mode 100644
index 0000000..9ba2f94
--- /dev/null
+++ b/programs/winhelp/ChangeLog
@@ -0,0 +1,7 @@
+Mon Apr 29 19:48:15 1996 Ulrich Schmid <uschmid@mail.hh.provi.de>
+
+ * [winhelp.c] [winhelp.h] [hlpfile.c] [hlpfile.h]
+ [macro.c] [macro.h] [macro.lex.l] [macro.yacc.y]
+ [string.c] [En.rc] [De.rc] [Xx.rc] [hlp2sgml.c]
+ Original by Ulrich Schmid
+
diff --git a/programs/winhelp/De.rc b/programs/winhelp/De.rc
new file mode 100644
index 0000000..38a0c17
--- /dev/null
+++ b/programs/winhelp/De.rc
@@ -0,0 +1,48 @@
+/*
+ * Help Viewer
+ *
+ * Copyright 1996 Ulrich Schmid
+ */
+
+/* This file is not yet complete !! */
+
+#define LANGUAGE_ID De
+#define LANGUAGE_NUMBER 2
+
+/* Menu */
+
+#define MENU_FILE "&Datei"
+#define MENU_FILE_OPEN "Ö&ffnen..."
+#define MENU_FILE_PRINT "Thema &drucken"
+#define MENU_FILE_PRINTER_SETUP "Drucker&einrichtung..."
+#define MENU_FILE_EXIT "&Beenden"
+
+#define MENU_EDIT "&Bearbeiten"
+#define MENU_EDIT_COPY_DIALOG "&Kopieren..."
+#define MENU_EDIT_ANNOTATE "&Anmerken..."
+
+#define MENU_BOOKMARK "&Lesezeichen"
+#define MENU_BOOKMARK_DEFINE "&Definieren..."
+
+#define MENU_HELP "&Hilfe"
+#define MENU_HELP_ON_HELP "&Hilfe benutzen"
+#define MENU_HELP_ON_TOP "Immer im &Vordergrund"
+#define MENU_HELP_INFO "Inf&o..."
+#define MENU_HELP_ABOUT_WINE "&Über WINE"
+
+/* Strings */
+
+#define STRING_WINE_HELP "WINE Hilfe"
+#define STRING_ERROR "FEHLER"
+#define STRING_WARNING "ACHTUNG"
+#define STRING_INFO "Information"
+#define STRING_NOT_IMPLEMENTED "Nicht implementiert"
+#define STRING_HLPFILE_ERROR_s "Fehler beim Lesen der Hilfe-Datei `%s'"
+#define STRING_CONTENTS "&Inhalt"
+#define STRING_SEARCH "&Suchen"
+#define STRING_BACK "&Zurück"
+#define STRING_HISTORY "&Bisher"
+#define STRING_ALL_FILES "Alle Dateien (*.*)"
+#define STRING_HELP_FILES_HLP "Hilfe-Dateien (*.hlp)"
+
+#include "Xx.rc"
diff --git a/programs/winhelp/En.rc b/programs/winhelp/En.rc
new file mode 100644
index 0000000..b14389b
--- /dev/null
+++ b/programs/winhelp/En.rc
@@ -0,0 +1,48 @@
+/*
+ * Help Viewer
+ *
+ * Copyright 1996 Ulrich Schmid
+ */
+
+/* This file is not yet complete !! */
+
+#define LANGUAGE_ID En
+#define LANGUAGE_NUMBER 0
+
+/* Menu */
+
+#define MENU_FILE "&File"
+#define MENU_FILE_OPEN "&Open..."
+#define MENU_FILE_PRINT "&Print"
+#define MENU_FILE_PRINTER_SETUP "Printer &setup..."
+#define MENU_FILE_EXIT "&Exit"
+
+#define MENU_EDIT "&Edit"
+#define MENU_EDIT_COPY_DIALOG "&Copy..."
+#define MENU_EDIT_ANNOTATE "&Annotate..."
+
+#define MENU_BOOKMARK "&Bookmark"
+#define MENU_BOOKMARK_DEFINE "&Define..."
+
+#define MENU_HELP "&Help"
+#define MENU_HELP_ON_HELP "Help &on help"
+#define MENU_HELP_ON_TOP "Always on &top"
+#define MENU_HELP_INFO "&Info..."
+#define MENU_HELP_ABOUT_WINE "&About WINE"
+
+/* Strings */
+
+#define STRING_WINE_HELP "WINE Help"
+#define STRING_ERROR "ERROR"
+#define STRING_WARNING "WARNING"
+#define STRING_INFO "Information"
+#define STRING_NOT_IMPLEMENTED "Not implemented"
+#define STRING_HLPFILE_ERROR_s "Error while reading the help file `%s'"
+#define STRING_CONTENTS "&Contents"
+#define STRING_SEARCH "&Search"
+#define STRING_BACK "&Back"
+#define STRING_HISTORY "&History"
+#define STRING_ALL_FILES "All files (*.*)"
+#define STRING_HELP_FILES_HLP "Help files (*.hlp)"
+
+#include "Xx.rc"
diff --git a/programs/winhelp/Makefile.in b/programs/winhelp/Makefile.in
new file mode 100644
index 0000000..96a5fcb
--- /dev/null
+++ b/programs/winhelp/Makefile.in
@@ -0,0 +1,63 @@
+TOPSRC = @top_srcdir@
+MODULE = none
+PROGRAMS = winhelp hlp2sgml
+ALL_LIBS = $(WINELIB) $(X_LIBS) $(XPM_LIB) $(XLIB) $(LDLIBS)
+
+LANGUAGES = En De
+
+# Installation infos
+
+INSTALL = @INSTALL@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_DATA = @INSTALL_DATA@
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+bindir = @bindir@
+libdir = @libdir@
+sysconfdir = @sysconfdir@
+mandir = @mandir@/man1
+manext = .1
+
+MOSTOBJS = \
+ winhelp.o \
+ hlpfile.o \
+ macro.o \
+ y.tab.o \
+ lex.yy.o
+
+STRINGOBJS = \
+ string.o \
+ $(LANGUAGES:%=%.o)
+
+C_SRCS = $(MOSTOBJS:.o=.c) $(STRINGOBJS:.o=.c) hlp2sgml.c
+
+all: check_winerc $(PROGRAMS)
+
+@MAKE_RULES@
+
+# Some strings need addresses >= 0x10000
+winhelp: $(MOSTOBJS) $(STRINGOBJS) $(WINELIB)
+ $(CC) -o winhelp $(MOSTOBJS) $(LDOPTIONS) $(ALL_LIBS) $(STRINGOBJS)
+
+hlp2sgml: hlp2sgml.o hlpfile.o
+ $(CC) -o hlp2sgml hlp2sgml.o hlpfile.o
+
+install: dummy
+ $(INSTALL_PROGRAM) winhelp $(bindir)/winhelp
+ $(INSTALL_PROGRAM) hlp2sgml $(bindir)/hlp2sgml
+
+clean::
+ $(RM) $(PROGRAMS) lex.yy.c y.tab.c y.tab.h
+ $(RM) $(LANGUAGES:%=%.c) $(LANGUAGES:%=%.h)
+
+y.tab.c y.tab.h: macro.yacc.y
+ $(YACC) -d -t macro.yacc.y
+
+lex.yy.c: macro.lex.l
+ $(LEX) -8 -I macro.lex.l
+
+$(LANGUAGES:%=%.c) $(LANGUAGES:%=%.h): $(WINERC) Xx.rc
+
+dummy:
+
+### Dependencies:
diff --git a/programs/winhelp/Xx.rc b/programs/winhelp/Xx.rc
new file mode 100644
index 0000000..d2e713b
--- /dev/null
+++ b/programs/winhelp/Xx.rc
@@ -0,0 +1,80 @@
+/*
+ * Help Viewer
+ *
+ * Copyright 1996 Ulrich Schmid
+ */
+
+#include "winhelp.h"
+
+#define CONCAT(a, b) CONCAT1(a, b)
+#define CONCAT1(a, b) a##b
+
+/* Menu */
+
+CONCAT(MENU_, LANGUAGE_ID) MENU
+{
+ POPUP MENU_FILE {
+ MENUITEM MENU_FILE_OPEN, WH_OPEN
+ MENUITEM SEPARATOR
+ MENUITEM MENU_FILE_PRINT, WH_PRINT
+ MENUITEM MENU_FILE_PRINTER_SETUP, WH_PRINTER_SETUP
+ MENUITEM SEPARATOR
+ MENUITEM MENU_FILE_EXIT, WH_EXIT
+ }
+ POPUP MENU_EDIT {
+ MENUITEM MENU_EDIT_COPY_DIALOG, WH_COPY_DIALOG
+ MENUITEM SEPARATOR
+ MENUITEM MENU_EDIT_ANNOTATE, WH_ANNOTATE
+ }
+ POPUP MENU_BOOKMARK {
+ MENUITEM MENU_BOOKMARK_DEFINE, WH_BOOKMARK_DEFINE
+ }
+ POPUP MENU_HELP {
+ MENUITEM MENU_HELP_ON_HELP, WH_HELP_ON_HELP
+ MENUITEM MENU_HELP_ON_TOP, WH_HELP_ON_TOP
+ MENUITEM SEPARATOR
+ MENUITEM MENU_HELP_INFO, WH_ABOUT
+#ifdef WINELIB
+ MENUITEM MENU_HELP_ABOUT_WINE, WH_ABOUT_WINE
+#endif
+ }
+}
+
+/* Dialogs */
+
+DIALOG_TEST DIALOG 0, 0, 150, 22
+STYLE DS_MODALFRAME
+CAPTION "Macro Test"
+{
+GROUPBOX "", IDIGNORE, 4, 4, 102, 12
+EDITTEXT 99, 5, 7, 100, 8
+DEFPUSHBUTTON "OK", IDOK, 110, 5, 35, 12
+}
+
+/* Strings */
+
+#define ADDSTRING(str) ADDSTRING1(LANGUAGE_NUMBER, IDS_ ## str) STRING_ ## str
+#define ADDSTRING1(langnum, ids) ADDSTRING2(langnum, ids)
+#define ADDSTRING2(langnum, ids) 0x ## langnum ## ids
+
+#define STRINGIFY(str) STRINGIFY1(str)
+#define STRINGIFY1(str) #str
+
+#define STRING_LANGUAGE_ID STRINGIFY(LANGUAGE_ID)
+
+STRINGTABLE
+{
+ADDSTRING(LANGUAGE_ID)
+ADDSTRING(WINE_HELP)
+ADDSTRING(ERROR)
+ADDSTRING(WARNING)
+ADDSTRING(INFO)
+ADDSTRING(NOT_IMPLEMENTED)
+ADDSTRING(HLPFILE_ERROR_s)
+ADDSTRING(CONTENTS)
+ADDSTRING(SEARCH)
+ADDSTRING(BACK)
+ADDSTRING(HISTORY)
+ADDSTRING(ALL_FILES)
+ADDSTRING(HELP_FILES_HLP)
+}
diff --git a/programs/winhelp/hlp2sgml.c b/programs/winhelp/hlp2sgml.c
new file mode 100644
index 0000000..7df0184
--- /dev/null
+++ b/programs/winhelp/hlp2sgml.c
@@ -0,0 +1,333 @@
+/*
+ * Copyright 1996 Ulrich Schmid
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <ctype.h>
+#include <fcntl.h>
+#include "windows.h"
+#include "hlpfile.h"
+
+typedef struct
+{
+ const char *header1;
+ const char *header2;
+ const char *section;
+ const char *first_paragraph;
+ const char *newline;
+ const char *next_paragraph;
+ const char *special_char;
+ const char *begin_italic;
+ const char *end_italic;
+ const char *begin_boldface;
+ const char *end_boldface;
+ const char *begin_typewriter;
+ const char *end_typewriter;
+ const char *tail;
+} FORMAT;
+
+typedef struct
+{
+ const char ch;
+ const char *subst;
+} CHARMAP[];
+
+
+FORMAT format =
+{
+ "<!doctype linuxdoc system>\n"
+ "<article>\n"
+ "<title>\n",
+
+ "\n<author>\n%s\n"
+ "<date>\n%s\n",
+
+ "\n<sect>\n",
+ "\n<p>\n",
+ "\n<newline>\n",
+ "\n\n",
+
+ "&%s;",
+
+ "<em>",
+ "</em>",
+ "<bf>",
+ "</bf>",
+ "<tt>",
+ "</tt>",
+
+ "\n</article>\n"
+};
+
+CHARMAP charmap =
+ {{'Æ', "AElig"},
+ {'Á', "Aacute"},
+ {'Â', "Acirc"},
+ {'À', "Agrave"},
+ {'Ã', "Atilde"},
+ {'Ç', "Ccedil"},
+ {'É', "Eacute"},
+ {'È', "Egrave"},
+ {'Ë', "Euml"},
+ {'Í', "Iacute"},
+ {'Î', "Icirc"},
+ {'Ì', "Igrave"},
+ {'Ï', "Iuml"},
+ {'Ñ', "Ntilde"},
+ {'Ó', "Oacute"},
+ {'Ô', "Ocirc"},
+ {'Ò', "Ograve"},
+ {'Ø', "Oslash"},
+ {'Ú', "Uacute"},
+ {'Ù', "Ugrave"},
+ {'Ý', "Yacute"},
+ {'á', "aacute"},
+ {'â', "acirc"},
+ {'æ', "aelig"},
+ {'à', "agrave"},
+ {'å', "aring"},
+ {'ã', "atilde"},
+ {'ç', "ccedil"},
+ {'é', "eacute"},
+ {'ê', "ecirc"},
+ {'è', "egrave"},
+ {'ë', "euml"},
+ {'í', "iacute"},
+ {'î', "icirc"},
+ {'ì', "igrave"},
+ {'ï', "iuml"},
+ {'ñ', "ntilde"},
+ {'ó', "oacute"},
+ {'ÿ', "yuml"},
+ {'ô', "ocirc"},
+ {'ò', "ograve"},
+ {'ø', "oslash"},
+ {'õ', "otilde"},
+ {'ú', "uacute"},
+ {'û', "ucirc"},
+ {'ù', "ugrave"},
+ {'ý', "yacute"},
+ {'<', "lt"},
+ {'&', "amp"},
+ {'"', "dquot"},
+ {'#', "num"},
+ {'%', "percnt"},
+ {'\'', "quot"},
+#if 0
+ {'(', "lpar"},
+ {')', "rpar"},
+ {'*', "ast"},
+ {'+', "plus"},
+ {',', "comma"},
+ {'-', "hyphen"},
+ {':', "colon"},
+ {';', "semi"},
+ {'=', "equals"},
+ {'@', "commat"},
+ {'[', "lsqb"},
+ {']', "rsqb"},
+ {'^', "circ"},
+ {'_', "lowbar"},
+ {'{', "lcub"},
+ {'|', "verbar"},
+ {'}', "rcub"},
+ {'~', "tilde"},
+#endif
+ {'\\', "bsol"},
+ {'$', "dollar"},
+ {'Ä', "Auml"},
+ {'ä', "auml"},
+ {'Ö', "Ouml"},
+ {'ö', "ouml"},
+ {'Ü', "Uuml"},
+ {'ü', "uuml"},
+ {'ß', "szlig"},
+ {'>', "gt"},
+ {'§', "sect"},
+ {'¶', "para"},
+ {'©', "copy"},
+ {'¡', "iexcl"},
+ {'¿', "iquest"},
+ {'¢', "cent"},
+ {'£', "pound"},
+ {'×', "times"},
+ {'±', "plusmn"},
+ {'÷', "divide"},
+ {'¬', "not"},
+ {'µ', "mu"},
+ {0,0}};
+
+/***********************************************************************
+ *
+ * print_text
+ */
+
+static void print_text(const char *p)
+{
+ int i;
+
+ for (; *p; p++)
+ {
+ for (i = 0; charmap[i].ch; i++)
+ if (*p == charmap[i].ch)
+ {
+ printf(format.special_char, charmap[i].subst);
+ break;
+ }
+ if (!charmap[i].ch)
+ printf("%c", *p);
+ }
+}
+
+/***********************************************************************
+ *
+ * main
+ */
+
+int main(int argc, char **argv)
+{
+ HLPFILE *hlpfile;
+ HLPFILE_PAGE *page;
+ HLPFILE_PARAGRAPH *paragraph;
+ time_t t;
+ char date[50];
+ char *filename;
+
+ hlpfile = HLPFILE_ReadHlpFile(argc > 1 ? argv[1] : "");
+
+ if (!hlpfile) return(2);
+
+ time(&t);
+ strftime(date, sizeof(date), "%x", localtime(&t));
+ filename = strrchr(hlpfile->lpszPath, '/');
+ if (filename) filename++;
+ else filename = hlpfile->lpszPath;
+
+ /* Header */
+ printf(format.header1);
+ print_text(hlpfile->lpszTitle);
+ printf(format.header2, filename, date);
+
+ for (page = hlpfile->first_page; page; page = page->next)
+ {
+ paragraph = page->first_paragraph;
+ if (!paragraph) continue;
+
+ /* Section */
+ printf(format.section);
+ for (; paragraph && !paragraph->wVSpace; paragraph = paragraph->next)
+ print_text(paragraph->lpszText);
+ printf(format.first_paragraph);
+
+ for (; paragraph; paragraph = paragraph->next)
+ {
+ /* New line; new paragraph */
+ if (paragraph->wVSpace == 1)
+ printf(format.newline);
+ else if (paragraph->wVSpace > 1)
+ printf(format.next_paragraph);
+
+ if (paragraph->wFont)
+ printf(format.begin_boldface);
+
+ print_text(paragraph->lpszText);
+
+ if (paragraph->wFont)
+ printf(format.end_boldface);
+ }
+ }
+
+ printf(format.tail);
+
+ return(0);
+}
+
+/***********************************************************************
+ *
+ * Substitutions for some WINELIB functions
+ */
+
+HFILE OpenFile( LPCSTR path, OFSTRUCT *ofs, UINT mode )
+{
+ FILE *file;
+
+ if (!*path) return (HFILE) stdin;
+
+ file = fopen(path, "r");
+ if (!file) return HFILE_ERROR;
+ return (HFILE) file;
+}
+
+HFILE _lclose( HFILE hFile )
+{
+ fclose((FILE*) hFile);
+ return 0;
+}
+
+LONG _hread( HFILE hFile, SEGPTR buffer, LONG count )
+{
+ return fread(buffer, 1, count, (FILE*) hFile);
+}
+
+HGLOBAL GlobalAlloc( WORD flags, DWORD size )
+{
+ return (HGLOBAL) malloc(size);
+}
+
+LPVOID GlobalLock( HGLOBAL handle )
+{
+ return (LPVOID) handle;
+}
+
+HGLOBAL GlobalFree( HGLOBAL handle )
+{
+ free((VOID*) handle);
+ return(0);
+}
+
+/*
+ * String functions
+ *
+ * Copyright 1993 Yngvi Sigurjonsson (yngvi@hafro.is)
+ */
+
+INT lstrcmp(LPCSTR str1,LPCSTR str2)
+{
+ return strcmp( str1, str2 );
+}
+
+INT lstrcmpi( LPCSTR str1, LPCSTR str2 )
+{
+ INT res;
+
+ while (*str1)
+ {
+ if ((res = toupper(*str1) - toupper(*str2)) != 0) return res;
+ str1++;
+ str2++;
+ }
+ return toupper(*str1) - toupper(*str2);
+}
+
+INT lstrlen(LPCSTR str)
+{
+ return strlen(str);
+}
+
+SEGPTR lstrcpy( SEGPTR target, SEGPTR source )
+{
+ strcpy( (char *)target, (char *)source );
+ return target;
+}
+
+void hmemcpy(LPVOID hpvDest, LPCVOID hpvSource, LONG cbCopy)
+{
+ memcpy(hpvDest, hpvSource, cbCopy);
+}
+
+/* Local Variables: */
+/* c-file-style: "GNU" */
+/* End: */
diff --git a/programs/winhelp/hlpfile.c b/programs/winhelp/hlpfile.c
new file mode 100644
index 0000000..80232d9
--- /dev/null
+++ b/programs/winhelp/hlpfile.c
@@ -0,0 +1,989 @@
+/*
+ * Help Viewer
+ *
+ * Copyright 1996 Ulrich Schmid
+ */
+
+#include <stdio.h>
+#include <windows.h>
+#include "winhelp.h"
+
+static void Report(LPCSTR str)
+{
+#if 0
+ fprintf(stderr, "%s\n", str);
+#endif
+}
+
+#define GET_USHORT(buffer, i)\
+(((BYTE)((buffer)[(i)]) + 0x100 * (BYTE)((buffer)[(i)+1])))
+#define GET_SHORT(buffer, i)\
+(((BYTE)((buffer)[(i)]) + 0x100 * (signed char)((buffer)[(i)+1])))
+#define GET_UINT(buffer, i)\
+GET_USHORT(buffer, i) + 0x10000 * GET_USHORT(buffer, i+2)
+
+static BOOL HLPFILE_DoReadHlpFile(HLPFILE*, LPCSTR);
+static BOOL HLPFILE_ReadFileToBuffer(HFILE);
+static BOOL HLPFILE_FindSubFile(LPCSTR name, BYTE**, BYTE**);
+static VOID HLPFILE_SystemCommands(HLPFILE*);
+static BOOL HLPFILE_Uncompress1_Phrases();
+static BOOL HLPFILE_Uncompress1_Topic();
+static BOOL HLPFILE_GetContext(HLPFILE*);
+static BOOL HLPFILE_AddPage(HLPFILE*, BYTE*, BYTE*);
+static BOOL HLPFILE_AddParagraph(HLPFILE*, BYTE *, BYTE*);
+static UINT HLPFILE_Uncompressed2_Size(BYTE*, BYTE*);
+static VOID HLPFILE_Uncompress2(BYTE**, BYTE*, BYTE*);
+
+static HLPFILE *first_hlpfile = 0;
+static HGLOBAL hFileBuffer;
+static BYTE *file_buffer;
+
+static struct
+{
+ UINT num;
+ BYTE *buf;
+ HGLOBAL hBuffer;
+} phrases;
+
+static struct
+{
+ BYTE **map;
+ BYTE *end;
+ UINT wMapLen;
+ HGLOBAL hMap;
+ HGLOBAL hBuffer;
+} topic;
+
+static struct
+{
+ UINT bDebug;
+ UINT wFont;
+ UINT wIndent;
+ UINT wHSpace;
+ UINT wVSpace;
+ UINT wVBackSpace;
+ HLPFILE_LINK link;
+} attributes;
+
+/***********************************************************************
+ *
+ * HLPFILE_Contents
+ */
+
+HLPFILE_PAGE *HLPFILE_Contents(LPCSTR lpszPath)
+{
+ HLPFILE *hlpfile = HLPFILE_ReadHlpFile(lpszPath);
+
+ if (!hlpfile) return(0);
+
+ return(hlpfile->first_page);
+}
+
+/***********************************************************************
+ *
+ * HLPFILE_PageByNumber
+ */
+
+HLPFILE_PAGE *HLPFILE_PageByNumber(LPCSTR lpszPath, UINT wNum)
+{
+ HLPFILE_PAGE *page;
+ HLPFILE *hlpfile = HLPFILE_ReadHlpFile(lpszPath);
+
+ if (!hlpfile) return(0);
+
+ for (page = hlpfile->first_page; page && wNum; page = page->next) wNum--;
+
+ return page;
+}
+
+/***********************************************************************
+ *
+ * HLPFILE_HlpFilePageByHash
+ */
+
+HLPFILE_PAGE *HLPFILE_PageByHash(LPCSTR lpszPath, LONG lHash)
+{
+ INT i;
+ UINT wNum;
+ HLPFILE_PAGE *page;
+ HLPFILE *hlpfile = HLPFILE_ReadHlpFile(lpszPath);
+
+ if (!hlpfile) return(0);
+
+ for (i = 0; i < hlpfile->wContextLen; i++)
+ if (hlpfile->Context[i].lHash == lHash) break;
+
+ if (i >= hlpfile->wContextLen)
+ {
+ HLPFILE_FreeHlpFile(hlpfile);
+ return(0);
+ }
+
+ wNum = hlpfile->Context[i].wPage;
+ for (page = hlpfile->first_page; page && wNum; page = page->next) wNum--;
+
+ 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)
+{
+ HGLOBAL hHlpFile;
+ HLPFILE *hlpfile;
+
+ for (hlpfile = first_hlpfile; hlpfile; hlpfile = hlpfile->next)
+ if (!lstrcmp(hlpfile->lpszPath, lpszPath))
+ {
+ hlpfile->wRefCount++;
+ return(hlpfile);
+ }
+
+ hHlpFile = GlobalAlloc(GMEM_FIXED, sizeof(HLPFILE) + lstrlen(lpszPath) + 1);
+ if (!hHlpFile) return(0);
+
+ hlpfile = GlobalLock(hHlpFile);
+ hlpfile->hSelf = hHlpFile;
+ hlpfile->wRefCount = 1;
+ hlpfile->hTitle = 0;
+ hlpfile->hContext = 0;
+ hlpfile->wContextLen = 0;
+ hlpfile->first_page = 0;
+ hlpfile->first_macro = 0;
+ hlpfile->prev = 0;
+ hlpfile->next = first_hlpfile;
+ first_hlpfile = hlpfile;
+ if (hlpfile->next) hlpfile->next->prev = hlpfile;
+
+ hlpfile->lpszPath = GlobalLock(hHlpFile);
+ hlpfile->lpszPath += sizeof(HLPFILE);
+ lstrcpy(hlpfile->lpszPath, (SEGPTR) lpszPath);
+
+ phrases.hBuffer = topic.hBuffer = hFileBuffer = 0;
+
+ if (!HLPFILE_DoReadHlpFile(hlpfile, lpszPath))
+ {
+ HLPFILE_FreeHlpFile(hlpfile);
+ hlpfile = 0;
+ }
+
+ if (phrases.hBuffer) GlobalFree(phrases.hBuffer);
+ if (topic.hBuffer) GlobalFree(topic.hBuffer);
+ if (topic.hMap) GlobalFree(topic.hMap);
+ if (hFileBuffer) GlobalFree(hFileBuffer);
+
+ return(hlpfile);
+}
+
+/***********************************************************************
+ *
+ * HLPFILE_DoReadHlpFile
+ */
+
+static BOOL HLPFILE_DoReadHlpFile(HLPFILE *hlpfile, LPCSTR lpszPath)
+{
+ BOOL ret;
+ HFILE hFile;
+ OFSTRUCT ofs;
+ BYTE *buf;
+
+ hFile=OpenFile(lpszPath, &ofs, OF_READ | OF_SEARCH);
+ if (hFile == HFILE_ERROR) return FALSE;
+
+ ret = HLPFILE_ReadFileToBuffer(hFile);
+ _lclose(hFile);
+ if (!ret) return FALSE;
+
+ HLPFILE_SystemCommands(hlpfile);
+ if (!HLPFILE_Uncompress1_Phrases()) return FALSE;
+ if (!HLPFILE_Uncompress1_Topic()) return FALSE;
+
+ buf = topic.map[0] + 0xc;
+ while(buf + 0xc < topic.end)
+ {
+ BYTE *end = MIN(buf + GET_UINT(buf, 0), topic.end);
+ UINT next, index, offset;
+
+ switch (buf[0x14])
+ {
+ case 0x02:
+ if (!HLPFILE_AddPage(hlpfile, buf, end)) return(FALSE);
+ break;
+
+ case 0x20:
+ if (!HLPFILE_AddParagraph(hlpfile, buf, end)) return(FALSE);
+ break;
+
+ case 0x23:
+ if (!HLPFILE_AddParagraph(hlpfile, buf, end)) return(FALSE);
+ break;
+
+ default:
+ fprintf(stderr, "buf[0x14] = %x\n", buf[0x14]);
+ }
+
+ next = GET_UINT(buf, 0xc);
+ if (next == 0xffffffff) break;
+
+ index = next >> 14;
+ offset = next & 0x3fff;
+ if (index > topic.wMapLen) {Report("maplen"); break;}
+ buf = topic.map[index] + offset;
+ }
+
+ return(HLPFILE_GetContext(hlpfile));
+}
+
+/***********************************************************************
+ *
+ * HLPFILE_AddPage
+ */
+
+static BOOL HLPFILE_AddPage(HLPFILE *hlpfile, BYTE *buf, BYTE *end)
+{
+ HGLOBAL hPage;
+ HLPFILE_PAGE *page, **pageptr;
+ BYTE *title;
+ UINT titlesize;
+
+ for (pageptr = &hlpfile->first_page; *pageptr; pageptr = &(*pageptr)->next)
+ /* Nothing */;
+
+ if (buf + 0x31 > end) {Report("page1"); return(FALSE);};
+ title = buf + GET_UINT(buf, 0x10);
+ if (title > end) {Report("page2"); return(FALSE);};
+
+ titlesize = HLPFILE_Uncompressed2_Size(title, end);
+ hPage = GlobalAlloc(GMEM_FIXED, sizeof(HLPFILE_PAGE) + titlesize);
+ if (!hPage) return FALSE;
+ page = *pageptr = GlobalLock(hPage);
+ pageptr = &page->next;
+ page->hSelf = hPage;
+ page->file = hlpfile;
+ page->next = 0;
+ page->first_paragraph = 0;
+
+ page->lpszTitle = GlobalLock(hPage);
+ page->lpszTitle += sizeof(HLPFILE_PAGE);
+ HLPFILE_Uncompress2(&title, end, page->lpszTitle);
+
+ page->wNumber = GET_UINT(buf, 0x21);
+
+ attributes.bDebug = 0;
+ attributes.wFont = 0;
+ attributes.wVSpace = 0;
+ attributes.wVBackSpace = 0;
+ attributes.wHSpace = 0;
+ attributes.wIndent = 0;
+ attributes.link.lpszPath = 0;
+
+ return TRUE;
+}
+
+/***********************************************************************
+ *
+ * HLPFILE_AddParagraph
+ */
+
+static BOOL HLPFILE_AddParagraph(HLPFILE *hlpfile, BYTE *buf, BYTE *end)
+{
+ HGLOBAL hParagraph;
+ HLPFILE_PAGE *page;
+ HLPFILE_PARAGRAPH *paragraph, **paragraphptr;
+ UINT textsize;
+ BYTE *format, *text;
+ BOOL format_header = TRUE;
+ BOOL format_end = FALSE;
+ UINT mask, i;
+
+ if (!hlpfile->first_page) {Report("paragraph1"); return(FALSE);};
+
+ for (page = hlpfile->first_page; page->next; page = page->next) /* Nothing */;
+ for (paragraphptr = &page->first_paragraph; *paragraphptr;
+ paragraphptr = &(*paragraphptr)->next) /* Nothing */;
+
+ if (buf + 0x19 > end) {Report("paragraph2"); return(FALSE);};
+
+ if (buf[0x14] == 0x02) return TRUE;
+
+ text = buf + GET_UINT(buf, 0x10);
+
+ switch (buf[0x14])
+ {
+ case 0x20:
+ format = buf + 0x18;
+ while (*format) format++;
+ format += 4;
+ break;
+
+ case 0x23:
+ format = buf + 0x2b;
+ if (buf[0x17] & 1) format++;
+ break;
+
+ default:
+ Report("paragraph3");
+ return FALSE;
+ }
+
+ while (text < end)
+ {
+ if (format_header)
+ {
+ format_header = FALSE;
+
+ mask = GET_USHORT(format, 0);
+ mask &= 0x3ff;
+ format += 2;
+
+ for (i = 0; i < 10; i++, mask = mask >> 1)
+ {
+ if (mask & 1)
+ {
+ BOOL twoargs = FALSE;
+ CHAR prefix0 = ' ';
+ CHAR prefix1 = '*';
+
+ if (i == 9 && !twoargs)
+ {
+ switch (*format++)
+ {
+ default:
+ prefix0 = prefix1 = '?';
+ break;
+
+ case 0x82:
+ prefix0 = prefix1 = 'x';
+ break;
+
+ case 0x84:
+ prefix0 = prefix1 = 'X';
+ twoargs = TRUE;
+ }
+ }
+
+ if (*format & 1)
+ switch(*format)
+ {
+ default:
+ format += 2;
+ break;
+ }
+ else
+ switch(*format)
+ {
+
+ default:
+ format++;
+ break;
+
+ case 0x08:
+ format += 3;
+ break;
+ }
+
+ if (twoargs) format += (*format & 1) ? 2 : 1;
+ }
+ }
+ }
+
+ for (; !format_header && text < end && format < end && !*text; text++)
+ {
+ switch(*format)
+ {
+ case 0x80:
+ attributes.wFont = GET_USHORT(format, 1);
+ format += 3;
+ break;
+
+ case 0x81:
+ attributes.wVSpace++;
+ format += 1;
+ break;
+
+ case 0x82:
+ attributes.wVSpace += 2 - attributes.wVBackSpace;
+ attributes.wVBackSpace = 0;
+ attributes.wIndent = 0;
+ format += 1;
+ break;
+
+ case 0x83:
+ attributes.wIndent++;
+ format += 1;
+ break;
+
+ case 0x84:
+ format += 3;
+ break;
+
+ case 0x86:
+ case 0x87:
+ case 0x88:
+ format += 9;
+ break;
+
+ case 0x89:
+ attributes.wVBackSpace++;
+ format += 1;
+ break;
+
+ case 0xa9:
+ format += 2;
+ break;
+
+ case 0xe2:
+ case 0xe3:
+ attributes.link.lpszPath = hlpfile->lpszPath;
+ attributes.link.lHash = GET_UINT(format, 1);
+ attributes.link.bPopup = !(*format & 1);
+ format += 5;
+ break;
+
+ case 0xea:
+ attributes.link.lpszPath = format + 8;
+ attributes.link.lHash = GET_UINT(format, 4);
+ attributes.link.bPopup = !(*format & 1);
+ format += 3 + GET_USHORT(format, 1);
+ break;
+
+ case 0xff:
+ if (buf[0x14] != 0x23 || GET_USHORT(format, 1) == 0xffff)
+ {
+ if (format_end) Report("format_end");
+ format_end = TRUE;
+ break;
+ }
+ else
+ {
+ format_header = TRUE;
+ format += 10;
+ break;
+ }
+
+ default:
+ Report("format");
+ format++;
+ }
+ }
+
+ if (text > end || format > end) {Report("paragraph_end"); return(FALSE);};
+ if (text == end && !format_end) Report("text_end");
+
+ if (text == end) break;
+
+ textsize = HLPFILE_Uncompressed2_Size(text, end);
+ hParagraph = GlobalAlloc(GMEM_FIXED, sizeof(HLPFILE_PARAGRAPH) + textsize);
+ if (!hParagraph) return FALSE;
+ paragraph = *paragraphptr = GlobalLock(hParagraph);
+ paragraphptr = ¶graph->next;
+ paragraph->hSelf = hParagraph;
+ paragraph->next = 0;
+ paragraph->link = 0;
+
+ paragraph->lpszText = GlobalLock(hParagraph);
+ paragraph->lpszText += sizeof(HLPFILE_PARAGRAPH);
+ HLPFILE_Uncompress2(&text, end, paragraph->lpszText);
+
+ paragraph->bDebug = attributes.bDebug;
+ paragraph->wFont = attributes.wFont;
+ paragraph->wVSpace = attributes.wVSpace;
+ paragraph->wHSpace = attributes.wHSpace;
+ paragraph->wIndent = attributes.wIndent;
+ if (attributes.link.lpszPath)
+ {
+ LPSTR ptr;
+ HGLOBAL handle = GlobalAlloc(GMEM_FIXED, sizeof(HLPFILE_LINK) +
+ strlen(attributes.link.lpszPath) + 1);
+ if (!handle) return FALSE;
+ paragraph->link = GlobalLock(handle);
+ paragraph->link->hSelf = handle;
+
+ ptr = GlobalLock(handle);
+ ptr += sizeof(HLPFILE_LINK);
+ lstrcpy(ptr, (LPSTR) attributes.link.lpszPath);
+
+ paragraph->link->lpszPath = ptr;
+ paragraph->link->lHash = attributes.link.lHash;
+ paragraph->link->bPopup = attributes.link.bPopup;
+ }
+
+ attributes.bDebug = 0;
+ attributes.wVSpace = 0;
+ attributes.wHSpace = 0;
+ attributes.link.lpszPath = 0;
+ }
+
+ return TRUE;
+}
+
+/***********************************************************************
+ *
+ * HLPFILE_ReadFileToBuffer
+ */
+
+static BOOL HLPFILE_ReadFileToBuffer(HFILE hFile)
+{
+ BYTE header[16], dummy[1];
+ UINT size;
+
+ if (_hread(hFile, header, 16) != 16) {Report("header"); return(FALSE);};
+
+ size = GET_UINT(header, 12);
+ hFileBuffer = GlobalAlloc(GMEM_FIXED, size + 1);
+ if (!hFileBuffer) return FALSE;
+ file_buffer = GlobalLock(hFileBuffer);
+
+ memcpy(file_buffer, header, 16);
+ if (_hread(hFile, file_buffer + 16, size - 16) != size - 16)
+ {Report("filesize1"); return(FALSE);};
+
+ if (_hread(hFile, dummy, 1) != 0) Report("filesize2");
+
+ file_buffer[size] = '0';
+
+ return TRUE;
+}
+
+/***********************************************************************
+ *
+ * HLPFILE_FindSubFile
+ */
+
+static BOOL HLPFILE_FindSubFile(LPCSTR name, BYTE **subbuf, BYTE **subend)
+{
+ BYTE *root = file_buffer + GET_UINT(file_buffer, 4);
+ BYTE *end = file_buffer + GET_UINT(file_buffer, 12);
+ BYTE *ptr = root + 0x37;
+
+ while (ptr < end && ptr[0] == 0x7c)
+ {
+ BYTE *fname = ptr + 1;
+ ptr += strlen(ptr) + 1;
+ if (!lstrcmpi(fname, name))
+ {
+ *subbuf = file_buffer + GET_UINT(ptr, 0);
+ *subend = *subbuf + GET_UINT(*subbuf, 0);
+ if (file_buffer > *subbuf || *subbuf > *subend || *subend >= end)
+ {
+ Report("subfile");
+ return FALSE;
+ }
+ return TRUE;
+ }
+ else ptr += 4;
+ }
+ return FALSE;
+}
+
+/***********************************************************************
+ *
+ * HLPFILE_SystemCommands
+ */
+static VOID HLPFILE_SystemCommands(HLPFILE* hlpfile)
+{
+ BYTE *buf, *ptr, *end;
+ HGLOBAL handle;
+ HLPFILE_MACRO *macro, **m;
+ LPSTR p;
+
+ hlpfile->lpszTitle = "";
+
+ if (!HLPFILE_FindSubFile("SYSTEM", &buf, &end)) return;
+
+ for (ptr = buf + 0x15; ptr + 4 <= end; ptr += GET_USHORT(ptr, 2) + 4)
+ {
+ switch (GET_USHORT(ptr, 0))
+ {
+ case 1:
+ if (hlpfile->hTitle) {Report("title"); break;}
+ hlpfile->hTitle = GlobalAlloc(GMEM_FIXED, strlen(ptr + 4) + 1);
+ if (!hlpfile->hTitle) return;
+ hlpfile->lpszTitle = GlobalLock(hlpfile->hTitle);
+ lstrcpy(hlpfile->lpszTitle, ptr + 4);
+ break;
+
+ case 2:
+ if (GET_USHORT(ptr, 2) != 1 || ptr[4] != 0) Report("system2");
+ break;
+
+ case 3:
+ if (GET_USHORT(ptr, 2) != 4 || GET_UINT(ptr, 4) != 0) Report("system3");
+ break;
+
+ case 4:
+ handle = GlobalAlloc(GMEM_FIXED, sizeof(HLPFILE_MACRO) + lstrlen(ptr + 4) + 1);
+ if (!handle) break;
+ macro = GlobalLock(handle);
+ macro->hSelf = handle;
+ p = GlobalLock(handle);
+ p += sizeof(HLPFILE_MACRO);
+ lstrcpy(p, (LPSTR) ptr + 4);
+ macro->lpszMacro = p;
+ macro->next = 0;
+ for (m = &hlpfile->first_macro; *m; m = &(*m)->next);
+ *m = macro;
+ break;
+
+ default:
+ Report("system");
+ }
+ }
+}
+
+/***********************************************************************
+ *
+ * HLPFILE_Uncompressed1_Size
+ */
+
+static INT HLPFILE_Uncompressed1_Size(BYTE *ptr, BYTE *end)
+{
+ INT i, newsize = 0;
+
+ while (ptr < end)
+ {
+ INT mask=*ptr++;
+ for (i = 0; i < 8 && ptr < end; i++, mask = mask >> 1)
+ {
+ if (mask & 1)
+ {
+ INT code = GET_USHORT(ptr, 0);
+ INT len = 3 + (code >> 12);
+ newsize += len;
+ ptr += 2;
+ }
+ else newsize++, ptr++;
+ }
+ }
+
+ return(newsize);
+}
+
+/***********************************************************************
+ *
+ * HLPFILE_Uncompress1
+ */
+
+static BYTE *HLPFILE_Uncompress1(BYTE *ptr, BYTE *end, BYTE *newptr)
+{
+ INT i;
+
+ while (ptr < end)
+ {
+ INT mask=*ptr++;
+ for (i = 0; i < 8 && ptr < end; i++, mask = mask >> 1)
+ {
+ if (mask & 1)
+ {
+ INT code = GET_USHORT(ptr, 0);
+ INT len = 3 + (code >> 12);
+ INT offset = code & 0xfff;
+ hmemcpy(newptr, newptr - offset - 1, len);
+ newptr += len;
+ ptr += 2;
+ }
+ else *newptr++ = *ptr++;
+ }
+ }
+
+ return(newptr);
+}
+
+/***********************************************************************
+ *
+ * HLPFILE_Uncompress1_Phrases
+ */
+
+static BOOL HLPFILE_Uncompress1_Phrases()
+{
+ UINT i, num, newsize;
+ BYTE *buf, *end, *newbuf;
+
+ if (!HLPFILE_FindSubFile("Phrases", &buf, &end)) {Report("phrases0"); return FALSE;}
+
+ num = phrases.num = GET_USHORT(buf, 9);
+ if (buf + 2 * num + 0x13 >= end) {Report("uncompress1a"); return(FALSE);};
+
+ newsize = 2 * num + 2;
+ newsize += HLPFILE_Uncompressed1_Size(buf + 0x13 + 2 * num, end);
+ phrases.hBuffer = GlobalAlloc(GMEM_FIXED, newsize);
+ if (!phrases.hBuffer) return FALSE;
+ newbuf = phrases.buf = GlobalLock(phrases.hBuffer);
+
+ hmemcpy(newbuf, buf + 0x11, 2 * num + 2);
+ HLPFILE_Uncompress1(buf + 0x13 + 2 * num, end, newbuf + 2 * num + 2);
+
+ for (i = 0; i < num; i++)
+ {
+ INT i0 = GET_USHORT(newbuf, 2 * i);
+ INT i1 = GET_USHORT(newbuf, 2 * i + 2);
+ if (i1 < i0 || i1 > newsize) {Report("uncompress1b"); return(FALSE);};
+ }
+ return TRUE;
+}
+
+/***********************************************************************
+ *
+ * HLPFILE_Uncompress1_Topic
+ */
+
+static BOOL HLPFILE_Uncompress1_Topic()
+{
+ BYTE *buf, *ptr, *end, *newptr;
+ INT i, newsize = 0;
+
+ if (!HLPFILE_FindSubFile("TOPIC", &buf, &end)) {Report("topic0"); return FALSE;}
+
+ buf += 9;
+ topic.wMapLen = (end - buf - 1) / 0x1000 + 1;
+
+ for (i = 0; i < topic.wMapLen; i++)
+ {
+ ptr = buf + i * 0x1000;
+
+ /* I don't know why, it's necessary for printman.hlp */
+ if (ptr + 0x44 > end) ptr = end - 0x44;
+
+ newsize += HLPFILE_Uncompressed1_Size(ptr + 0xc, MIN(end, ptr + 0x1000));
+ }
+
+ topic.hMap = GlobalAlloc(GMEM_FIXED, topic.wMapLen * sizeof(topic.map[0]));
+ topic.hBuffer = GlobalAlloc(GMEM_FIXED, newsize);
+ if (!topic.hMap || !topic.hBuffer) return FALSE;
+ topic.map = GlobalLock(topic.hMap);
+ newptr = GlobalLock(topic.hBuffer);
+ topic.end = newptr + newsize;
+
+ for (i = 0; i < topic.wMapLen; i++)
+ {
+ ptr = buf + i * 0x1000;
+ if (ptr + 0x44 > end) ptr = end - 0x44;
+
+ topic.map[i] = newptr - 0xc;
+ newptr = HLPFILE_Uncompress1(ptr + 0xc, MIN(end, ptr + 0x1000), newptr);
+ }
+
+ return TRUE;
+}
+
+/***********************************************************************
+ *
+ * HLPFILE_Uncompressed2_Size
+ */
+
+static UINT HLPFILE_Uncompressed2_Size(BYTE *ptr, BYTE *end)
+{
+ UINT wSize = 0;
+
+ while (ptr < end && *ptr)
+ {
+ if (*ptr >= 0x20)
+ wSize++, ptr++;
+ else
+ {
+ BYTE *phptr, *phend;
+ UINT code = 0x100 * ptr[0] + ptr[1];
+ UINT index = (code - 0x100) / 2;
+ BOOL space = code & 1;
+
+ if (index < phrases.num)
+ {
+ phptr = phrases.buf + GET_USHORT(phrases.buf, 2 * index);
+ phend = phrases.buf + GET_USHORT(phrases.buf, 2 * index + 2);
+
+ if (phend < phptr) Report("uncompress2a");
+
+ wSize += phend - phptr;
+ if (space) wSize++;
+ }
+ else Report("uncompress2b");
+
+ ptr += 2;
+ }
+ }
+
+ return(wSize + 1);
+}
+
+/***********************************************************************
+ *
+ * HLPFILE_Uncompress2
+ */
+
+static VOID HLPFILE_Uncompress2(BYTE **pptr, BYTE *end, BYTE *newptr)
+{
+ BYTE *ptr = *pptr;
+
+ while (ptr < end && *ptr)
+ {
+ if (*ptr >= 0x20)
+ *newptr++ = *ptr++;
+ else
+ {
+ BYTE *phptr, *phend;
+ UINT code = 0x100 * ptr[0] + ptr[1];
+ UINT index = (code - 0x100) / 2;
+ BOOL space = code & 1;
+
+ phptr = phrases.buf + GET_USHORT(phrases.buf, 2 * index);
+ phend = phrases.buf + GET_USHORT(phrases.buf, 2 * index + 2);
+
+ hmemcpy(newptr, phptr, phend - phptr);
+ newptr += phend - phptr;
+ if (space) *newptr++ = ' ';
+
+ ptr += 2;
+ }
+ }
+ *newptr = '\0';
+ *pptr = ptr;
+}
+
+/***********************************************************************
+ *
+ * HLPFILE_GetContext
+ */
+
+static BOOL HLPFILE_GetContext(HLPFILE *hlpfile)
+{
+ UINT i, j, clen, tlen;
+ BYTE *cbuf, *cptr, *cend, *tbuf, *tptr, *tend;
+
+ if (!HLPFILE_FindSubFile("CONTEXT", &cbuf, &cend)) {Report("context0"); return FALSE;}
+ if (cbuf + 0x37 > cend) {Report("context1"); return(FALSE);};
+ clen = GET_UINT(cbuf, 0x2b);
+ if (cbuf + 0x37 + 8 * hlpfile->wContextLen > cend) {Report("context2"); return(FALSE);};
+
+ if (!HLPFILE_FindSubFile("TTLBTREE", &tbuf, &tend)) {Report("ttlb0"); return FALSE;}
+ if (tbuf + 0x37 > tend) {Report("ttlb1"); return(FALSE);};
+ tlen = GET_UINT(tbuf, 0x2b);
+
+ hlpfile->hContext = GlobalAlloc(GMEM_FIXED, clen * sizeof(HLPFILE_CONTEXT));
+ if (!hlpfile->hContext) return FALSE;
+ hlpfile->Context = GlobalLock(hlpfile->hContext);
+ hlpfile->wContextLen = clen;
+
+ cptr = cbuf + 0x37;
+ for (i = 0; i < clen; i++, cptr += 8)
+ {
+ tptr = tbuf + 0x37;
+ for (j = 0; j < tlen; j++, tptr += 5 + strlen(tptr + 4))
+ {
+ if (tptr + 4 >= tend) {Report("ttlb2"); return(FALSE);};
+ if (GET_UINT(tptr, 0) == GET_UINT(cptr, 4)) break;
+ }
+ if (j >= tlen)
+ {
+ Report("ttlb3");
+ j = 0;
+ }
+ hlpfile->Context[i].lHash = GET_UINT(cptr, 0);
+ hlpfile->Context[i].wPage = j;
+ }
+
+ return TRUE;
+}
+
+/***********************************************************************
+ *
+ * HLPFILE_DeleteParagraph
+ */
+
+static VOID HLPFILE_DeleteParagraph(HLPFILE_PARAGRAPH* paragraph)
+{
+ if (!paragraph) return;
+
+ if (paragraph->link) GlobalFree(paragraph->link->hSelf);
+
+ HLPFILE_DeleteParagraph(paragraph->next);
+ GlobalFree(paragraph->hSelf);
+}
+
+/***********************************************************************
+ *
+ * DeletePage
+ */
+
+static VOID HLPFILE_DeletePage(HLPFILE_PAGE* page)
+{
+ if (!page) return;
+
+ HLPFILE_DeletePage(page->next);
+ HLPFILE_DeleteParagraph(page->first_paragraph);
+ GlobalFree(page->hSelf);
+}
+
+/***********************************************************************
+ *
+ * DeleteMacro
+ */
+
+static VOID HLPFILE_DeleteMacro(HLPFILE_MACRO* macro)
+{
+ if (!macro) return;
+
+ HLPFILE_DeleteMacro(macro->next);
+ GlobalFree(macro->hSelf);
+}
+
+/***********************************************************************
+ *
+ * HLPFILE_FreeHlpFile
+ */
+
+VOID HLPFILE_FreeHlpFile(HLPFILE* hlpfile)
+{
+ if (!hlpfile) return;
+ if (--hlpfile->wRefCount) return;
+
+ if (hlpfile->next) hlpfile->next->prev = hlpfile->prev;
+ if (hlpfile->prev) hlpfile->prev->next = hlpfile->next;
+ else first_hlpfile = 0;
+
+ HLPFILE_DeletePage(hlpfile->first_page);
+ HLPFILE_DeleteMacro(hlpfile->first_macro);
+ GlobalFree(hlpfile->hContext);
+ GlobalFree(hlpfile->hTitle);
+ GlobalFree(hlpfile->hSelf);
+}
+
+/***********************************************************************
+ *
+ * FreeHlpFilePage
+ */
+
+VOID HLPFILE_FreeHlpFilePage(HLPFILE_PAGE* page)
+{
+ if (!page) return;
+ HLPFILE_FreeHlpFile(page->file);
+}
+
+/* Local Variables: */
+/* c-file-style: "GNU" */
+/* End: */
diff --git a/programs/winhelp/hlpfile.h b/programs/winhelp/hlpfile.h
new file mode 100644
index 0000000..fb525db
--- /dev/null
+++ b/programs/winhelp/hlpfile.h
@@ -0,0 +1,90 @@
+/*
+ * Help Viewer
+ *
+ * Copyright 1996 Ulrich Schmid
+ */
+
+struct tagHelpFile;
+
+typedef struct
+{
+ LPCSTR lpszPath;
+ LONG lHash;
+ BOOL bPopup;
+
+ HGLOBAL hSelf;
+} HLPFILE_LINK;
+
+typedef struct tagHlpFileParagraph
+{
+ LPSTR lpszText;
+
+ UINT bDebug;
+ UINT wFont;
+ UINT wIndent;
+ UINT wHSpace;
+ UINT wVSpace;
+
+ HLPFILE_LINK *link;
+
+ struct tagHlpFileParagraph *next;
+
+ HGLOBAL hSelf;
+} HLPFILE_PARAGRAPH;
+
+typedef struct tagHlpFilePage
+{
+ LPSTR lpszTitle;
+ HLPFILE_PARAGRAPH *first_paragraph;
+
+ UINT wNumber;
+
+ struct tagHlpFilePage *next;
+ struct tagHlpFileFile *file;
+
+ HGLOBAL hSelf;
+} HLPFILE_PAGE;
+
+typedef struct
+{
+ LONG lHash;
+ UINT wPage;
+} HLPFILE_CONTEXT;
+
+typedef struct tagHlpFileMacro
+{
+ LPCSTR lpszMacro;
+
+ HGLOBAL hSelf;
+ struct tagHlpFileMacro *next;
+} HLPFILE_MACRO;
+
+typedef struct tagHlpFileFile
+{
+ LPSTR lpszPath;
+ LPSTR lpszTitle;
+ HLPFILE_PAGE *first_page;
+ HLPFILE_MACRO *first_macro;
+ UINT wContextLen;
+ HLPFILE_CONTEXT *Context;
+
+ struct tagHlpFileFile *prev;
+ struct tagHlpFileFile *next;
+
+ UINT wRefCount;
+
+ HGLOBAL hTitle;
+ HGLOBAL hContext;
+ HGLOBAL hSelf;
+} HLPFILE;
+
+HLPFILE *HLPFILE_ReadHlpFile(LPCSTR lpszPath);
+HLPFILE_PAGE *HLPFILE_Contents(LPCSTR lpszPath);
+HLPFILE_PAGE *HLPFILE_PageByHash(LPCSTR lpszPath, LONG wNum);
+LONG HLPFILE_Hash(LPCSTR lpszContext);
+VOID HLPFILE_FreeHlpFilePage(HLPFILE_PAGE*);
+VOID HLPFILE_FreeHlpFile(HLPFILE*);
+
+/* Local Variables: */
+/* c-file-style: "GNU" */
+/* End: */
diff --git a/programs/winhelp/macro.c b/programs/winhelp/macro.c
new file mode 100644
index 0000000..7355270
--- /dev/null
+++ b/programs/winhelp/macro.c
@@ -0,0 +1,555 @@
+/*
+ * Help Viewer
+ *
+ * Copyright 1996 Ulrich Schmid
+ */
+
+#include <stdio.h>
+#include <windows.h>
+#include <commdlg.h>
+#ifdef WINELIB
+#include <shell.h>
+#endif
+#include "winhelp.h"
+#include "macro.h"
+
+VOID MACRO_About(VOID)
+{
+ fprintf(stderr, "About()\n");
+}
+
+VOID MACRO_AddAccelerator(LONG u1, LONG u2, LPCSTR str)
+{
+ fprintf(stderr, "AddAccelerator(%lu, %lu, \"%s\")\n", u1, u2, str);
+}
+
+VOID MACRO_ALink(LPCSTR str1, LONG u, LPCSTR str2)
+{
+ fprintf(stderr, "ALink(\"%s\", %lu, \"%s\")\n", str1, u, str2);
+}
+
+VOID MACRO_Annotate(VOID)
+{
+ fprintf(stderr, "Annotate()\n");
+}
+
+VOID MACRO_AppendItem(LPCSTR str1, LPCSTR str2, LPCSTR str3, LPCSTR str4)
+{
+ fprintf(stderr, "AppendItem(\"%s\", \"%s\", \"%s\", \"%s\")\n", str1, str2, str3, str4);
+}
+
+VOID MACRO_Back(VOID)
+{
+ fprintf(stderr, "Back()\n");
+}
+
+VOID MACRO_BackFlush(VOID)
+{
+ fprintf(stderr, "BackFlush()\n");
+}
+
+VOID MACRO_BookmarkDefine(VOID)
+{
+ fprintf(stderr, "BookmarkDefine()\n");
+}
+
+VOID MACRO_BookmarkMore(VOID)
+{
+ fprintf(stderr, "BookmarkMore()\n");
+}
+
+VOID MACRO_BrowseButtons(VOID)
+{
+ MACRO_CreateButton("BTN_PREV", "&<<", "Prev()");
+ MACRO_CreateButton("BTN_NEXT", "&>>", "Next()");
+}
+
+VOID MACRO_ChangeButtonBinding(LPCSTR str1, LPCSTR str2)
+{
+ fprintf(stderr, "ChangeButtonBinding(\"%s\", \"%s\")\n", str1, str2);
+}
+
+VOID MACRO_ChangeEnable(LPCSTR str1, LPCSTR str2)
+{
+ fprintf(stderr, "ChangeEnable(\"%s\", \"%s\")\n", str1, str2);
+}
+
+VOID MACRO_ChangeItemBinding(LPCSTR str1, LPCSTR str2)
+{
+ fprintf(stderr, "ChangeItemBinding(\"%s\", \"%s\")\n", str1, str2);
+}
+
+VOID MACRO_CheckItem(LPCSTR str)
+{
+ fprintf(stderr, "CheckItem(\"%s\")\n", str);
+}
+
+VOID MACRO_CloseSecondarys(VOID)
+{
+ WINHELP_WINDOW *win;
+ for (win = Globals.win_list; win; win = win->next)
+ if (win->lpszName && lstrcmpi(win->lpszName, "main"))
+ DestroyWindow(win->hMainWnd);
+}
+
+VOID MACRO_CloseWindow(LPCSTR lpszWindow)
+{
+ WINHELP_WINDOW *win;
+ if (!lpszWindow || !lpszWindow[0]) lpszWindow = "main";
+
+ for (win = Globals.win_list; win; win = win->next)
+ if (win->lpszName && !lstrcmpi(win->lpszName, lpszWindow))
+ DestroyWindow(win->hMainWnd);
+}
+
+VOID MACRO_Compare(LPCSTR str)
+{
+ fprintf(stderr, "Compare(\"%s\")\n", str);
+}
+
+VOID MACRO_Contents(VOID)
+{
+ if (Globals.active_win->page)
+ MACRO_JumpContents(Globals.active_win->page->file->lpszPath, NULL);
+}
+
+VOID MACRO_ControlPanel(LPCSTR str1, LPCSTR str2, LONG u)
+{
+ fprintf(stderr, "ControlPanel(\"%s\", \"%s\", %lu)\n", str1, str2, u);
+}
+
+VOID MACRO_CopyDialog(VOID)
+{
+ fprintf(stderr, "CopyDialog()\n");
+}
+
+VOID MACRO_CopyTopic(VOID)
+{
+ fprintf(stderr, "CopyTopic()\n");
+}
+
+VOID MACRO_CreateButton(LPCSTR id, LPCSTR name, LPCSTR macro)
+{
+ WINHELP_WINDOW *win = Globals.active_win;
+ WINHELP_BUTTON *button, **b;
+ LONG size;
+ HGLOBAL handle;
+ LPSTR ptr;
+
+ size = sizeof(WINHELP_BUTTON) + lstrlen(id) + lstrlen(name) + lstrlen(macro) + 3;
+ handle = GlobalAlloc(GMEM_FIXED, size);
+ if (!handle) return;
+
+ button = GlobalLock(handle);
+ button->hSelf = handle;
+ button->next = 0;
+ button->hWnd = 0;
+
+ ptr = GlobalLock(handle);
+ ptr += sizeof(WINHELP_BUTTON);
+
+ lstrcpy(ptr, (LPSTR) id);
+ button->lpszID = ptr;
+ ptr += lstrlen(id) + 1;
+
+ lstrcpy(ptr, (LPSTR) name);
+ button->lpszName = ptr;
+ ptr += lstrlen(name) + 1;
+
+ lstrcpy(ptr, (LPSTR) 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;
+
+ SendMessage(win->hMainWnd, WM_USER, 0, 0);
+}
+
+VOID MACRO_DeleteItem(LPCSTR str)
+{
+ fprintf(stderr, "DeleteItem(\"%s\")\n", str);
+}
+
+VOID MACRO_DeleteMark(LPCSTR str)
+{
+ fprintf(stderr, "DeleteMark(\"%s\")\n", str);
+}
+
+VOID MACRO_DestroyButton(LPCSTR str)
+{
+ fprintf(stderr, "DestroyButton(\"%s\")\n", str);
+}
+
+VOID MACRO_DisableButton(LPCSTR str)
+{
+ fprintf(stderr, "DisableButton(\"%s\")\n", str);
+}
+
+VOID MACRO_DisableItem(LPCSTR str)
+{
+ fprintf(stderr, "DisableItem(\"%s\")\n", str);
+}
+
+VOID MACRO_EnableButton(LPCSTR str)
+{
+ fprintf(stderr, "EnableButton(\"%s\")\n", str);
+}
+
+VOID MACRO_EnableItem(LPCSTR str)
+{
+ fprintf(stderr, "EnableItem(\"%s\")\n", str);
+}
+
+VOID MACRO_EndMPrint(VOID)
+{
+ fprintf(stderr, "EndMPrint()\n");
+}
+
+VOID MACRO_ExecFile(LPCSTR str1, LPCSTR str2, LONG u, LPCSTR str3)
+{
+ fprintf(stderr, "ExecFile(\"%s\", \"%s\", %lu, \"%s\")\n", str1, str2, u, str3);
+}
+
+VOID MACRO_ExecProgram(LPCSTR str, LONG u)
+{
+ fprintf(stderr, "ExecProgram(\"%s\", %lu)\n", str, u);
+}
+
+VOID MACRO_Exit(VOID)
+{
+ while(Globals.win_list)
+ DestroyWindow(Globals.win_list->hMainWnd);
+}
+
+VOID MACRO_ExtAbleItem(LPCSTR str, LONG u)
+{
+ fprintf(stderr, "ExtAbleItem(\"%s\", %lu)\n", str, u);
+}
+
+VOID MACRO_ExtInsertItem(LPCSTR str1, LPCSTR str2, LPCSTR str3, LPCSTR str4, LONG u1, LONG u2)
+{
+ fprintf(stderr, "ExtInsertItem(\"%s\", \"%s\", \"%s\", \"%s\", %lu, %lu)\n", str1, str2, str3, str4, u1, u2);
+}
+
+VOID MACRO_ExtInsertMenu(LPCSTR str1, LPCSTR str2, LPCSTR str3, LONG u1, LONG u2)
+{
+ fprintf(stderr, "ExtInsertMenu(\"%s\", \"%s\", \"%s\", %lu, %lu)\n", str1, str2, str3, u1, u2);
+}
+
+BOOL MACRO_FileExist(LPCSTR str)
+{
+ fprintf(stderr, "FileExist(\"%s\")\n", str);
+ return TRUE;
+}
+
+VOID MACRO_FileOpen(VOID)
+{
+ OPENFILENAME openfilename;
+ CHAR szPath[MAX_PATHNAME_LEN];
+ CHAR szDir[MAX_PATHNAME_LEN];
+ CHAR szzFilter[2 * MAX_STRING_LEN + 100];
+ LPSTR p = szzFilter;
+
+ LoadString(Globals.hInstance, IDS_HELP_FILES_HLP, p, MAX_STRING_LEN);
+ p += strlen(p) + 1;
+ lstrcpy(p, "*.hlp");
+ p += strlen(p) + 1;
+ LoadString(Globals.hInstance, IDS_ALL_FILES, p, MAX_STRING_LEN);
+ p += strlen(p) + 1;
+ lstrcpy(p, "*.*");
+ p += strlen(p) + 1;
+ *p = '\0';
+
+ GetWindowsDirectory(szDir, sizeof(szDir));
+
+ openfilename.lStructSize = 0;
+ openfilename.hwndOwner = Globals.active_win->hMainWnd;
+ openfilename.hInstance = Globals.hInstance;
+ openfilename.lpstrFilter = szzFilter;
+ openfilename.lpstrCustomFilter = 0;
+ openfilename.nMaxCustFilter = 0;
+ openfilename.nFilterIndex = 0;
+ openfilename.lpstrFile = szPath;
+ openfilename.nMaxFile = sizeof(szPath);
+ openfilename.lpstrFileTitle = 0;
+ openfilename.nMaxFileTitle = 0;
+ openfilename.lpstrInitialDir = szDir;
+ openfilename.lpstrTitle = 0;
+ openfilename.Flags = 0;
+ openfilename.nFileOffset = 0;
+ openfilename.nFileExtension = 0;
+ openfilename.lpstrDefExt = 0;
+ openfilename.lCustData = 0;
+ openfilename.lpfnHook = 0;
+ openfilename.lpTemplateName = 0;
+
+ if (GetOpenFileName(&openfilename))
+ WINHELP_CreateHelpWindow(szPath, 0, "main", FALSE, NULL, NULL, SW_SHOWNORMAL);
+}
+
+VOID MACRO_Find(VOID)
+{
+ fprintf(stderr, "Find()\n");
+}
+
+VOID MACRO_Finder(VOID)
+{
+ fprintf(stderr, "Finder()\n");
+}
+
+VOID MACRO_FloatingMenu(VOID)
+{
+ fprintf(stderr, "FloatingMenu()\n");
+}
+
+VOID MACRO_Flush(VOID)
+{
+ fprintf(stderr, "Flush()\n");
+}
+
+VOID MACRO_FocusWindow(LPCSTR str)
+{
+ fprintf(stderr, "FocusWindow(\"%s\")\n", str);
+}
+
+VOID MACRO_Generate(LPCSTR str, WPARAM w, LPARAM l)
+{
+ fprintf(stderr, "Generate(\"%s\", %x, %lx)\n", str, w, l);
+}
+
+VOID MACRO_GotoMark(LPCSTR str)
+{
+ fprintf(stderr, "GotoMark(\"%s\")\n", str);
+}
+
+VOID MACRO_HelpOn(VOID)
+{
+ MACRO_JumpContents((Globals.wVersion > 4) ? "winhelp32.hlp" : "winhelp.hlp", NULL);
+}
+
+VOID MACRO_HelpOnTop(VOID)
+{
+ fprintf(stderr, "HelpOnTop()\n");
+}
+
+VOID MACRO_History(VOID)
+{
+ fprintf(stderr, "History()\n");
+}
+
+BOOL MACRO_InitMPrint(VOID)
+{
+ fprintf(stderr, "InitMPrint()\n");
+ return FALSE;
+}
+
+VOID MACRO_InsertItem(LPCSTR str1, LPCSTR str2, LPCSTR str3, LPCSTR str4, LONG u)
+{
+ fprintf(stderr, "InsertItem(\"%s\", \"%s\", \"%s\", \"%s\", %lu)\n", str1, str2, str3, str4, u);
+}
+
+VOID MACRO_InsertMenu(LPCSTR str1, LPCSTR str2, LONG u)
+{
+ fprintf(stderr, "InsertMenu(\"%s\", \"%s\", %lu)\n", str1, str2, u);
+}
+
+BOOL MACRO_IsBook(VOID)
+{
+ fprintf(stderr, "IsBook()\n");
+ return TRUE;
+}
+
+BOOL MACRO_IsMark(LPCSTR str)
+{
+ fprintf(stderr, "IsMark(\"%s\")\n", str);
+ return FALSE;
+}
+
+BOOL MACRO_IsNotMark(LPCSTR str)
+{
+ fprintf(stderr, "IsNotMark(\"%s\")\n", str);
+ return TRUE;
+}
+
+VOID MACRO_JumpContents(LPCSTR lpszPath, LPCSTR lpszWindow)
+{
+ WINHELP_CreateHelpWindow(lpszPath, 0, lpszWindow, FALSE, NULL, NULL, SW_NORMAL);
+}
+
+VOID MACRO_JumpContext(LPCSTR lpszPath, LPCSTR lpszWindow, LONG context)
+{
+ fprintf(stderr, "JumpContext(\"%s\", \"%s\", %lu)\n", lpszPath, lpszWindow, context);
+}
+
+VOID MACRO_JumpHash(LPCSTR lpszPath, LPCSTR lpszWindow, LONG lHash)
+{
+ WINHELP_CreateHelpWindow(lpszPath, lHash, lpszWindow, FALSE, NULL, NULL, SW_NORMAL);
+}
+
+VOID MACRO_JumpHelpOn(VOID)
+{
+ fprintf(stderr, "JumpHelpOn()\n");
+}
+
+VOID MACRO_JumpID(LPCSTR lpszPath, LPCSTR lpszWindow, LPCSTR topic_id)
+{
+ MACRO_JumpHash(lpszPath, lpszWindow, HLPFILE_Hash(topic_id));
+}
+
+VOID MACRO_JumpKeyword(LPCSTR lpszPath, LPCSTR lpszWindow, LPCSTR keyword)
+{
+ fprintf(stderr, "JumpKeyword(\"%s\", \"%s\", \"%s\")\n", lpszPath, lpszWindow, keyword);
+}
+
+VOID MACRO_KLink(LPCSTR str1, LONG u, LPCSTR str2, LPCSTR str3)
+{
+ fprintf(stderr, "KLink(\"%s\", %lu, \"%s\", \"%s\")\n", str1, u, str2, str3);
+}
+
+VOID MACRO_Menu(VOID)
+{
+ fprintf(stderr, "Menu()\n");
+}
+
+VOID MACRO_MPrintHash(LONG u)
+{
+ fprintf(stderr, "MPrintHash(%lu)\n", u);
+}
+
+VOID MACRO_MPrintID(LPCSTR str)
+{
+ fprintf(stderr, "MPrintID(\"%s\")\n", str);
+}
+
+VOID MACRO_Next(VOID)
+{
+ fprintf(stderr, "Next()\n");
+}
+
+VOID MACRO_NoShow(VOID)
+{
+ fprintf(stderr, "NoShow()\n");
+}
+
+VOID MACRO_PopupContext(LPCSTR str, LONG u)
+{
+ fprintf(stderr, "PopupContext(\"%s\", %lu)\n", str, u);
+}
+
+VOID MACRO_PopupHash(LPCSTR str, LONG u)
+{
+ fprintf(stderr, "PopupHash(\"%s\", %lu)\n", str, u);
+}
+
+VOID MACRO_PopupId(LPCSTR str1, LPCSTR str2)
+{
+ fprintf(stderr, "PopupId(\"%s\", \"%s\")\n", str1, str2);
+}
+
+VOID MACRO_PositionWindow(LONG i1, LONG i2, LONG u1, LONG u2, LONG u3, LPCSTR str)
+{
+ fprintf(stderr, "PositionWindow(%li, %li, %lu, %lu, %lu, \"%s\")\n", i1, i2, u1, u2, u3, str);
+}
+
+VOID MACRO_Prev(VOID)
+{
+ fprintf(stderr, "Prev()\n");
+}
+
+VOID MACRO_Print(VOID)
+{
+ fprintf(stderr, "Print()\n");
+}
+
+VOID MACRO_PrinterSetup(VOID)
+{
+ fprintf(stderr, "PrinterSetup()\n");
+}
+
+VOID MACRO_RegisterRoutine(LPCSTR str1, LPCSTR str2, LPCSTR str3)
+{
+ fprintf(stderr, "RegisterRoutine(\"%s\", \"%s\", \"%s\")\n", str1, str2, str3);
+}
+
+VOID MACRO_RemoveAccelerator(LONG u1, LONG u2)
+{
+ fprintf(stderr, "RemoveAccelerator(%lu, %lu)\n", u1, u2);
+}
+
+VOID MACRO_ResetMenu(VOID)
+{
+ fprintf(stderr, "ResetMenu()\n");
+}
+
+VOID MACRO_SaveMark(LPCSTR str)
+{
+ fprintf(stderr, "SaveMark(\"%s\")\n", str);
+}
+
+VOID MACRO_Search(VOID)
+{
+ fprintf(stderr, "Search()\n");
+}
+
+VOID MACRO_SetContents(LPCSTR str, LONG u)
+{
+ fprintf(stderr, "SetContents(\"%s\", %lu)\n", str, u);
+}
+
+VOID MACRO_SetHelpOnFile(LPCSTR str)
+{
+ fprintf(stderr, "SetHelpOnFile(\"%s\")\n", str);
+}
+
+VOID MACRO_SetPopupColor(LONG u1, LONG u2, LONG u3)
+{
+ fprintf(stderr, "SetPopupColor(%lu, %lu, %lu)\n", u1, u2, u3);
+}
+
+VOID MACRO_ShellExecute(LPCSTR str1, LPCSTR str2, LONG u1, LONG u2, LPCSTR str3, LPCSTR str4)
+{
+ fprintf(stderr, "ShellExecute(\"%s\", \"%s\", %lu, %lu, \"%s\", \"%s\")\n", str1, str2, u1, u2, str3, str4);
+}
+
+VOID MACRO_ShortCut(LPCSTR str1, LPCSTR str2, WPARAM w, LPARAM l, LPCSTR str)
+{
+ fprintf(stderr, "ShortCut(\"%s\", \"%s\", %x, %lx, \"%s\")\n", str1, str2, w, l, str);
+}
+
+VOID MACRO_TCard(LONG u)
+{
+ fprintf(stderr, "TCard(%lu)\n", u);
+}
+
+VOID MACRO_Test(LONG u)
+{
+ fprintf(stderr, "Test(%lu)\n", u);
+}
+
+BOOL MACRO_TestALink(LPCSTR str)
+{
+ fprintf(stderr, "TestALink(\"%s\")\n", str);
+ return FALSE;
+}
+
+BOOL MACRO_TestKLink(LPCSTR str)
+{
+ fprintf(stderr, "TestKLink(\"%s\")\n", str);
+ return FALSE;
+}
+
+VOID MACRO_UncheckItem(LPCSTR str)
+{
+ fprintf(stderr, "UncheckItem(\"%s\")\n", str);
+}
+
+VOID MACRO_UpdateWindow(LPCSTR str1, LPCSTR str2)
+{
+ fprintf(stderr, "UpdateWindow(\"%s\", \"%s\")\n", str1, str2);
+}
+
+/* Local Variables: */
+/* c-file-style: "GNU" */
+/* End: */
diff --git a/programs/winhelp/macro.h b/programs/winhelp/macro.h
new file mode 100644
index 0000000..b09e8dd
--- /dev/null
+++ b/programs/winhelp/macro.h
@@ -0,0 +1,108 @@
+/*
+ * Help Viewer
+ *
+ * Copyright 1996 Ulrich Schmid
+ */
+
+#include <windows.h>
+
+VOID MACRO_ExecuteMacro(LPCSTR);
+
+INT yyparse(VOID);
+INT yylex(VOID);
+VOID yyerror(LPCSTR);
+extern CHAR MACRO_extra_separator;
+
+VOID MACRO_About(VOID);
+VOID MACRO_AddAccelerator(LONG, LONG, LPCSTR);
+VOID MACRO_ALink(LPCSTR, LONG, LPCSTR);
+VOID MACRO_Annotate(VOID);
+VOID MACRO_AppendItem(LPCSTR, LPCSTR, LPCSTR, LPCSTR);
+VOID MACRO_Back(VOID);
+VOID MACRO_BackFlush(VOID);
+VOID MACRO_BookmarkDefine(VOID);
+VOID MACRO_BookmarkMore(VOID);
+VOID MACRO_BrowseButtons(VOID);
+VOID MACRO_ChangeButtonBinding(LPCSTR, LPCSTR);
+VOID MACRO_ChangeEnable(LPCSTR, LPCSTR);
+VOID MACRO_ChangeItemBinding(LPCSTR, LPCSTR);
+VOID MACRO_CheckItem(LPCSTR);
+VOID MACRO_CloseSecondarys(VOID);
+VOID MACRO_CloseWindow(LPCSTR);
+VOID MACRO_Compare(LPCSTR);
+VOID MACRO_Contents(VOID);
+VOID MACRO_ControlPanel(LPCSTR, LPCSTR, LONG);
+VOID MACRO_CopyDialog(VOID);
+VOID MACRO_CopyTopic(VOID);
+VOID MACRO_CreateButton(LPCSTR, LPCSTR, LPCSTR);
+VOID MACRO_DeleteItem(LPCSTR);
+VOID MACRO_DeleteMark(LPCSTR);
+VOID MACRO_DestroyButton(LPCSTR);
+VOID MACRO_DisableButton(LPCSTR);
+VOID MACRO_DisableItem(LPCSTR);
+VOID MACRO_EnableButton(LPCSTR);
+VOID MACRO_EnableItem(LPCSTR);
+VOID MACRO_EndMPrint(VOID);
+VOID MACRO_ExecFile(LPCSTR, LPCSTR, LONG, LPCSTR);
+VOID MACRO_ExecProgram(LPCSTR, LONG);
+VOID MACRO_Exit(VOID);
+VOID MACRO_ExtAbleItem(LPCSTR, LONG);
+VOID MACRO_ExtInsertItem(LPCSTR, LPCSTR, LPCSTR, LPCSTR, LONG, LONG);
+VOID MACRO_ExtInsertMenu(LPCSTR, LPCSTR, LPCSTR, LONG, LONG);
+BOOL MACRO_FileExist(LPCSTR);
+VOID MACRO_FileOpen(VOID);
+VOID MACRO_Find(VOID);
+VOID MACRO_Finder(VOID);
+VOID MACRO_FloatingMenu(VOID);
+VOID MACRO_Flush(VOID);
+VOID MACRO_FocusWindow(LPCSTR);
+VOID MACRO_Generate(LPCSTR, WPARAM, LPARAM);
+VOID MACRO_GotoMark(LPCSTR);
+VOID MACRO_HelpOn(VOID);
+VOID MACRO_HelpOnTop(VOID);
+VOID MACRO_History(VOID);
+BOOL MACRO_InitMPrint(VOID);
+VOID MACRO_InsertItem(LPCSTR, LPCSTR, LPCSTR, LPCSTR, LONG);
+VOID MACRO_InsertMenu(LPCSTR, LPCSTR, LONG);
+BOOL MACRO_IsBook(VOID);
+BOOL MACRO_IsMark(LPCSTR);
+BOOL MACRO_IsNotMark(LPCSTR);
+VOID MACRO_JumpContents(LPCSTR, LPCSTR);
+VOID MACRO_JumpContext(LPCSTR, LPCSTR, LONG);
+VOID MACRO_JumpHash(LPCSTR, LPCSTR, LONG);
+VOID MACRO_JumpHelpOn(VOID);
+VOID MACRO_JumpID(LPCSTR, LPCSTR, LPCSTR);
+VOID MACRO_JumpKeyword(LPCSTR, LPCSTR, LPCSTR);
+VOID MACRO_KLink(LPCSTR, LONG, LPCSTR, LPCSTR);
+VOID MACRO_Menu(VOID);
+VOID MACRO_MPrintHash(LONG);
+VOID MACRO_MPrintID(LPCSTR);
+VOID MACRO_Next(VOID);
+VOID MACRO_NoShow(VOID);
+VOID MACRO_PopupContext(LPCSTR, LONG);
+VOID MACRO_PopupHash(LPCSTR, LONG);
+VOID MACRO_PopupId(LPCSTR, LPCSTR);
+VOID MACRO_PositionWindow(LONG, LONG, LONG, LONG, LONG, LPCSTR);
+VOID MACRO_Prev(VOID);
+VOID MACRO_Print(VOID);
+VOID MACRO_PrinterSetup(VOID);
+VOID MACRO_RegisterRoutine(LPCSTR, LPCSTR, LPCSTR);
+VOID MACRO_RemoveAccelerator(LONG, LONG);
+VOID MACRO_ResetMenu(VOID);
+VOID MACRO_SaveMark(LPCSTR);
+VOID MACRO_Search(VOID);
+VOID MACRO_SetContents(LPCSTR, LONG);
+VOID MACRO_SetHelpOnFile(LPCSTR);
+VOID MACRO_SetPopupColor(LONG, LONG, LONG);
+VOID MACRO_ShellExecute(LPCSTR, LPCSTR, LONG, LONG, LPCSTR, LPCSTR);
+VOID MACRO_ShortCut(LPCSTR, LPCSTR, WPARAM, LPARAM, LPCSTR);
+VOID MACRO_TCard(LONG);
+VOID MACRO_Test(LONG);
+BOOL MACRO_TestALink(LPCSTR);
+BOOL MACRO_TestKLink(LPCSTR);
+VOID MACRO_UncheckItem(LPCSTR);
+VOID MACRO_UpdateWindow(LPCSTR, LPCSTR);
+
+/* Local Variables: */
+/* c-file-style: "GNU" */
+/* End: */
diff --git a/programs/winhelp/macro.lex.l b/programs/winhelp/macro.lex.l
new file mode 100644
index 0000000..146c8ea
--- /dev/null
+++ b/programs/winhelp/macro.lex.l
@@ -0,0 +1,235 @@
+%{
+/*
+ * Help Viewer
+ *
+ * Copyright 1996 Ulrich Schmid
+ */
+%}
+%x quote dquote
+%x null_string
+%{
+#include "macro.h"
+#include "y.tab.h"
+
+static LPCSTR macroptr, firsttoken, thistoken, nexttoken, current_string;
+static LPSTR strptr;
+static HGLOBAL hStringBuffer = 0;
+
+CHAR MACRO_extra_separator = 0;
+
+#define YY_INPUT(buf,result,max_size)\
+ if ((result = *macroptr ? 1 : 0)) buf[0] = *macroptr++;
+
+#define YY_USER_ACTION\
+ if (YY_START == INITIAL) thistoken = nexttoken, nexttoken = macroptr;
+
+#define YY_NO_UNPUT
+#define YY_NO_TOP_STATE
+%}
+%%
+About yylval = MACRO_About; return VOID_FUNCTION_VOID;
+AddAccelerator|AA yylval = MACRO_AddAccelerator; return VOID_FUNCTION_2UINT_STRING;
+ALink|AL yylval = MACRO_ALink; return VOID_FUNCTION_STRING_UINT_STRING;
+Annotate yylval = MACRO_Annotate; return VOID_FUNCTION_VOID;
+AppendItem yylval = MACRO_AppendItem; return VOID_FUNCTION_4STRING;
+Back yylval = MACRO_Back; return VOID_FUNCTION_VOID;
+BackFlush|BF yylval = MACRO_BackFlush; return VOID_FUNCTION_VOID;
+BookmarkDefine yylval = MACRO_BookmarkDefine; return VOID_FUNCTION_VOID;
+BookmarkMore yylval = MACRO_BookmarkMore; return VOID_FUNCTION_VOID;
+BrowseButtons yylval = MACRO_BrowseButtons; return VOID_FUNCTION_VOID;
+ChangeButtonBinding|CBB yylval = MACRO_ChangeButtonBinding; return VOID_FUNCTION_2STRING;
+ChangeEnable|CE yylval = MACRO_ChangeEnable; return VOID_FUNCTION_2STRING;
+ChangeItemBinding|CIB yylval = MACRO_ChangeItemBinding; return VOID_FUNCTION_2STRING;
+CheckItem|CI yylval = MACRO_CheckItem; return VOID_FUNCTION_STRING;
+CloseSecondarys|CS yylval = MACRO_CloseSecondarys; return VOID_FUNCTION_VOID;
+CloseWindow|CW yylval = MACRO_CloseWindow; return VOID_FUNCTION_STRING;
+Compare yylval = MACRO_Compare; return VOID_FUNCTION_STRING;
+Contents yylval = MACRO_Contents; return VOID_FUNCTION_VOID;
+ControlPanel yylval = MACRO_ControlPanel; return VOID_FUNCTION_2STRING_UINT;
+CopyDialog yylval = MACRO_CopyDialog; return VOID_FUNCTION_VOID;
+CopyTopic|CT yylval = MACRO_CopyTopic; return VOID_FUNCTION_VOID;
+CreateButton|CB yylval = MACRO_CreateButton; return VOID_FUNCTION_3STRING;
+DeleteItem yylval = MACRO_DeleteItem; return VOID_FUNCTION_STRING;
+DeleteMark yylval = MACRO_DeleteMark; return VOID_FUNCTION_STRING;
+DestroyButton yylval = MACRO_DestroyButton; return VOID_FUNCTION_STRING;
+DisableButton|DB yylval = MACRO_DisableButton; return VOID_FUNCTION_STRING;
+DisableItem|DI yylval = MACRO_DisableItem; return VOID_FUNCTION_STRING;
+EnableButton|EB yylval = MACRO_EnableButton; return VOID_FUNCTION_STRING;
+EnableItem|EI yylval = MACRO_EnableItem; return VOID_FUNCTION_STRING;
+EndMPrint yylval = MACRO_EndMPrint; return VOID_FUNCTION_VOID;
+ExecFile|EF yylval = MACRO_ExecFile; return VOID_FUNCTION_2STRING_UINT_STRING;
+ExecProgram|EP yylval = MACRO_ExecProgram; return VOID_FUNCTION_STRING_UINT;
+Exit yylval = MACRO_Exit; return VOID_FUNCTION_VOID;
+ExtAbleItem yylval = MACRO_ExtAbleItem; return VOID_FUNCTION_STRING_UINT;
+ExtInsertItem yylval = MACRO_ExtInsertItem; return VOID_FUNCTION_4STRING_2UINT;
+ExtInsertMenu yylval = MACRO_ExtInsertMenu; return VOID_FUNCTION_3STRING_2UINT;
+FileExist|FE yylval = MACRO_FileExist; return BOOL_FUNCTION_STRING;
+FileOpen|FO yylval = MACRO_FileOpen; return VOID_FUNCTION_VOID;
+Find yylval = MACRO_Find; return VOID_FUNCTION_VOID;
+Finder|FD yylval = MACRO_Finder; return VOID_FUNCTION_VOID;
+FloatingMenu yylval = MACRO_FloatingMenu; return VOID_FUNCTION_VOID;
+Flush|FH yylval = MACRO_Flush; return VOID_FUNCTION_VOID;
+FocusWindow yylval = MACRO_FocusWindow; return VOID_FUNCTION_STRING;
+Generate yylval = MACRO_Generate; return VOID_FUNCTION_STRING_WPARAM_LPARAM;
+GotoMark yylval = MACRO_GotoMark; return VOID_FUNCTION_STRING;
+HelpOn yylval = MACRO_HelpOn; return VOID_FUNCTION_VOID;
+HelpOnTop yylval = MACRO_HelpOnTop; return VOID_FUNCTION_VOID;
+History yylval = MACRO_History; return VOID_FUNCTION_VOID;
+IfThen|IF return IF_THEN;
+IfThenElse|IE return IF_THEN_ELSE;
+InitMPrint yylval = MACRO_InitMPrint; return BOOL_FUNCTION_VOID;
+InsertItem yylval = MACRO_InsertItem; return VOID_FUNCTION_4STRING_UINT;
+InsertMenu yylval = MACRO_InsertMenu; return VOID_FUNCTION_2STRING_UINT;
+IsBook yylval = MACRO_IsBook; return BOOL_FUNCTION_VOID;
+IsMark yylval = MACRO_IsMark; return BOOL_FUNCTION_STRING;
+IsNotMark|NM yylval = MACRO_IsNotMark; return BOOL_FUNCTION_STRING;
+JumpContents yylval = MACRO_JumpContents; return VOID_FUNCTION_FILE_WIN;
+JumpContext|JC yylval = MACRO_JumpContext; return VOID_FUNCTION_FILE_WIN_UINT;
+JumpHash|JH yylval = MACRO_JumpHash; return VOID_FUNCTION_FILE_WIN_UINT;
+JumpHelpOn yylval = MACRO_JumpHelpOn; return VOID_FUNCTION_VOID;
+JumpID|JI yylval = MACRO_JumpID; return VOID_FUNCTION_FILE_WIN_STRING;
+JumpKeyword|JK yylval = MACRO_JumpKeyword; return VOID_FUNCTION_FILE_WIN_STRING;
+KLink|KL yylval = MACRO_KLink; return VOID_FUNCTION_STRING_UINT_2STRING;
+Menu|MU yylval = MACRO_Menu; return VOID_FUNCTION_VOID;
+MPrintHash yylval = MACRO_MPrintHash; return VOID_FUNCTION_UINT;
+MPrintID yylval = MACRO_MPrintID; return VOID_FUNCTION_STRING;
+Next yylval = MACRO_Next; return VOID_FUNCTION_VOID;
+NoShow yylval = MACRO_NoShow; return VOID_FUNCTION_VOID;
+Not return NOT;
+PopupContext|PC yylval = MACRO_PopupContext; return VOID_FUNCTION_STRING_UINT;
+PopupHash yylval = MACRO_PopupHash; return VOID_FUNCTION_STRING_UINT;
+PopupId|PI yylval = MACRO_PopupId; return VOID_FUNCTION_2STRING;
+PositionWindow|PW yylval = MACRO_PositionWindow; return VOID_FUNCTION_2INT_3UINT_STRING;
+Prev yylval = MACRO_Prev; return VOID_FUNCTION_VOID;
+Print yylval = MACRO_Print; return VOID_FUNCTION_VOID;
+PrinterSetup yylval = MACRO_PrinterSetup; return VOID_FUNCTION_VOID;
+RegisterRoutine|RR yylval = MACRO_RegisterRoutine; return VOID_FUNCTION_3STRING;
+RemoveAccelerator|RA yylval = MACRO_RemoveAccelerator; return VOID_FUNCTION_2UINT;
+ResetMenu yylval = MACRO_ResetMenu; return VOID_FUNCTION_VOID;
+SaveMark yylval = MACRO_SaveMark; return VOID_FUNCTION_STRING;
+Search yylval = MACRO_Search; return VOID_FUNCTION_VOID;
+SetContents yylval = MACRO_SetContents; return VOID_FUNCTION_STRING_UINT;
+SetHelpOnFile yylval = MACRO_SetHelpOnFile; return VOID_FUNCTION_STRING;
+SetPopupColor|SPC yylval = MACRO_SetPopupColor; return VOID_FUNCTION_3UINT;
+ShellExecute|SE yylval = MACRO_ShellExecute; return VOID_FUNCTION_2STRING_2UINT_2STRING;
+ShortCut|SH yylval = MACRO_ShortCut; return VOID_FUNCTION_2STRING_WPARAM_LPARAM_STRING;
+TCard yylval = MACRO_TCard; return VOID_FUNCTION_UINT;
+Test yylval = MACRO_Test; return VOID_FUNCTION_UINT;
+TestALink yylval = MACRO_TestALink; return BOOL_FUNCTION_STRING;
+TestKLink yylval = MACRO_TestKLink; return BOOL_FUNCTION_STRING;
+UncheckItem|UI yylval = MACRO_UncheckItem; return VOID_FUNCTION_STRING;
+UpdateWindow|UW yylval = MACRO_UpdateWindow; return VOID_FUNCTION_2STRING;
+
+[-+]?[0-9]+ yylval.integer = strtol(yytext, NULL, 10); return INTEGER;
+[-+]?0[xX][0-9a-f]+ yylval.integer = strtol(yytext, NULL, 16); return INTEGER;
+
+\` |
+\" {
+ if (!hStringBuffer)
+ {
+ hStringBuffer = GlobalAlloc(GMEM_FIXED, strlen(macroptr));
+ strptr = GlobalLock(hStringBuffer);
+ }
+ current_string = strptr;
+ yy_push_state(yytext[0] == '`' ? quote : dquote);
+ }
+
+<quote>\` {
+ *strptr++ = yytext[0];
+ yy_push_state(quote);
+ }
+
+<quote>\' |
+<dquote>\" {
+ yy_pop_state();
+ if (YY_START == INITIAL)
+ {
+ *strptr++ = '\0';
+ if (MACRO_extra_separator)
+ {
+ yy_push_state(null_string);
+ MACRO_extra_separator = 0;
+ }
+ yylval = current_string;
+ return STRING;
+ }
+ else *strptr++ = yytext[0];
+ }
+
+<quote,dquote>{
+
+. {
+ if (MACRO_extra_separator == (CHAR) yytext[0])
+ {
+ *strptr++ = '\0';
+ MACRO_extra_separator = 0;
+ yylval = current_string;
+ current_string = strptr;
+ return STRING;
+ }
+ else *strptr++ = yytext[0];
+ }
+
+\\. *strptr++ = yytext[1];
+
+<<EOF>> return 0;
+}
+
+<null_string>"" {
+ yy_pop_state();
+ yylval = (LPCSTR) 0;
+ return STRING;
+ }
+
+" "
+
+. return yytext[0];
+%%
+#include "winhelp.h"
+static CHAR szTestMacro[256];
+
+static LRESULT MACRO_TestDialogProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ if (msg == WM_COMMAND && wParam == IDOK)
+ {
+ GetDlgItemText(hDlg, 99, szTestMacro, sizeof(szTestMacro));
+ EndDialog(hDlg, IDCANCEL);
+ return TRUE;
+ }
+ return FALSE;
+}
+
+VOID MACRO_ExecuteMacro(LPCSTR macro)
+{
+ static BOOL init = TRUE;
+
+ if (init) init = FALSE;
+ else
+ {
+ YY_FLUSH_BUFFER;
+ while (YY_START != INITIAL)
+ yy_pop_state();
+ }
+
+ if (!lstrcmpi(macro, "MacroTest"))
+ {
+ WNDPROC lpfnDlg = MakeProcInstance(MACRO_TestDialogProc, Globals.hInstance);
+ DialogBox(Globals.hInstance, STRING_DIALOG_TEST, Globals.active_win->hMainWnd, lpfnDlg);
+ FreeProcInstance(lpfnDlg);
+ macro = szTestMacro;
+ }
+
+ macroptr = firsttoken = thistoken = nexttoken = macro;
+
+ yyparse();
+
+ if (hStringBuffer) GlobalFree(hStringBuffer);
+ hStringBuffer = 0;
+}
+
+void yyerror (const char *s)
+{
+ fprintf(stderr, "%s\n%.*s\n%*s%s\n", s,
+ thistoken - firsttoken, firsttoken,
+ thistoken - firsttoken, "", thistoken);
+}
diff --git a/programs/winhelp/macro.yacc.y b/programs/winhelp/macro.yacc.y
new file mode 100644
index 0000000..66bce6e
--- /dev/null
+++ b/programs/winhelp/macro.yacc.y
@@ -0,0 +1,170 @@
+%{
+/*
+ * Help Viewer
+ *
+ * Copyright 1996 Ulrich Schmid
+ */
+
+#include "macro.h"
+static int skip = 0;
+%}
+%union
+ {
+ BOOL bool;
+ LPCSTR string;
+ LONG integer;
+ VOID (*void_function_void)(VOID);
+ BOOL (*bool_function_void)(VOID);
+ VOID (*void_function_string)(LPCSTR);
+ BOOL (*bool_function_string)(LPCSTR);
+
+ BOOL (*bool_funktion_string)(LPCSTR);
+ BOOL (*bool_funktion_void)(VOID);
+ VOID (*void_funktion_2int_3uint_string)(LONG,LONG,LONG,LONG,LONG,LPCSTR);
+ VOID (*void_funktion_2string)(LPCSTR,LPCSTR);
+ VOID (*void_funktion_2string_2uint_2string)(LPCSTR,LPCSTR,LONG,LONG,LPCSTR,LPCSTR);
+ VOID (*void_funktion_2string_uint)(LPCSTR,LPCSTR,LONG);
+ VOID (*void_funktion_2string_uint_string)(LPCSTR,LPCSTR,LONG,LPCSTR);
+ VOID (*void_funktion_2string_wparam_lparam_string)(LPCSTR,LPCSTR,WPARAM,LPARAM,LPCSTR);
+ VOID (*void_funktion_2uint)(LONG,LONG);
+ VOID (*void_funktion_2uint_string)(LONG,LONG,LPCSTR);
+ VOID (*void_funktion_3string)(LPCSTR,LPCSTR,LPCSTR);
+ VOID (*void_funktion_3string_2uint)(LPCSTR,LPCSTR,LPCSTR,LONG,LONG);
+ VOID (*void_funktion_3uint)(LONG,LONG,LONG);
+ VOID (*void_funktion_4string)(LPCSTR,LPCSTR,LPCSTR,LPCSTR);
+ VOID (*void_funktion_4string_2uint)(LPCSTR,LPCSTR,LPCSTR,LPCSTR,LONG,LONG);
+ VOID (*void_funktion_4string_uint)(LPCSTR,LPCSTR,LPCSTR,LPCSTR,LONG);
+ VOID (*void_funktion_string)(LPCSTR);
+ VOID (*void_funktion_string_uint)(LPCSTR,LONG);
+ VOID (*void_funktion_string_uint_2string)(LPCSTR,LONG,LPCSTR,LPCSTR);
+ VOID (*void_funktion_string_uint_string)(LPCSTR,LONG,LPCSTR);
+ VOID (*void_funktion_string_wparam_lparam)(LPCSTR,WPARAM,LPARAM);
+ VOID (*void_funktion_uint)(LONG);
+ VOID (*void_funktion_void)(VOID);
+ }
+%token NOT
+%token IF_THEN
+%token IF_THEN_ELSE
+%token <string> STRING
+%token <integer> INTEGER
+%token <bool_funktion_string> BOOL_FUNCTION_STRING
+%token <bool_funktion_void> BOOL_FUNCTION_VOID
+%token <void_funktion_2int_3uint_string> VOID_FUNCTION_2INT_3UINT_STRING
+%token <void_funktion_2string> VOID_FUNCTION_2STRING
+%token <void_funktion_2string_2uint_2string> VOID_FUNCTION_2STRING_2UINT_2STRING
+%token <void_funktion_2string_uint> VOID_FUNCTION_2STRING_UINT
+%token <void_funktion_2string_uint_string> VOID_FUNCTION_2STRING_UINT_STRING
+%token <void_funktion_2string_wparam_lparam_string> VOID_FUNCTION_2STRING_WPARAM_LPARAM_STRING
+%token <void_funktion_2uint> VOID_FUNCTION_2UINT
+%token <void_funktion_2uint_string> VOID_FUNCTION_2UINT_STRING
+%token <void_funktion_3string> VOID_FUNCTION_3STRING
+%token <void_funktion_3string_2uint> VOID_FUNCTION_3STRING_2UINT
+%token <void_funktion_3uint> VOID_FUNCTION_3UINT
+%token <void_funktion_4string> VOID_FUNCTION_4STRING
+%token <void_funktion_4string_2uint> VOID_FUNCTION_4STRING_2UINT
+%token <void_funktion_4string_uint> VOID_FUNCTION_4STRING_UINT
+%token <void_funktion_string> VOID_FUNCTION_STRING
+%token <void_funktion_string_uint> VOID_FUNCTION_STRING_UINT
+%token <void_funktion_string_uint_2string> VOID_FUNCTION_STRING_UINT_2STRING
+%token <void_funktion_string_uint_string> VOID_FUNCTION_STRING_UINT_STRING
+%token <void_funktion_string_wparam_lparam> VOID_FUNCTION_STRING_WPARAM_LPARAM
+%token <void_funktion_uint> VOID_FUNCTION_UINT
+%token <void_funktion_void> VOID_FUNCTION_VOID
+%token <void_funktion_2string> VOID_FUNCTION_FILE_WIN
+%token <void_funktion_3string> VOID_FUNCTION_FILE_WIN_STRING
+%token <void_funktion_2string_uint> VOID_FUNCTION_FILE_WIN_UINT
+%type <bool> bool_macro
+%type <string> filename
+%%
+
+macrostring: macro |
+ macro macrosep macrostring ;
+
+macrosep: ';' |
+ ':' ;
+
+macro: /* Empty */ |
+ IF_THEN '(' bool_macro ',' {if (! $3) skip++;}
+ macrostring ')' {if (! $3) skip--;} |
+ IF_THEN_ELSE '(' bool_macro ',' {if (! $3) skip++;}
+ macrostring ',' {if (! $3) skip--; else skip++;}
+ macrostring ')' {if ( $3) skip--;} |
+ VOID_FUNCTION_VOID
+ '(' ')'
+ {if (! skip) (*$1)();} |
+ VOID_FUNCTION_STRING
+ '(' STRING ')'
+ {if (! skip) (*$1)($3);} |
+ VOID_FUNCTION_2STRING
+ '(' STRING ',' STRING ')'
+ {if (! skip) (*$1)($3, $5);} |
+ VOID_FUNCTION_2STRING_UINT
+ '(' STRING ',' STRING ',' INTEGER ')'
+ {if (! skip) (*$1)($3, $5, $7);} |
+ VOID_FUNCTION_2STRING_UINT_STRING
+ '(' STRING ',' STRING ',' INTEGER ',' STRING ')'
+ {if (! skip) (*$1)($3, $5, $7, $9);} |
+ VOID_FUNCTION_2STRING_2UINT_2STRING
+ '(' STRING ',' STRING ',' INTEGER ',' INTEGER ',' STRING ',' STRING ')'
+ {if (! skip) (*$1)($3, $5, $7, $9, $11, $13);} |
+ VOID_FUNCTION_2STRING_WPARAM_LPARAM_STRING
+ '(' STRING ',' STRING ',' INTEGER ',' INTEGER ',' STRING ')'
+ {if (! skip) (*$1)($3, $5, $7, $9, $11);} |
+ VOID_FUNCTION_3STRING
+ '(' STRING ',' STRING ',' STRING ')'
+ {if (! skip) (*$1)($3, $5, $7);} |
+ VOID_FUNCTION_3STRING_2UINT
+ '(' STRING ',' STRING ',' STRING ',' INTEGER ',' INTEGER ')'
+ {if (! skip) (*$1)($3, $5, $7, $9, $11);} |
+ VOID_FUNCTION_4STRING
+ '(' STRING ',' STRING ',' STRING ',' STRING ')'
+ {if (! skip) (*$1)($3, $5, $7, $9);} |
+ VOID_FUNCTION_4STRING_UINT
+ '(' STRING ',' STRING ',' STRING ',' STRING ',' INTEGER')'
+ {if (! skip) (*$1)($3, $5, $7, $9, $11);} |
+ VOID_FUNCTION_4STRING_2UINT
+ '(' STRING ',' STRING ',' STRING ',' STRING ',' INTEGER ',' INTEGER')'
+ {if (! skip) (*$1)($3, $5, $7, $9, $11, $13);} |
+ VOID_FUNCTION_STRING_UINT
+ '(' STRING ',' INTEGER ')'
+ {if (! skip) (*$1)($3, $5);} |
+ VOID_FUNCTION_STRING_UINT_STRING
+ '(' STRING ',' INTEGER ',' STRING ')'
+ {if (! skip) (*$1)($3, $5, $7);} |
+ VOID_FUNCTION_STRING_UINT_2STRING
+ '(' STRING ',' INTEGER ',' STRING ',' STRING ')'
+ {if (! skip) (*$1)($3, $5, $7, $9);} |
+ VOID_FUNCTION_STRING_WPARAM_LPARAM
+ '(' STRING ',' INTEGER ',' INTEGER ')'
+ {if (! skip) (*$1)($3, $5, $7);} |
+ VOID_FUNCTION_UINT
+ '(' INTEGER ')'
+ {if (! skip) (*$1)($3);} |
+ VOID_FUNCTION_2UINT
+ '(' INTEGER ',' INTEGER ')'
+ {if (! skip) (*$1)($3, $5);} |
+ VOID_FUNCTION_2UINT_STRING
+ '(' INTEGER ',' INTEGER ',' STRING ')'
+ {if (! skip) (*$1)($3, $5, $7);} |
+ VOID_FUNCTION_3UINT
+ '(' INTEGER ',' INTEGER ',' INTEGER ')'
+ {if (! skip) (*$1)($3, $5, $7);} |
+ VOID_FUNCTION_2INT_3UINT_STRING
+ '(' INTEGER ',' INTEGER ',' INTEGER ',' INTEGER ',' INTEGER ',' STRING ')'
+ {if (! skip) (*$1)($3, $5, $7, $9, $11, $13);} |
+ VOID_FUNCTION_FILE_WIN
+ '(' filename STRING ')'
+ {if (! skip) (*$1)($3, $4);} |
+ VOID_FUNCTION_FILE_WIN_STRING
+ '(' filename STRING ',' STRING ')'
+ {if (! skip) (*$1)($3, $4, $6);} |
+ VOID_FUNCTION_FILE_WIN_UINT
+ '(' filename STRING ',' INTEGER ')'
+ {if (! skip) (*$1)($3, $4, $6);} ;
+
+filename: {MACRO_extra_separator = '>'} STRING {$$ = $2;} ;
+
+bool_macro: NOT '(' bool_macro ')' {$$ = ! $3;} |
+ STRING {$$ = MACRO_IsMark($1);} |
+ BOOL_FUNCTION_VOID '(' ')' {$$ = (*$1)();} |
+ BOOL_FUNCTION_STRING '(' STRING ')' {$$ = (*$1)($3);} ;
diff --git a/programs/winhelp/string.c b/programs/winhelp/string.c
new file mode 100644
index 0000000..647b968
--- /dev/null
+++ b/programs/winhelp/string.c
@@ -0,0 +1,25 @@
+/*
+ * Help Viewer
+ *
+ * Copyright 1996 Ulrich Schmid
+ */
+
+#include <windows.h>
+#include "winhelp.h"
+
+/* Class names */
+
+CHAR MAIN_WIN_CLASS_NAME[] = "WHMain";
+CHAR BUTTON_BOX_WIN_CLASS_NAME[] = "WHButtonBox";
+CHAR TEXT_WIN_CLASS_NAME[] = "WHText";
+CHAR SHADOW_WIN_CLASS_NAME[] = "WHShadow";
+CHAR STRING_BUTTON[] = "BUTTON";
+
+/* Resource names */
+/* Xx will be overwritten with En, ... */
+CHAR STRING_MENU_Xx[] = "MENU_Xx";
+CHAR STRING_DIALOG_TEST[] = "DIALOG_TEST";
+
+/* Local Variables: */
+/* c-file-style: "GNU" */
+/* End: */
diff --git a/programs/winhelp/winhelp.c b/programs/winhelp/winhelp.c
new file mode 100644
index 0000000..c7244b0
--- /dev/null
+++ b/programs/winhelp/winhelp.c
@@ -0,0 +1,1069 @@
+/*
+ * Help Viewer
+ *
+ * Copyright 1996 Ulrich Schmid <uschmid@mail.hh.provi.de>
+ */
+
+#include <stdio.h>
+#include <windows.h>
+#ifdef WINELIB
+#include <resource.h>
+#include <options.h>
+#include <shell.h>
+extern const char people[];
+#endif
+#include "winhelp.h"
+
+VOID LIBWINE_Register_De(void);
+VOID LIBWINE_Register_En(void);
+
+static BOOL WINHELP_RegisterWinClasses();
+static LRESULT WINHELP_MainWndProc(HWND, UINT, WPARAM, LPARAM);
+static LRESULT WINHELP_TextWndProc(HWND, UINT, WPARAM, LPARAM);
+static LRESULT WINHELP_ButtonBoxWndProc(HWND, UINT, WPARAM, LPARAM);
+static VOID WINHELP_CheckPopup(UINT);
+static BOOL WINHELP_SplitLines(HWND hWnd, LPSIZE);
+static VOID WINHELP_InitFonts(HWND hWnd);
+static VOID WINHELP_DeleteLines(WINHELP_WINDOW*);
+static VOID WINHELP_DeleteWindow(WINHELP_WINDOW*);
+static VOID WINHELP_SetupText(HWND hWnd);
+static BOOL WINHELP_AppendText(WINHELP_LINE***, WINHELP_LINE_PART***,
+ LPSIZE, LPSIZE, INT*, INT, LPCSTR, UINT,
+ HFONT, COLORREF, HLPFILE_LINK*);
+
+WINHELP_GLOBALS Globals = {3, 0, 0, 0, 0, 0};
+
+static BOOL MacroTest = FALSE;
+
+/***********************************************************************
+ *
+ * WinMain
+ */
+
+int PASCAL WinMain (HANDLE hInstance, HANDLE prev, LPSTR cmdline, int show)
+{
+ LPCSTR opt_lang = "En";
+ CHAR lang[3];
+ MSG msg;
+ LONG lHash = 0;
+ INT langnum;
+
+#if defined(WINELIB) && !defined(HAVE_WINE_CONSTRUCTOR)
+ /* Register resources */
+ LIBWINE_Register_De();
+ LIBWINE_Register_En();
+#endif
+
+ Globals.hInstance = hInstance;
+
+ /* Get options */
+ while (*cmdline && (*cmdline == ' ' || *cmdline == '-'))
+ {
+ CHAR option;
+ LPCSTR topic_id;
+ if (*cmdline++ == ' ') continue;
+
+ option = *cmdline;
+ if (option) cmdline++;
+ while (*cmdline && *cmdline == ' ') cmdline++;
+ switch(option)
+ {
+ case 'i':
+ case 'I':
+ topic_id = cmdline;
+ while (*cmdline && *cmdline != ' ') cmdline++;
+ if (*cmdline) *cmdline++ = '\0';
+ lHash = HLPFILE_Hash(topic_id);
+ break;
+
+ case '3':
+ case '4':
+ Globals.wVersion = option - '0';
+ break;
+
+ case 't':
+ MacroTest = TRUE;
+ break;
+ }
+ }
+
+#ifdef WINELIB
+ opt_lang = langNames[Options.language];
+#endif
+
+ /* Find language specific string table */
+ for (langnum = 0; langnum <= MAX_LANGUAGE_NUMBER; langnum++)
+ {
+ Globals.wStringTableOffset = langnum * 0x100;
+ if (LoadString(hInstance, IDS_LANGUAGE_ID, lang, sizeof(lang)) &&
+ !lstrcmp(opt_lang, lang))
+ break;
+ }
+ if (langnum > MAX_LANGUAGE_NUMBER)
+ {
+ /* Find fallback language */
+ for (langnum = 0; langnum <= MAX_LANGUAGE_NUMBER; langnum++)
+ {
+ Globals.wStringTableOffset = langnum * 0x100;
+ if (LoadString(hInstance, IDS_LANGUAGE_ID, lang, sizeof(lang)))
+ break;
+ }
+ if (langnum > MAX_LANGUAGE_NUMBER)
+ {
+ MessageBox(0, "No language found", "FATAL ERROR", MB_OK);
+ return(1);
+ }
+ }
+
+ /* Change Resource names */
+ lstrcpyn(STRING_MENU_Xx + lstrlen(STRING_MENU_Xx) - 2, lang, 3);
+
+ /* Create primary window */
+ WINHELP_RegisterWinClasses();
+ WINHELP_CreateHelpWindow(cmdline, lHash, "main", FALSE, NULL, NULL, show);
+
+ /* Message loop */
+ while (GetMessage (&msg, 0, 0, 0))
+ {
+ TranslateMessage (&msg);
+ DispatchMessage (&msg);
+ }
+ return 0;
+}
+
+/***********************************************************************
+ *
+ * RegisterWinClasses
+ */
+
+static BOOL WINHELP_RegisterWinClasses()
+{
+ WNDCLASS class_main, class_button_box, class_text, class_shadow;
+
+ class_main.style = CS_HREDRAW | CS_VREDRAW;
+ class_main.lpfnWndProc = WINHELP_MainWndProc;
+ class_main.cbClsExtra = 0;
+ class_main.cbWndExtra = sizeof(LONG);
+ class_main.hInstance = Globals.hInstance;
+ class_main.hIcon = LoadIcon (0, IDI_APPLICATION);
+ class_main.hCursor = LoadCursor (0, IDC_ARROW);
+ class_main.hbrBackground = GetStockObject (WHITE_BRUSH);
+ class_main.lpszMenuName = 0;
+ class_main.lpszClassName = MAIN_WIN_CLASS_NAME;
+
+ class_button_box = class_main;
+ class_button_box.lpfnWndProc = WINHELP_ButtonBoxWndProc;
+ class_button_box.hbrBackground = GetStockObject(GRAY_BRUSH);
+ class_button_box.lpszClassName = BUTTON_BOX_WIN_CLASS_NAME;
+
+ class_text = class_main;
+ class_text.lpfnWndProc = WINHELP_TextWndProc;
+ class_text.lpszClassName = TEXT_WIN_CLASS_NAME;
+
+ class_shadow = class_main;
+ class_shadow.lpfnWndProc = DefWindowProc;
+ class_shadow.hbrBackground = GetStockObject(GRAY_BRUSH);
+ class_shadow.lpszClassName = SHADOW_WIN_CLASS_NAME;
+
+ return (RegisterClass(&class_main) &&
+ RegisterClass(&class_button_box) &&
+ RegisterClass(&class_text) &&
+ RegisterClass(&class_shadow));
+}
+
+/***********************************************************************
+ *
+ * WINHELP_CreateHelpWindow
+ */
+
+VOID WINHELP_CreateHelpWindow(LPCSTR lpszFile, LONG lHash, LPCSTR lpszWindow,
+ BOOL bPopup, HWND hParentWnd, LPPOINT mouse, INT nCmdShow)
+{
+ CHAR szCaption[MAX_STRING_LEN];
+ CHAR szContents[MAX_STRING_LEN];
+ CHAR szSearch[MAX_STRING_LEN];
+ CHAR szBack[MAX_STRING_LEN];
+ CHAR szHistory[MAX_STRING_LEN];
+ SIZE size = {CW_USEDEFAULT, CW_USEDEFAULT};
+ POINT origin = {240, 0};
+ LPSTR ptr;
+ HGLOBAL handle;
+ WINHELP_WINDOW *win, *oldwin;
+ HLPFILE_PAGE *page;
+ HLPFILE_MACRO *macro;
+ HWND hWnd;
+ BOOL bPrimary;
+
+ if (bPopup)
+ lpszWindow = NULL;
+ else if (!lpszWindow)
+ lpszWindow = Globals.active_win->lpszName;
+ bPrimary = lpszWindow && !lstrcmpi(lpszWindow, "main");
+
+ /* Read help file */
+ if (lpszFile[0])
+ {
+ page = lHash ? HLPFILE_PageByHash(lpszFile, lHash) : HLPFILE_Contents(lpszFile);
+
+ /* Add Suffix `.hlp' */
+ if (!page && lstrcmpi(lpszFile + strlen(lpszFile) - 4, ".hlp"))
+ {
+ CHAR szFile_hlp[MAX_PATHNAME_LEN];
+
+ lstrcpyn(szFile_hlp, lpszFile, sizeof(szFile_hlp) - 4);
+ szFile_hlp[sizeof(szFile_hlp) - 5] = '\0';
+ lstrcat(szFile_hlp, ".hlp");
+
+ page = lHash ? HLPFILE_PageByHash(szFile_hlp, lHash) : HLPFILE_Contents(szFile_hlp);
+ if (!page)
+ {
+ WINHELP_MessageBoxIDS_s(IDS_HLPFILE_ERROR_s, lpszFile, IDS_ERROR, MB_OK);
+ if (Globals.win_list) return;
+ }
+ }
+ }
+ else page = 0;
+
+ /* Calculate horizontal size and position of a popup window */
+ if (bPopup)
+ {
+ RECT parent_rect;
+ GetWindowRect(hParentWnd, &parent_rect);
+ size.cx = (parent_rect.right - parent_rect.left) / 2;
+
+ origin = *mouse;
+ ClientToScreen(hParentWnd, &origin);
+ origin.x -= size.cx / 2;
+ origin.x = MIN(origin.x, GetSystemMetrics(SM_CXSCREEN) - size.cx);
+ origin.x = MAX(origin.x, 0);
+ }
+
+ /* Initialize WINHELP_WINDOW struct */
+ handle = GlobalAlloc(GMEM_FIXED, sizeof(WINHELP_WINDOW) +
+ (lpszWindow ? strlen(lpszWindow) + 1 : 0));
+ if (!handle) return;
+ win = GlobalLock(handle);
+ win->hSelf = handle;
+ win->next = Globals.win_list;
+ Globals.win_list = win;
+ if (lpszWindow)
+ {
+ ptr = GlobalLock(handle);
+ ptr += sizeof(WINHELP_WINDOW);
+ lstrcpy(ptr, (LPSTR) lpszWindow);
+ win->lpszName = ptr;
+ }
+ else win->lpszName = NULL;
+ win->page = page;
+ win->first_button = 0;
+ win->first_line = 0;
+ win->hMainWnd = 0;
+ win->hButtonBoxWnd = 0;
+ win->hTextWnd = 0;
+ win->hShadowWnd = 0;
+
+ Globals.active_win = win;
+
+ /* Initialize default pushbuttons */
+ if (MacroTest && !bPopup)
+ MACRO_CreateButton("BTN_TEST", "&Test", "MacroTest");
+ if (bPrimary && page)
+ {
+ LoadString(Globals.hInstance, IDS_CONTENTS, szContents, sizeof(szContents));
+ LoadString(Globals.hInstance, IDS_SEARCH, szSearch, sizeof(szSearch));
+ LoadString(Globals.hInstance, IDS_BACK, szBack, sizeof(szBack));
+ LoadString(Globals.hInstance, IDS_HISTORY, szHistory, sizeof(szHistory));
+ MACRO_CreateButton("BTN_CONTENTS", szContents, "Contents()");
+ MACRO_CreateButton("BTN_SEARCH", szSearch, "Search()");
+ MACRO_CreateButton("BTN_BACK", szBack, "Back()");
+ MACRO_CreateButton("BTN_HISTORY", szHistory, "History()");
+ }
+
+ /* Initialize file specific pushbuttons */
+ if (!bPopup && page)
+ for (macro = page->file->first_macro; macro; macro = macro->next)
+ MACRO_ExecuteMacro(macro->lpszMacro);
+
+ /* Reuse existing window */
+ if (lpszWindow)
+ for (oldwin = win->next; oldwin; oldwin = oldwin->next)
+ if (oldwin->lpszName && !lstrcmpi(oldwin->lpszName, lpszWindow))
+ {
+ WINHELP_BUTTON *button;
+
+ win->hMainWnd = oldwin->hMainWnd;
+ win->hButtonBoxWnd = oldwin->hButtonBoxWnd;
+ win->hTextWnd = oldwin->hTextWnd;
+ oldwin->hMainWnd = oldwin->hButtonBoxWnd = oldwin->hTextWnd = 0;
+
+ SetWindowLong(win->hMainWnd, 0, (LONG) win);
+ SetWindowLong(win->hButtonBoxWnd, 0, (LONG) win);
+ SetWindowLong(win->hTextWnd, 0, (LONG) win);
+
+ WINHELP_InitFonts(win->hMainWnd);
+
+ SetWindowText(win->hMainWnd, page->file->lpszTitle);
+
+ WINHELP_SetupText(win->hTextWnd);
+ InvalidateRect(win->hTextWnd, NULL, TRUE);
+ SendMessage(win->hMainWnd, WM_USER, 0, 0);
+ UpdateWindow(win->hTextWnd);
+
+
+ for (button = oldwin->first_button; button; button = button->next)
+ DestroyWindow(button->hWnd);
+
+ WINHELP_DeleteWindow(oldwin);
+ return;
+ }
+
+ /* Create main Window */
+ if (!page) LoadString(Globals.hInstance, IDS_WINE_HELP, szCaption, sizeof(szCaption));
+ hWnd = CreateWindow (bPopup ? TEXT_WIN_CLASS_NAME : MAIN_WIN_CLASS_NAME,
+ page ? (SEGPTR) page->file->lpszTitle : (SEGPTR) szCaption,
+ bPopup ? WS_POPUPWINDOW | WS_BORDER : WS_OVERLAPPEDWINDOW,
+ origin.x, origin.y, size.cx, size.cy,
+ 0, bPrimary ? LoadMenu(Globals.hInstance, STRING_MENU_Xx) : 0,
+ Globals.hInstance, (SEGPTR) win);
+
+ ShowWindow (hWnd, nCmdShow);
+ UpdateWindow (hWnd);
+}
+
+/***********************************************************************
+ *
+ * WINHELP_MainWndProc
+ */
+
+static LRESULT WINHELP_MainWndProc (HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ WINHELP_WINDOW *win;
+ WINHELP_BUTTON *button;
+ RECT rect, button_box_rect;
+ INT text_top;
+
+ WINHELP_CheckPopup(msg);
+
+ switch (msg)
+ {
+ case WM_NCCREATE:
+ win = (WINHELP_WINDOW*) ((LPCREATESTRUCT) lParam)->lpCreateParams;
+ SetWindowLong(hWnd, 0, (LONG) win);
+ win->hMainWnd = hWnd;
+ break;
+
+ case WM_CREATE:
+ win = (WINHELP_WINDOW*) GetWindowLong(hWnd, 0);
+
+ /* Create button box and text Window */
+ CreateWindow(BUTTON_BOX_WIN_CLASS_NAME, "", WS_CHILD | WS_VISIBLE,
+ 0, 0, 0, 0, hWnd, 0, Globals.hInstance, (SEGPTR) win);
+
+ CreateWindow(TEXT_WIN_CLASS_NAME, "", WS_CHILD | WS_VISIBLE,
+ 0, 0, 0, 0, hWnd, 0, Globals.hInstance, (SEGPTR) win);
+
+ /* Fall through */
+ case WM_USER:
+ case WM_WINDOWPOSCHANGED:
+ win = (WINHELP_WINDOW*) GetWindowLong(hWnd, 0);
+ GetClientRect(hWnd, &rect);
+
+ /* Update button box and text Window */
+ SetWindowPos(win->hButtonBoxWnd, HWND_TOP,
+ rect.left, rect.top,
+ rect.right - rect.left,
+ rect.bottom - rect.top, 0);
+
+ GetWindowRect(win->hButtonBoxWnd, &button_box_rect);
+ text_top = rect.top + button_box_rect.bottom - button_box_rect.top;
+
+ SetWindowPos(win->hTextWnd, HWND_TOP,
+ rect.left, text_top,
+ rect.right - rect.left,
+ rect.bottom - text_top, 0);
+
+ break;
+
+ case WM_COMMAND:
+ Globals.active_win = win = (WINHELP_WINDOW*) GetWindowLong(hWnd, 0);
+ switch (wParam)
+ {
+ /* Menu FILE */
+ case WH_OPEN: MACRO_FileOpen(); break;
+ case WH_PRINT: MACRO_Print(); break;
+ case WH_PRINTER_SETUP: MACRO_PrinterSetup(); break;
+ case WH_EXIT: MACRO_Exit(); break;
+
+ /* Menu EDIT */
+ case WH_COPY_DIALOG: MACRO_CopyDialog(); break;
+ case WH_ANNOTATE: MACRO_Annotate(); break;
+
+ /* Menu Bookmark */
+ case WH_BOOKMARK_DEFINE: MACRO_BookmarkDefine(); break;
+
+ /* Menu Help */
+ case WH_HELP_ON_HELP: MACRO_HelpOn(); break;
+ case WH_HELP_ON_TOP: MACRO_HelpOnTop(); break;
+
+ /* Menu Info */
+ case WH_ABOUT: MACRO_About(); break;
+#ifdef WINELIB
+ case WH_ABOUT_WINE:
+ ShellAbout(hWnd, "WINE", people, 0);
+ break;
+#endif
+
+ default:
+ /* Buttons */
+ for (button = win->first_button; button; button = button->next)
+ if (wParam == button->wParam) break;
+ if (button)
+ MACRO_ExecuteMacro(button->lpszMacro);
+ else
+ WINHELP_MessageBoxIDS(IDS_NOT_IMPLEMENTED, IDS_ERROR, MB_OK);
+ break;
+ }
+ break;
+ }
+
+ return DefWindowProc (hWnd, msg, wParam, lParam);
+}
+
+/***********************************************************************
+ *
+ * WINHELP_ButtonBoxWndProc
+ */
+
+static LRESULT WINHELP_ButtonBoxWndProc (HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ WINDOWPOS *winpos;
+ WINHELP_WINDOW *win;
+ WINHELP_BUTTON *button;
+ SIZE button_size;
+ INT x, y;
+
+ WINHELP_CheckPopup(msg);
+
+ switch(msg)
+ {
+ case WM_NCCREATE:
+ win = (WINHELP_WINDOW*) ((LPCREATESTRUCT) lParam)->lpCreateParams;
+ SetWindowLong(hWnd, 0, (LONG) win);
+ win->hButtonBoxWnd = hWnd;
+ break;
+
+ case WM_WINDOWPOSCHANGING:
+ winpos = (WINDOWPOS*) lParam;
+ win = (WINHELP_WINDOW*) GetWindowLong(hWnd, 0);
+
+ /* Update buttons */
+ button_size.cx = 0;
+ button_size.cy = 0;
+ for (button = win->first_button; button; button = button->next)
+ {
+ HDC hDc;
+ SIZE textsize;
+ if (!button->hWnd)
+ button->hWnd = CreateWindow(STRING_BUTTON, (LPSTR) button->lpszName,
+ WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON,
+ 0, 0, 0, 0,
+ hWnd, (HMENU) button->wParam,
+ Globals.hInstance, 0);
+ hDc = GetDC(button->hWnd);
+ GetTextExtentPoint(hDc, button->lpszName,
+ lstrlen(button->lpszName), &textsize);
+ ReleaseDC(button->hWnd, hDc);
+
+ button_size.cx = MAX(button_size.cx, textsize.cx + BUTTON_CX);
+ button_size.cy = MAX(button_size.cy, textsize.cy + BUTTON_CY);
+ }
+
+ x = 0;
+ y = 0;
+ for (button = win->first_button; button; button = button->next)
+ {
+ SetWindowPos(button->hWnd, HWND_TOP, x, y, button_size.cx, button_size.cy, 0);
+
+ if (x + 2 * button_size.cx <= winpos->cx)
+ x += button_size.cx;
+ else
+ x = 0, y += button_size.cy;
+ }
+ winpos->cy = y + (x ? button_size.cy : 0);
+ break;
+
+ case WM_COMMAND:
+ SendMessage(GetParent(hWnd), msg, wParam, lParam);
+ break;
+ }
+
+ return(DefWindowProc(hWnd, msg, wParam, lParam));
+}
+
+/***********************************************************************
+ *
+ * WINHELP_TextWndProc
+ */
+
+static LRESULT WINHELP_TextWndProc (HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ WINHELP_WINDOW *win;
+ WINHELP_LINE *line;
+ WINHELP_LINE_PART *part;
+ WINDOWPOS *winpos;
+ PAINTSTRUCT ps;
+ HDC hDc;
+ POINT mouse;
+ INT scroll_pos;
+ HWND hPopupWnd;
+ BOOL bExit;
+
+ if (msg != WM_LBUTTONDOWN)
+ WINHELP_CheckPopup(msg);
+
+ switch (msg)
+ {
+ case WM_NCCREATE:
+ win = (WINHELP_WINDOW*) ((LPCREATESTRUCT) lParam)->lpCreateParams;
+ SetWindowLong(hWnd, 0, (LONG) win);
+ win->hTextWnd = hWnd;
+ if (!win->lpszName) Globals.hPopupWnd = win->hMainWnd = hWnd;
+ WINHELP_InitFonts(hWnd);
+ break;
+
+ case WM_CREATE:
+ win = (WINHELP_WINDOW*) GetWindowLong(hWnd, 0);
+
+ /* Calculate vertical size and position of a popup window */
+ if (!win->lpszName)
+ {
+ POINT origin;
+ RECT old_window_rect;
+ RECT old_client_rect;
+ SIZE old_window_size;
+ SIZE old_client_size;
+ SIZE new_client_size;
+ SIZE new_window_size;
+
+ GetWindowRect(hWnd, &old_window_rect);
+ origin.x = old_window_rect.left;
+ origin.y = old_window_rect.top;
+ old_window_size.cx = old_window_rect.right - old_window_rect.left;
+ old_window_size.cy = old_window_rect.bottom - old_window_rect.top;
+
+ GetClientRect(hWnd, &old_client_rect);
+ old_client_size.cx = old_client_rect.right - old_client_rect.left;
+ old_client_size.cy = old_client_rect.bottom - old_client_rect.top;
+
+ new_client_size = old_client_size;
+ WINHELP_SplitLines(hWnd, &new_client_size);
+
+ if (origin.y + POPUP_YDISTANCE + new_client_size.cy <= GetSystemMetrics(SM_CYSCREEN))
+ origin.y += POPUP_YDISTANCE;
+ else
+ origin.y -= POPUP_YDISTANCE + new_client_size.cy;
+
+ new_window_size.cx = old_window_size.cx - old_client_size.cx + new_client_size.cx;
+ new_window_size.cy = old_window_size.cy - old_client_size.cy + new_client_size.cy;
+
+ win->hShadowWnd =
+ CreateWindow(SHADOW_WIN_CLASS_NAME, "", WS_POPUP | WS_VISIBLE,
+ origin.x + SHADOW_DX, origin.y + SHADOW_DY,
+ new_window_size.cx, new_window_size.cy,
+ 0, 0, Globals.hInstance, 0);
+
+ SetWindowPos(hWnd, HWND_TOP, origin.x, origin.y,
+ new_window_size.cx, new_window_size.cy,
+ SWP_NOZORDER | SWP_NOACTIVATE);
+ ShowWindow(win->hShadowWnd, SW_NORMAL);
+ }
+ break;
+
+ case WM_WINDOWPOSCHANGED:
+ winpos = (WINDOWPOS*) lParam;
+ if (!(winpos->flags & SWP_NOSIZE)) WINHELP_SetupText(hWnd);
+ break;
+
+ case WM_VSCROLL:
+ {
+ BOOL update = TRUE;
+ RECT rect;
+ INT Min, Max;
+ INT CurPos = GetScrollPos(hWnd, SB_VERT);
+ GetScrollRange(hWnd, SB_VERT, &Min, &Max);
+ GetClientRect(hWnd, &rect);
+
+ switch (wParam & 0xffff)
+ {
+ case SB_THUMBTRACK:
+ case SB_THUMBPOSITION: CurPos = wParam >> 16; break;
+ case SB_TOP: CurPos = Min; break;
+ case SB_BOTTOM: CurPos = Max; break;
+ case SB_PAGEUP: CurPos -= (rect.bottom - rect.top) / 2; break;
+ case SB_PAGEDOWN: CurPos += (rect.bottom - rect.top) / 2; break;
+ case SB_LINEUP: CurPos -= GetSystemMetrics(SM_CXVSCROLL); break;
+ case SB_LINEDOWN: CurPos += GetSystemMetrics(SM_CXVSCROLL); break;
+ default: update = FALSE;
+ }
+ if (update)
+ {
+ INT dy = GetScrollPos(hWnd, SB_VERT) - CurPos;
+ SetScrollPos(hWnd, SB_VERT, CurPos, TRUE);
+ ScrollWindow(hWnd, 0, dy, NULL, NULL);
+ UpdateWindow(hWnd);
+ }
+ }
+ break;
+
+ case WM_PAINT:
+ hDc = BeginPaint (hWnd, &ps);
+ win = (WINHELP_WINDOW*) GetWindowLong(hWnd, 0);
+ scroll_pos = GetScrollPos(hWnd, SB_VERT);
+
+ for (line = win->first_line; line; line = line->next)
+ for (part = &line->first_part; part; part = part->next)
+ {
+ SelectObject(hDc, part->hFont);
+ SetTextColor(hDc, part->color);
+ TextOut(hDc, part->rect.left, part->rect.top - scroll_pos,
+ (LPSTR) part->lpsText, part->wTextLen);
+ }
+
+ EndPaint (hWnd, &ps);
+ break;
+
+ case WM_LBUTTONDOWN:
+ win = (WINHELP_WINDOW*) GetWindowLong(hWnd, 0);
+ scroll_pos = GetScrollPos(hWnd, SB_VERT);
+
+ hPopupWnd = Globals.hPopupWnd;
+ Globals.hPopupWnd = 0;
+
+ mouse.x = LOWORD(lParam);
+ mouse.y = HIWORD(lParam);
+ for (line = win->first_line; line; line = line->next)
+ for (part = &line->first_part; part; part = part->next)
+ if (part->link.lpszPath &&
+ part->rect.left <= mouse.x &&
+ part->rect.right >= mouse.x &&
+ part->rect.top <= mouse.y + scroll_pos &&
+ part->rect.bottom >= mouse.y + scroll_pos)
+ WINHELP_CreateHelpWindow(part->link.lpszPath, part->link.lHash, NULL,
+ part->link.bPopup, hWnd, &mouse, SW_NORMAL);
+ if (hPopupWnd)
+ DestroyWindow(hPopupWnd);
+ break;
+
+ case WM_NCDESTROY:
+ win = (WINHELP_WINDOW*) GetWindowLong(hWnd, 0);
+
+ if (hWnd == Globals.hPopupWnd) Globals.hPopupWnd = 0;
+
+ bExit = (Globals.wVersion >= 4 && !lstrcmpi(win->lpszName, "main"));
+
+ WINHELP_DeleteWindow(win);
+
+ if (bExit) MACRO_Exit();
+
+ if (!Globals.win_list)
+ PostQuitMessage (0);
+ break;
+ }
+
+ return DefWindowProc (hWnd, msg, wParam, lParam);
+}
+
+/***********************************************************************
+ *
+ * SetupText
+ */
+
+static VOID WINHELP_SetupText(HWND hWnd)
+{
+ HDC hDc = GetDC(hWnd);
+ RECT rect;
+ SIZE newsize;
+
+ ShowScrollBar(hWnd, SB_VERT, FALSE);
+ if (!WINHELP_SplitLines(hWnd, NULL))
+ {
+ ShowScrollBar(hWnd, SB_VERT, TRUE);
+ GetClientRect(hWnd, &rect);
+
+ WINHELP_SplitLines(hWnd, &newsize);
+ SetScrollRange(hWnd, SB_VERT, 0, rect.top + newsize.cy - rect.bottom, TRUE);
+ }
+ else SetScrollPos(hWnd, SB_VERT, 0, FALSE);
+
+ ReleaseDC(hWnd, hDc);
+}
+
+/***********************************************************************
+ *
+ * WINHELP_SplitLines
+ */
+
+static BOOL WINHELP_SplitLines(HWND hWnd, LPSIZE newsize)
+{
+ WINHELP_WINDOW *win = (WINHELP_WINDOW*) GetWindowLong(hWnd, 0);
+ HLPFILE_PARAGRAPH *p;
+ WINHELP_LINE **line = &win->first_line;
+ WINHELP_LINE_PART **part = 0;
+ INT line_ascent = 0;
+ SIZE space;
+ RECT rect;
+ HDC hDc;
+
+ if (newsize) newsize->cx = newsize->cy = 0;
+
+ if (!win->page) return TRUE;
+
+ WINHELP_DeleteLines(win);
+
+ GetClientRect(hWnd, &rect);
+
+ rect.top += INTERNAL_BORDER_WIDTH;
+ rect.left += INTERNAL_BORDER_WIDTH;
+ rect.right -= INTERNAL_BORDER_WIDTH;
+ rect.bottom -= INTERNAL_BORDER_WIDTH;
+
+
+ space.cy = rect.top;
+ space.cx = rect.left;
+
+ hDc = GetDC(hWnd);
+
+ for (p = win->page->first_paragraph; p; p = p->next)
+ {
+ TEXTMETRIC tm;
+ SIZE textsize = {0, 0};
+ LPCSTR text = p->lpszText;
+ UINT len = strlen(text);
+ UINT indent = 0;
+
+ UINT wFont = (p->wFont < win->fonts_len) ? p->wFont : 0;
+ BOOL bUnderline = p->link && !p->link->bPopup;
+ HFONT hFont = win->fonts[wFont][bUnderline ? 1 : 0];
+
+ COLORREF color = RGB(0, 0, 0);
+ if (p->link) color = RGB(0, 0x80, 0);
+ if (p->bDebug) color = RGB(0xff, 0, 0);
+
+ SelectObject(hDc, hFont);
+
+ GetTextMetrics (hDc, &tm);
+
+ if (p->wIndent)
+ {
+ indent = p->wIndent * 5 * tm.tmAveCharWidth;
+ if (!part)
+ space.cx = rect.left + indent - 2 * tm.tmAveCharWidth;
+ }
+
+ if (p->wVSpace)
+ {
+ part = 0;
+ space.cx = rect.left + indent;
+ space.cy += (p->wVSpace - 1) * tm.tmHeight;
+ }
+
+ if (p->wHSpace)
+ {
+ space.cx += p->wHSpace * 2 * tm.tmAveCharWidth;
+ }
+
+ while (len)
+ {
+ INT free_width = rect.right - (part ? (*line)->rect.right : rect.left) - space.cx;
+ UINT low = 0, curr = len, high = len, textlen;
+
+ if (free_width > 0)
+ {
+ while (1)
+ {
+ GetTextExtentPoint(hDc, text, curr, &textsize);
+
+ if (textsize.cx <= free_width) low = curr;
+ else high = curr;
+
+ if (high <= low + 1) break;
+
+ if (textsize.cx) curr = (curr * free_width) / textsize.cx;
+ if (curr <= low) curr = low + 1;
+ else if (curr >= high) curr = high - 1;
+ }
+ textlen = low;
+ while (textlen && text[textlen] && text[textlen] != ' ') textlen--;
+ }
+ if (!part && !textlen) textlen = MAX(low, 1);
+
+ if (free_width <= 0 || !textlen)
+ {
+ part = 0;
+ space.cx = rect.left + indent;
+ space.cx = MIN(space.cx, rect.right - rect.left - 1);
+ continue;
+ }
+
+ if (!WINHELP_AppendText(&line, &part, &space, &textsize,
+ &line_ascent, tm.tmAscent,
+ text, textlen, hFont, color, p->link) ||
+ (!newsize && (*line)->rect.bottom > rect.bottom))
+ {
+ ReleaseDC(hWnd, hDc);
+ return FALSE;
+ }
+
+ if (newsize)
+ newsize->cx = MAX(newsize->cx, (*line)->rect.right + INTERNAL_BORDER_WIDTH);
+
+ len -= textlen;
+ text += textlen;
+ if (text[0] == ' ') text++, len--;
+ }
+ }
+
+ if (newsize)
+ newsize->cy = (*line)->rect.bottom + INTERNAL_BORDER_WIDTH;
+
+ ReleaseDC(hWnd, hDc);
+ return TRUE;
+}
+
+/***********************************************************************
+ *
+ * WINHELP_AppendText
+ */
+
+static BOOL WINHELP_AppendText(WINHELP_LINE ***linep, WINHELP_LINE_PART ***partp,
+ LPSIZE space, LPSIZE textsize,
+ INT *line_ascent, INT ascent,
+ LPCSTR text, UINT textlen,
+ HFONT font, COLORREF color, HLPFILE_LINK *link)
+{
+ HGLOBAL handle;
+ WINHELP_LINE *line;
+ WINHELP_LINE_PART *part;
+ LPSTR ptr;
+
+ if (!*partp) /* New line */
+ {
+ *line_ascent = ascent;
+
+ handle = GlobalAlloc(GMEM_FIXED, sizeof(WINHELP_LINE) + textlen +
+ (link ? lstrlen(link->lpszPath) + 1 : 0));
+ if (!handle) return FALSE;
+ line = GlobalLock(handle);
+ line->next = 0;
+ part = &line->first_part;
+ ptr = GlobalLock(handle);
+ ptr += sizeof(WINHELP_LINE);
+
+ line->rect.top = (**linep ? (**linep)->rect.bottom : 0) + space->cy;
+ line->rect.bottom = line->rect.top;
+ line->rect.left = space->cx;
+ line->rect.right = space->cx;
+
+ if (**linep) *linep = &(**linep)->next;
+ **linep = line;
+ space->cy = 0;
+ }
+ else /* Same line */
+ {
+ line = **linep;
+
+ if (*line_ascent < ascent)
+ {
+ WINHELP_LINE_PART *p;
+ for (p = &line->first_part; p; p = p->next)
+ {
+ p->rect.top += ascent - *line_ascent;
+ p->rect.bottom += ascent - *line_ascent;
+ }
+ line->rect.bottom += ascent - *line_ascent;
+ *line_ascent = ascent;
+ }
+
+ handle = GlobalAlloc(GMEM_FIXED, sizeof(WINHELP_LINE_PART) + textlen +
+ (link ? lstrlen(link->lpszPath) + 1 : 0));
+ if (!handle) return FALSE;
+ part = GlobalLock(handle);
+ **partp = part;
+ ptr = GlobalLock(handle);
+ ptr += sizeof(WINHELP_LINE_PART);
+ }
+
+ hmemcpy(ptr, text, textlen);
+ part->rect.left = line->rect.right + (*partp ? space->cx : 0);
+ part->rect.right = part->rect.left + textsize->cx;
+ line->rect.right = part->rect.right;
+ part->rect.top =
+ ((*partp) ? line->rect.top : line->rect.bottom) + *line_ascent - ascent;
+ part->rect.bottom = part->rect.top + textsize->cy;
+ line->rect.bottom = MAX(line->rect.bottom, part->rect.bottom);
+ part->hSelf = handle;
+ part->lpsText = ptr;
+ part->wTextLen = textlen;
+ part->hFont = font;
+ part->color = color;
+ if (link)
+ {
+ strcpy(ptr + textlen, link->lpszPath);
+ part->link.lpszPath = ptr + textlen;
+ part->link.lHash = link->lHash;
+ part->link.bPopup = link->bPopup;
+ }
+ else part->link.lpszPath = 0;
+
+ part->next = 0;
+ *partp = &part->next;
+
+ space->cx = 0;
+
+ return TRUE;
+}
+
+/***********************************************************************
+ *
+ * WINHELP_CheckPopup
+ */
+
+static VOID WINHELP_CheckPopup(UINT msg)
+{
+ if (!Globals.hPopupWnd) return;
+
+ switch (msg)
+ {
+ case WM_COMMAND:
+ case WM_LBUTTONDOWN:
+ case WM_MBUTTONDOWN:
+ case WM_RBUTTONDOWN:
+ case WM_NCLBUTTONDOWN:
+ case WM_NCMBUTTONDOWN:
+ case WM_NCRBUTTONDOWN:
+ DestroyWindow(Globals.hPopupWnd);
+ Globals.hPopupWnd = 0;
+ }
+}
+
+/***********************************************************************
+ *
+ * WINHELP_DeleteLines
+ */
+
+static VOID WINHELP_DeleteLines(WINHELP_WINDOW *win)
+{
+ WINHELP_LINE *line, *next_line;
+ WINHELP_LINE_PART *part, *next_part;
+ for(line = win->first_line; line; line = next_line)
+ {
+ next_line = line->next;
+ for(part = &line->first_part; part; part = next_part)
+ {
+ next_part = part->next;
+ GlobalFree(part->hSelf);
+ }
+ }
+ win->first_line = 0;
+}
+
+/***********************************************************************
+ *
+ * WINHELP_DeleteWindow
+ */
+
+static VOID WINHELP_DeleteWindow(WINHELP_WINDOW *win)
+{
+ WINHELP_WINDOW **w;
+
+ for (w = &Globals.win_list; *w; w = &(*w)->next)
+ if (*w == win)
+ {
+ *w = win->next;
+ break;
+ }
+
+ if (win->hShadowWnd) DestroyWindow(win->hShadowWnd);
+ HLPFILE_FreeHlpFilePage(win->page);
+ WINHELP_DeleteLines(win);
+ GlobalFree(win->hSelf);
+}
+
+/***********************************************************************
+ *
+ * WINHELP_InitFonts
+ */
+
+static VOID WINHELP_InitFonts(HWND hWnd)
+{
+ WINHELP_WINDOW *win = (WINHELP_WINDOW*) GetWindowLong(hWnd, 0);
+ LOGFONT logfontlist[] = {
+ {-10, 0, 0, 0, 400, 0, 0, 0, 0, 0, 0, 0, 32, "Helv"},
+ {-12, 0, 0, 0, 700, 0, 0, 0, 0, 0, 0, 0, 32, "Helv"},
+ {-12, 0, 0, 0, 700, 0, 0, 0, 0, 0, 0, 0, 32, "Helv"},
+ {-12, 0, 0, 0, 400, 0, 0, 0, 0, 0, 0, 0, 32, "Helv"},
+ {-12, 0, 0, 0, 700, 0, 0, 0, 0, 0, 0, 0, 32, "Helv"},
+ {-10, 0, 0, 0, 700, 0, 0, 0, 0, 0, 0, 0, 32, "Helv"},
+ { -8, 0, 0, 0, 400, 0, 0, 0, 0, 0, 0, 0, 32, "Helv"}};
+#define FONTS_LEN (sizeof(logfontlist)/sizeof(*logfontlist))
+
+ static HFONT fonts[FONTS_LEN][2];
+ static BOOL init = 0;
+
+ win->fonts_len = FONTS_LEN;
+ win->fonts = fonts;
+
+ if (!init)
+ {
+ INT i;
+
+ for(i = 0; i < FONTS_LEN; i++)
+ {
+ LOGFONT logfont = logfontlist[i];
+
+ fonts[i][0] = CreateFontIndirect(&logfont);
+ logfont.lfUnderline = 1;
+ fonts[i][1] = CreateFontIndirect(&logfont);
+ }
+
+ init = 1;
+ }
+}
+
+/***********************************************************************
+ *
+ * WINHELP_MessageBoxIDS
+ */
+
+INT WINHELP_MessageBoxIDS(UINT ids_text, UINT ids_title, WORD type)
+{
+ CHAR text[MAX_STRING_LEN];
+ CHAR title[MAX_STRING_LEN];
+
+ LoadString(Globals.hInstance, ids_text, text, sizeof(text));
+ LoadString(Globals.hInstance, ids_title, title, sizeof(title));
+
+ return(MessageBox(0, text, title, type));
+}
+
+/***********************************************************************
+ *
+ * MAIN_MessageBoxIDS_s
+ */
+
+INT WINHELP_MessageBoxIDS_s(UINT ids_text, LPCSTR str, UINT ids_title, WORD type)
+{
+ CHAR text[MAX_STRING_LEN];
+ CHAR title[MAX_STRING_LEN];
+ CHAR newtext[MAX_STRING_LEN + MAX_PATHNAME_LEN];
+
+ LoadString(Globals.hInstance, ids_text, text, sizeof(text));
+ LoadString(Globals.hInstance, ids_title, title, sizeof(title));
+ wsprintf(newtext, text, str);
+
+ return(MessageBox(0, newtext, title, type));
+}
+
+/* Local Variables: */
+/* c-file-style: "GNU" */
+/* End: */
diff --git a/programs/winhelp/winhelp.h b/programs/winhelp/winhelp.h
new file mode 100644
index 0000000..debf695
--- /dev/null
+++ b/programs/winhelp/winhelp.h
@@ -0,0 +1,156 @@
+/*
+ * Help Viewer
+ *
+ * Copyright 1996 Ulrich Schmid
+ */
+
+#define MAX_LANGUAGE_NUMBER 255
+#define MAX_PATHNAME_LEN 1024
+#define MAX_STRING_LEN 255
+
+#define INTERNAL_BORDER_WIDTH 5
+#define POPUP_YDISTANCE 20
+#define SHADOW_DX 20
+#define SHADOW_DY 20
+#define BUTTON_CX 6
+#define BUTTON_CY 6
+
+#ifndef RC_INVOKED
+
+#include "hlpfile.h"
+#include "macro.h"
+
+typedef struct tagHelpLinePart
+{
+ RECT rect;
+ LPCSTR lpsText;
+ UINT wTextLen;
+ HFONT hFont;
+ COLORREF color;
+
+ struct
+ {
+ LPCSTR lpszPath;
+ LONG lHash;
+ BOOL bPopup;
+ } link;
+
+ HGLOBAL hSelf;
+ struct tagHelpLinePart *next;
+} WINHELP_LINE_PART;
+
+typedef struct tagHelpLine
+{
+ RECT rect;
+ WINHELP_LINE_PART first_part;
+ struct tagHelpLine *next;
+} WINHELP_LINE;
+
+typedef struct tagHelpButton
+{
+ HWND hWnd;
+
+ LPCSTR lpszID;
+ LPCSTR lpszName;
+ LPCSTR lpszMacro;
+
+ WPARAM wParam;
+
+ RECT rect;
+
+ HGLOBAL hSelf;
+ struct tagHelpButton *next;
+} WINHELP_BUTTON;
+
+typedef struct tagWinHelp
+{
+ LPCSTR lpszName;
+
+ WINHELP_BUTTON *first_button;
+ HLPFILE_PAGE *page;
+ WINHELP_LINE *first_line;
+
+ HWND hMainWnd;
+ HWND hButtonBoxWnd;
+ HWND hTextWnd;
+ HWND hShadowWnd;
+
+ HFONT (*fonts)[2];
+ UINT fonts_len;
+
+ HGLOBAL hSelf;
+ struct tagWinHelp *next;
+} WINHELP_WINDOW;
+
+typedef struct
+{
+ UINT wVersion;
+ HANDLE hInstance;
+ HWND hPopupWnd;
+ UINT wStringTableOffset;
+ WINHELP_WINDOW *active_win;
+ WINHELP_WINDOW *win_list;
+} WINHELP_GLOBALS;
+
+extern WINHELP_GLOBALS Globals;
+
+VOID WINHELP_CreateHelpWindow(LPCSTR, LONG, LPCSTR, BOOL, HWND, LPPOINT, INT);
+INT WINHELP_MessageBoxIDS(UINT, UINT, WORD);
+INT WINHELP_MessageBoxIDS_s(UINT, LPCSTR, UINT, WORD);
+
+extern CHAR MAIN_WIN_CLASS_NAME[];
+extern CHAR BUTTON_BOX_WIN_CLASS_NAME[];
+extern CHAR TEXT_WIN_CLASS_NAME[];
+extern CHAR SHADOW_WIN_CLASS_NAME[];
+extern CHAR STRING_BUTTON[];
+extern CHAR STRING_MENU_Xx[];
+extern CHAR STRING_DIALOG_TEST[];
+
+#define STRINGID(id) (0x##id + Globals.wStringTableOffset)
+
+#else /* RC_INVOKED */
+
+#define STRINGID(id) id
+
+#endif
+
+/* Stringtable index */
+#define IDS_LANGUAGE_ID STRINGID(00)
+#define IDS_WINE_HELP STRINGID(01)
+#define IDS_ERROR STRINGID(02)
+#define IDS_WARNING STRINGID(03)
+#define IDS_INFO STRINGID(04)
+#define IDS_NOT_IMPLEMENTED STRINGID(05)
+#define IDS_HLPFILE_ERROR_s STRINGID(06)
+#define IDS_CONTENTS STRINGID(07)
+#define IDS_SEARCH STRINGID(08)
+#define IDS_BACK STRINGID(09)
+#define IDS_HISTORY STRINGID(0a)
+#define IDS_ALL_FILES STRINGID(0b)
+#define IDS_HELP_FILES_HLP STRINGID(0c)
+
+/* Menu `File' */
+#define WH_OPEN 11
+#define WH_PRINT 12
+#define WH_PRINTER_SETUP 13
+#define WH_EXIT 14
+
+/* Menu `Edit' */
+#define WH_COPY_DIALOG 21
+#define WH_ANNOTATE 22
+
+/* Menu `Bookmark' */
+#define WH_BOOKMARK_DEFINE 31
+
+/* Menu `Help' */
+#define WH_HELP_ON_HELP 41
+#define WH_HELP_ON_TOP 42
+#define WH_ABOUT 43
+#define WH_ABOUT_WINE 44
+
+/* Buttons */
+#define WH_FIRST_BUTTON 500
+
+/* Local Variables: */
+/* c-file-style: "GNU" */
+/* End: */