summaryrefslogtreecommitdiff
path: root/Build/source/texk/windvi/windvi.c
diff options
context:
space:
mode:
Diffstat (limited to 'Build/source/texk/windvi/windvi.c')
-rw-r--r--Build/source/texk/windvi/windvi.c3354
1 files changed, 3354 insertions, 0 deletions
diff --git a/Build/source/texk/windvi/windvi.c b/Build/source/texk/windvi/windvi.c
new file mode 100644
index 00000000000..eb5f7e2e2b6
--- /dev/null
+++ b/Build/source/texk/windvi/windvi.c
@@ -0,0 +1,3354 @@
+#include "wingui.h"
+
+/* C RunTime Header Files */
+#ifndef DEBUG_GUI
+#include <kpathsea/c-minmax.h>
+#endif
+
+
+LRESULT DispDefault(EDWP, HWND, UINT, WPARAM, LPARAM);
+
+/* Functions defined in winevt.c */
+#include <stdio.h>
+#include <setjmp.h>
+#include "xdvi-config.h"
+
+/*
+ System type
+*/
+int iSystemType = -1;
+
+int GetSystemType(void);
+
+/****************************************************************************
+ Global Variables
+ ***************************************************************************/
+
+HINSTANCE hInst; /* Current instance */
+char szAppName[100]; /* Name of the app */
+char szTitle[100]; /* The title bar text */
+HWND hWndMain; /* Application main window handle */
+HWND hWndDraw; /* The window with the dvi page */
+HWND hViewLog = NULL; /* Logging window */
+HDC maneDC; /* DC for the screen window */
+HBITMAP maneDIB; /* In memory bitmap for the dvi page */
+HBITMAP magDIB; /* In memory bitmap for the magnifying glass */
+HMENU hMenuMain; /* Main menu */
+
+char *szLogFileName; /* Temporary log file for kpathsea */
+HANDLE hCrtIn, hCrtOut, hCrtErr; /* Standard handles */
+/* hCrtOut and hCrtErr are the same handle, duplicated
+ from the writable part of a pipe.
+ */
+HANDLE hLogIn; /* One side of the pipe for logging */
+/*
+ Logging needs 2 threads :
+ - one sentinel for reading on the other (readable) end of the pipe
+ - one loop message for the hViewLog window.
+ With these threads, anybody writing on stdout/stderr will
+ make hViewLog pop up, and the writings will be displayed
+ almost synchronously.
+ */
+HANDLE hViewLogThread = 0,
+ hLogLoopThread = 0;
+BOOL bLogShown; /* Log window is shown */
+
+int tbHeight, sbHeight; /* Toolbar and Status bar heights */
+int maneHeight, maneWidth; /* hWndDraw height and width */
+RECT maneRect; /* hWndDraw Rect */
+RECT rectWndPrev; /* Previous instance window rectangle */
+BOOL bPrevInstance = FALSE; /* Is there a previous instance ? */
+BOOL bSkipFirstClick = FALSE; /* Avoid mag. glass at click to gain focus. */
+
+/* Scrollbars' variables */
+SCROLLINFO si;
+int xMinScroll;
+int xMaxScroll;
+int xCurrentScroll;
+int yMinScroll;
+int yMaxScroll;
+int yCurrentScroll;
+BOOL fScroll;
+BOOL fSize;
+
+BOOL bInitComplete = FALSE; /* Initialization phase completed */
+
+/* Mouse Position */
+int xMousePos;
+int yMousePos;
+
+/*
+ Last used files.
+ This is a queue. It is addressed in thae arry, indexes modulo number of
+ entries. Two values tell the head and tail of the queue.
+*/
+char **lpLastUsedFiles;
+int iLastUsedFilesNum;
+int iLastCurrentUsed, iLastLatestUsed;
+
+/*****************************************************************************
+ Main window message table definition.
+ ****************************************************************************/
+MSD rgmsd[] =
+{
+ {WM_CREATE, MsgCreate },
+ {WM_SIZE, MsgSize },
+ {WM_MOVE, MsgMove },
+ {WM_DROPFILES, MsgDropFiles },
+ {WM_COMMAND, MsgCommand },
+ {WM_NOTIFY, MsgNotify },
+ {WM_MENUSELECT, MsgMenuSelect},
+ {WM_DESTROY, MsgDestroy },
+ {WM_CHAR, MsgChar },
+ {WM_KEYDOWN, MsgKeyDown },
+ {WM_ACTIVATE, MsgActivate },
+ {WM_COPYDATA, MsgCopyData }
+ /* {WM_PAINT, MsgPaint } */
+};
+
+MSDI msdiMain =
+{
+ sizeof(rgmsd) / sizeof(MSD),
+ rgmsd,
+ edwpWindow
+};
+
+
+/* Main window command table definition. */
+CMD rgcmd[] =
+{
+ {IDM_FILEOPEN, CmdOpen},
+ {IDM_FILECLOSE, CmdClose},
+ {IDM_FILEPRINT, CmdFilePrint},
+ {IDM_FILEPRINTDVIPS, CmdFilePrint},
+ {IDM_FILEPAGESU, CmdStub},
+ {IDM_FILEPRINTSU, CmdFilePrSetup},
+ {IDM_EXIT, CmdExit},
+
+ {IDM_FILE_RECENT, CmdOpenRecentFile},
+ {IDM_FILE_RECENT1, CmdOpenRecentFile},
+ {IDM_FILE_RECENT2, CmdOpenRecentFile},
+ {IDM_FILE_RECENT3, CmdOpenRecentFile},
+ {IDM_FILE_RECENT4, CmdOpenRecentFile},
+ {IDM_FILE_RECENT5, CmdOpenRecentFile},
+ {IDM_FILE_RECENT6, CmdOpenRecentFile},
+ {IDM_FILE_RECENT7, CmdOpenRecentFile},
+ {IDM_FILE_RECENT8, CmdOpenRecentFile},
+ {IDM_FILE_RECENT9, CmdOpenRecentFile},
+
+ {IDM_ZOOMIN, CmdZoomIn},
+ {IDM_ZOOMOUT, CmdZoomOut},
+ {IDM_REDRAWPAGE, CmdRedrawPage},
+ {IDM_KEEPPOS, CmdKeepPosition},
+ {IDM_TOGGLEPS, CmdTogglePS},
+ {IDM_TOGGLEGRID, CmdToggleGrid},
+
+ {IDM_NEXTPAGE, CmdNextPage},
+ {IDM_PREVIOUSPAGE,CmdPreviousPage},
+ {IDM_NEXT5, CmdNext5},
+ {IDM_PREVIOUS5, CmdPrevious5},
+ {IDM_NEXT10, CmdNext10},
+ {IDM_PREVIOUS10, CmdPrevious10},
+ {IDM_GOTOPAGE, CmdGotoPage},
+ {IDM_SRCSPECIALS, CmdSrcSpecials},
+ {IDM_FIRSTPAGE, CmdFirstPage},
+ {IDM_LASTPAGE, CmdLastPage},
+
+#ifdef HTEX
+ {IDM_URLBACK, CmdUrlBack},
+#endif
+ {ID_OPTIONS_WINDVI, CmdWindviConfig},
+ {ID_OPTIONS_TEXCONFIG, CmdTexConfig},
+
+ {IDM_HELPTOPICS, CmdHelpTopics},
+ /* {IDM_HELPCONTENTS, CmdHelpContents}, */
+ /* {IDM_HELPSEARCH, CmdHelpSearch}, */
+ /* {IDM_HELPHELP, CmdHelpHelp}, */
+ {IDM_VIEW_LOG, CmdViewLog},
+ {IDM_ABOUT, CmdAbout},
+};
+
+CMDI cmdiMain =
+{
+ sizeof(rgcmd) / sizeof(CMD),
+ rgcmd,
+ edwpWindow
+};
+
+/*****************************************************************************
+ Toolbar window
+ ****************************************************************************/
+HWND hWndToolbar;
+
+int bVertToolbar = 0;
+/*
+**TODO** Change the following values to match your toolbar bitmap
+
+NUMIMAGES = Number of images in toolbar.bmp. Note that this is not
+the same as the number of elements on the toolbar.
+IMAGEWIDTH = Width of a single button image in toolbar.bmp
+IMAGEHEIGHT = Height of a single button image in toolbar.bmp
+BUTTONWIDTH = Width of a button on the toolbar (zero = default)
+BUTTONHEIGHT = Height of a button on the toolbar (zero = default)
+*/
+
+#define NUMIMAGES 17
+
+#define IMAGEWIDTH 18
+#define IMAGEHEIGHT 17
+#define BUTTONWIDTH 0
+#define BUTTONHEIGHT 0
+
+/*
+**TODO** Add/remove entries in the following array to define the
+toolbar buttons (see documentation for TBBUTTON).
+*/
+
+TBBUTTON tbButton[] =
+{
+ {0, IDM_FILEOPEN, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0},
+ {1, IDM_FILEPRINT, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0},
+ {0, 0, TBSTATE_ENABLED, TBSTYLE_SEP, 0, 0},
+ {2, IDM_ZOOMIN, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0},
+ {3, IDM_ZOOMOUT, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0},
+ {0, 0, TBSTATE_ENABLED, TBSTYLE_SEP, 0, 0},
+ {4, IDM_PREVIOUS10, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0},
+ {6, IDM_PREVIOUS5, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0},
+ {8, IDM_PREVIOUSPAGE, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0},
+ {11, IDM_REDRAWPAGE, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0},
+ {9, IDM_NEXTPAGE, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0},
+ {7, IDM_NEXT5, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0},
+ {5, IDM_NEXT10, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0},
+ {0, 0, TBSTATE_ENABLED, TBSTYLE_SEP, 0, 0},
+ {13,IDM_GOTOPAGE, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0},
+ {16,IDM_SRCSPECIALS,
+#ifdef SRC_SPECIALS
+ TBSTATE_ENABLED,
+#else
+ TBSTATE_HIDDEN,
+#endif
+ TBSTYLE_BUTTON | TBSTYLE_CHECK, 0, 0},
+ {0, 0, TBSTATE_ENABLED, TBSTYLE_SEP, 0, 0},
+ {10,IDM_TOGGLEGRID, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0},
+ {12,IDM_TOGGLEPS,
+#ifdef PS_GS
+ TBSTATE_ENABLED,
+#else
+ TBSTATE_HIDDEN,
+#endif
+ TBSTYLE_BUTTON | TBSTYLE_CHECK, 0, 0},
+ {15,IDM_BOOKMODE, TBSTATE_ENABLED, TBSTYLE_BUTTON | TBSTYLE_CHECK, 0, 0},
+ {0, 0, TBSTATE_ENABLED, TBSTYLE_SEP, 0, 0},
+ {14,IDM_URLBACK,
+#ifdef HTEX
+ TBSTATE_ENABLED,
+#else
+ TBSTATE_HIDDEN,
+#endif
+ TBSTYLE_BUTTON, 0, 0},
+};
+
+/****************************************************************************
+ Status Bar Window
+ ****************************************************************************/
+HWND hWndStatusbar;
+
+/* **TODO** Add entries to this array for each popup menu in the same
+ positions as they appear in the main menu. Remember to define
+ the ID's in globals.h and add the strings to windvi.rc. */
+
+UINT idPopup[] =
+{
+ IDS_FILEMENU,
+ IDS_MOVEMENU,
+ IDS_VIEWMENU,
+ IDS_HELPMENU,
+};
+
+/*
+ 6 -> 123,123
+ 5 -> Cursor Pos:
+ 4 -> 999
+ 3 -> Scaling:
+ 2 -> 999999
+ 1 -> Page:
+ */
+
+/*****************************************************************************/
+
+/*
+ FUNCTION: WinMain(HANDLE, HANDLE, LPSTR, int)
+
+ PURPOSE: Entry point for the application.
+
+ COMMENTS:
+
+ This function initializes the application and processes the
+ message loop.
+*/
+int APIENTRY WinMain(HINSTANCE hInstance,
+ HINSTANCE hPrevInstance,
+ LPSTR lpCmdLine,
+ int nCmdShow)
+{
+ MSG msg;
+ HANDLE hAccelTable;
+
+ /* Initialize global strings */
+ lstrcpy (szAppName, SZAPPNAME);
+ LoadString (hInstance, IDS_APPNAME, szTitle, 100);
+
+ /* Setup standard io, real-time logging ... */
+ SetupEnv();
+
+ /* are we nt, w9x ? */
+ iSystemType = GetSystemType();
+
+ /* Get all information from command line */
+ ParseCmdLine(GetCommandLine());
+
+ if (!hPrevInstance) {
+ /* Perform instance initialization: */
+ if (!InitApplication(hInstance)) {
+ CleanUp();
+ return (FALSE);
+ }
+ }
+
+ /* Perform application initialization: */
+ if (!InitInstance(hInstance, nCmdShow)) {
+ CleanUp();
+ return (FALSE);
+ }
+
+#if 0
+ hAccelTable = LoadAccelerators (hInstance, szAppName);
+#endif
+
+ bInitComplete = TRUE;
+ SetForegroundWindow(hWndMain);
+ /* Main message loop: */
+ while (GetMessage(&msg, NULL, 0, 0)) {
+#if 0
+ if (!TranslateAccelerator (msg.hwnd, hAccelTable, &msg)) {
+#endif
+ TranslateMessage(&msg);
+ DispatchMessage(&msg);
+#if 0
+ }
+#endif
+ }
+ CleanUp();
+#if 0
+ DestroyWindow(hWndMain);
+#endif
+ return (msg.wParam);
+}
+
+/*
+ FUNCTION: SetupEnv()
+ PURPOSE: initializing stdi, stdout, stderr, redirecting output to the
+ view log window in real-time.
+*/
+void SetupEnv()
+{
+ SECURITY_ATTRIBUTES sa = { sizeof(SECURITY_ATTRIBUTES), NULL, TRUE };
+ HANDLE current_pid, hTmpOut;
+ DWORD idLogThread;
+ FILE *hf;
+ int fdIn, fdOut, fdErr;
+ int i;
+ extern char tick_tmp[];
+
+ /* if _DEBUG is not defined, these macros will result in nothing. */
+ SETUP_CRTDBG;
+ /* Set the debug-heap flag so that freed blocks are kept on the
+ linked list, to catch any inadvertent use of freed memory */
+ /* SET_CRT_DEBUG_FIELD( _CRTDBG_DELAY_FREE_MEM_DF );
+ SET_CRT_DEBUG_FIELD( _CRTDBG_CHECK_ALWAYS_DF ); */
+
+#if 0
+ /* maybe we could still have an option to write log to some temp file ? */
+ szLogFileName = xmalloc(260);
+ if (GetTempFileName(szTempPath, "xdvi", 0, szLogFileName) == 0)
+ Win32Error("GetTempFileName");
+#endif
+
+ if (GetTempPath(PATH_MAX, tick_tmp) == 0)
+ Win32Error("GetTempPath/tick_tmp");
+
+ hCrtIn = CreateFile("NUL", GENERIC_READ, FILE_SHARE_READ,
+ &sa, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
+ if (SetStdHandle(STD_INPUT_HANDLE, hCrtIn) == FALSE)
+ Win32Error("SetStdHandle/hCrtIn");
+
+ if (CreatePipe(&hLogIn, &hTmpOut, &sa, 0) == FALSE) {
+ Win32Error("Init/CreatePipe");
+ }
+
+ current_pid = GetCurrentProcess();
+
+ if (DuplicateHandle(current_pid, hTmpOut,
+ current_pid, &hCrtOut,
+ 0, TRUE, DUPLICATE_SAME_ACCESS) == FALSE)
+ Win32Error("DuplicateHandle/OutErr");
+
+ if (DuplicateHandle(current_pid, hTmpOut,
+ current_pid, &hCrtErr,
+ 0, TRUE, DUPLICATE_SAME_ACCESS) == FALSE)
+ Win32Error("DuplicateHandle/OutErr");
+
+
+ CloseHandleAndClear(&hTmpOut);
+
+ if (SetStdHandle(STD_OUTPUT_HANDLE, hCrtOut) == FALSE)
+ Win32Error("SetStdHandle/hCrtOut");
+
+ if (SetStdHandle(STD_ERROR_HANDLE, hCrtErr) == FALSE)
+ Win32Error("SetStdHandle/hCrtErr");
+
+ fdIn = _open_osfhandle((long) hCrtIn,
+ // (long) GetStdHandle(STD_INPUT_HANDLE),
+ _O_TEXT
+ );
+ hf = _fdopen( fdIn, "r" );
+ *stdin = *hf;
+ i = setvbuf( stdin, NULL, _IONBF, 0 );
+
+ fdOut = _open_osfhandle((long) hCrtOut,
+ // (long) GetStdHandle(STD_OUTPUT_HANDLE),
+ _O_TEXT
+ );
+ hf = _fdopen( fdOut, "w" );
+ *stdout = *hf;
+ i = setvbuf( stdout, NULL, _IONBF, 0 );
+
+ fdErr = _open_osfhandle((long) hCrtErr,
+ // (long) GetStdHandle(STD_ERROR_HANDLE),
+ _O_TEXT
+ );
+ hf = _fdopen( fdErr, "w" );
+ *stderr = *hf;
+ i = setvbuf( stderr, NULL, _IONBF, 0 );
+
+ /* Run a thread for the ViewLog dialog box. The thread will
+ wait for something to read on hLogIn. */
+ if ((hViewLogThread = CreateThread(&sa, /* security attributes */
+ 0, /* default stack size */
+ ViewLogSentinel, /* start address of thread */
+ 0, /* parameter */
+ 0, /* creation flags */
+ &idLogThread /* thread id */
+ )) == NULL)
+ Win32Error("Log/CreateThread");
+#if 0
+ fprintf(stderr, "Setupenv done\n");
+#endif
+}
+
+/*
+ FUNCTION: InitApplication(HANDLE)
+
+ PURPOSE: Initializes window data and registers window class
+
+ COMMENTS:
+
+ In this function, we initialize a window class by filling out a data
+ structure of type WNDCLASS and calling either RegisterClass or
+ the internal MyRegisterClass.
+*/
+BOOL InitApplication(HINSTANCE hInstance)
+{
+ WNDCLASSEX wc;
+ HWND hWndPrev;
+ HANDLE hMutex;
+
+#if 0
+ /* Win32 will always set hPrevInstance to NULL, so lets check
+ things a little closer. This is because we only want a single
+ version of this app to run at a time */
+ hwnd = FindWindow (szAppName, szTitle);
+ if (hwnd) {
+ /* We found another version of ourself. Lets defer to it: */
+ if (IsIconic(hwnd)) {
+ ShowWindow(hwnd, SW_RESTORE);
+ }
+ SetForegroundWindow (hwnd);
+
+ /* If this app actually had any functionality, we would
+ also want to communicate any action that our 'twin'
+ should now perform based on how the user tried to
+ execute us. */
+ return FALSE;
+ }
+#endif
+
+ hWndPrev = FindWindow(szAppName, NULL);
+ if (hWndPrev) {
+ GetWindowRect(hWndPrev, &rectWndPrev);
+ bPrevInstance = TRUE;
+ }
+
+ /* hPrevInstance is always NULL under Win32. We have been asked to run only one instance
+ of windvi. Next instance will have to wake up the first one, and send it :
+ - at least new working directory and file name
+ - other params ? With the restriction that we cannot send pointers. */
+ if (resource.single_flag) {
+ COPYDATASTRUCT CopyData;
+ SECURITY_ATTRIBUTES sa = { sizeof(SECURITY_ATTRIBUTES), NULL, TRUE };
+ struct data_exchange DataEx;
+
+ /* We create a mutex to be sure to be alone, but only if the option
+ single_instance has been given. */
+
+ if ((hMutex = CreateMutex(&sa, TRUE, "WindviMutex")) == NULL) {
+ Win32Error("WinMain/CreateMutex");
+ return FALSE;
+ }
+ if (GetLastError() == ERROR_ALREADY_EXISTS) {
+ /* send the right message to the existing instance */
+ if (!hWndPrev) {
+ MessageBox(hWndMain, "Can't find the previous instance.", NULL, MB_APPLMODAL | MB_ICONHAND | MB_OK);
+ return FALSE;
+ }
+ /* We found another version of ourself. Lets defer to it: */
+ if (IsIconic(hWndPrev)) {
+ ShowWindow(hWndPrev, SW_RESTORE);
+ }
+ if (!SetForegroundWindow(hWndPrev))
+ Win32Error("WinMain/SetForegroundWindow");
+ /* We send the data_exchange structure ! */
+ GetCurrentDirectory(sizeof(DataEx.cwd), DataEx.cwd);
+ lstrcpy(DataEx.dviname, dvi_name);
+
+ if (curr_page) {
+ current_page = (*curr_page ? atoi(curr_page) : 1) - 1;
+ }
+
+ DataEx.currentpage = current_page;
+ DataEx.shrinkfactor = mane.shrinkfactor;
+ CopyData.dwData = 0;
+ CopyData.cbData = sizeof(DataEx);
+ CopyData.lpData = &DataEx;
+ SendMessage(hWndPrev, WM_COPYDATA, (WPARAM)NULL, (LPARAM)&CopyData);
+ /* and exit */
+ return FALSE;
+ }
+ }
+
+
+ /* Fill in window class structure with parameters that describe
+ the main window. */
+ /* CS_OWNDC : un DC pour chaque fenêtre de la classe */
+ wc.cbSize = sizeof(WNDCLASSEX);
+ wc.lpszClassName = szAppName;
+ wc.hInstance = hInstance;
+ wc.lpfnWndProc = (WNDPROC)WndProc;
+ wc.hCursor = LoadCursor(NULL, IDC_ARROW);
+ wc.hIcon = LoadIcon (hInstance, MAKEINTRESOURCE(IDI_APPICON));
+ wc.lpszMenuName = szAppName;
+ wc.style = CS_OWNDC;
+ wc.cbClsExtra = 0;
+ wc.cbWndExtra = 0;
+ wc.hbrBackground = (HBRUSH) (COLOR_WINDOW+1);
+ wc.hIconSm = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_APPICON));
+ /* wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);*/
+
+
+ if (!RegisterClassEx(&wc)) {
+ /* Assume we are running on NT where RegisterClassEx() is
+ not implemented, so let's try calling RegisterClass(). */
+
+ if (!RegisterClass((LPWNDCLASS)&wc.style)) {
+ Win32Error("RegisterClassEx");
+ return FALSE;
+ }
+ }
+
+ wc.lpszClassName = "ClientDrawClass";
+ wc.hInstance = hInstance;
+ wc.lpfnWndProc = (WNDPROC)DrawProc;
+ wc.hCursor = NULL; /* Different cursors may be loaded */
+ wc.hIcon = LoadIcon (hInstance, MAKEINTRESOURCE(IDI_APPICON));
+ wc.lpszMenuName = NULL;
+ wc.hbrBackground = GetStockObject(LTGRAY_BRUSH);
+ wc.style = CS_OWNDC /* 0| CS_HREDRAW | CS_VREDRAW | CS_BYTEALIGNCLIENT */;
+ wc.cbClsExtra = 0;
+ wc.cbWndExtra = 0;
+ wc.hIcon = LoadIcon (hInstance, MAKEINTRESOURCE(IDI_APPICON));
+
+
+ if (!RegisterClassEx(&wc)) {
+ /* Assume we are running on NT where RegisterClassEx() is
+ not implemented, so let's try calling RegisterClass(). */
+
+ if (!RegisterClass((LPWNDCLASS)&wc.style)) {
+ Win32Error("RegisterClassEx");
+ return FALSE;
+ }
+ }
+
+ wc.lpszClassName = "MagnifyGlass";
+ wc.hInstance = hInstance;
+ wc.lpfnWndProc = (WNDPROC)MagnifyProc;
+ wc.hCursor = LoadCursor(NULL, IDC_ARROW);
+ wc.hIcon = LoadIcon (hInstance, MAKEINTRESOURCE(IDI_APPICON));
+ wc.lpszMenuName = NULL;
+ wc.hbrBackground = GetStockObject(LTGRAY_BRUSH);
+ wc.style = CS_OWNDC /* | CS_HREDRAW | CS_VREDRAW | CS_BYTEALIGNCLIENT */;
+ wc.cbClsExtra = 0;
+ wc.cbWndExtra = 0;
+ wc.hIcon = LoadIcon (hInstance, MAKEINTRESOURCE(IDI_APPICON));
+
+
+ if (!RegisterClassEx(&wc)) {
+ /* Assume we are running on NT where RegisterClassEx() is
+ not implemented, so let's try calling RegisterClass(). */
+
+ if (!RegisterClass((LPWNDCLASS)&wc.style)) {
+ Win32Error("RegisterClassEx");
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+}
+
+/*
+ FUNCTION: InitInstance(HANDLE, int)
+
+ PURPOSE: Saves instance handle and creates main window
+
+ COMMENTS:
+
+ In this function, we save the instance handle in a global variable and
+ create and display the main program window.
+ */
+BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
+{
+ extern void UpdateMainMenuUsedFiles(void);
+ hInst = hInstance; /* Store instance handle in our global variable */
+
+ magDIB = maneDIB = NULL;
+
+ /* Setup bswap function */
+ bswap = (check_386() ? bswap_c : bswap_asm);
+
+ /* setup units */
+ pixel_to_unit();
+
+#ifdef _TRACE
+ fprintf(stderr, "w = %d, h = %d\n", page_w, page_h);
+#endif
+
+ hCursWait = LoadCursor(NULL, IDC_WAIT);
+ hCursArrow = LoadCursor(NULL, IDC_ARROW);
+ hCursCross = LoadCursor(NULL, IDC_CROSS);
+/* BEGIN CHUNK xdvi.c 2 */
+#ifdef SRC_SPECIALS
+ hCursSrc = LoadCursor(NULL, IDC_IBEAM);
+#endif
+/* END CHUNK xdvi.c 2 */
+
+ hWndMain = CreateWindowEx(WS_EX_ACCEPTFILES, szAppName, szTitle,
+ WS_OVERLAPPEDWINDOW /*| WS_CLIPCHILDREN */,
+ CW_USEDEFAULT, 0, CW_USEDEFAULT, 0,
+ NULL, NULL, hInstance, NULL);
+
+ if (!hWndMain) {
+ Win32Error("CreateWindow");
+ return (FALSE);
+ }
+ if (!CreateTBar(hWndMain))
+ return FALSE;
+ if (!CreateSBar(hWndMain))
+ return FALSE;
+ if (!CreateDraw(hWndMain))
+ return FALSE;
+ if (!CreateMagnify(hWndDraw))
+ return FALSE;
+
+ hMenuMain = GetMenu(hWndMain);
+ CheckMenuItem(hMenuMain, IDM_TOGGLEPS, (resource._postscript ? MF_CHECKED : MF_UNCHECKED));
+ CheckMenuItem(hMenuMain, IDM_TOGGLEGRID, (resource._grid_mode ? MF_CHECKED : MF_UNCHECKED));
+ CheckMenuItem(hMenuMain, IDM_KEEPPOS, (resource.keep_flag ? MF_CHECKED : MF_UNCHECKED));
+
+ UpdateMainMenuUsedFiles();
+
+ ShowWindow(hWndMain, nCmdShow);
+ return (TRUE);
+}
+
+/*
+ FUNCTION: DispMessage(LPMSDI, HWND, UINT, WPARAM, LPARAM)
+
+ PURPOSE: Call the function associated with a message.
+
+ PARAMETERS:
+ lpmsdi - Structure containing the message dispatch information.
+ hwnd - The window handle
+ uMessage - The message number
+ wparam - Message specific data
+ lparam - Message specific data
+
+ RETURN VALUE:
+ The value returned by the message function that was called.
+
+ COMMENTS:
+ Runs the table of messages stored in lpmsdi->rgmsd searching
+ for a message number that matches uMessage. If a match is found,
+ call the associated function. Otherwise, call DispDefault to
+ call the default function, if any, associated with the message
+ structure. In either case, return the value recieved from the
+ message or default function.
+ */
+
+LRESULT DispMessage(LPMSDI lpmsdi,
+ HWND hwnd,
+ UINT uMessage,
+ WPARAM wparam,
+ LPARAM lparam)
+{
+ int imsd = 0;
+
+ MSD *rgmsd = lpmsdi->rgmsd;
+ int cmsd = lpmsdi->cmsd;
+
+ for (imsd = 0; imsd < cmsd; imsd++)
+ {
+ if (rgmsd[imsd].uMessage == uMessage)
+ return rgmsd[imsd].pfnmsg(hwnd, uMessage, wparam, lparam);
+ }
+
+ return DispDefault(lpmsdi->edwp, hwnd, uMessage, wparam, lparam);
+}
+
+/*
+ FUNCTION: DispCommand(LPCMDI, HWND, WPARAM, LPARAM)
+
+ PURPOSE: Call the function associated with a command.
+
+ PARAMETERS:
+ lpcmdi - Structure containing the command dispatch information.
+ hwnd - The window handle
+ GET_WM_COMMAND_ID(wparam, lparam) - Identifier of the menu item,
+ control, or accelerator.
+ GET_WM_COMMAND_CMD(wparam, lparam) - Notification code.
+ GET_WM_COMMAND_HWND(wparam, lparam) - The control handle or NULL.
+
+ RETURN VALUE:
+ The value returned by the command function that was called.
+
+ COMMENTS:
+ Runs the table of commands stored in lpcmdi->rgcmd searching
+ for a command number that matches wCommand. If a match is found,
+ call the associated function. Otherwise, call DispDefault to
+ call the default function, if any, associated with the command
+ structure. In either case, return the value recieved from the
+ command or default function.
+ */
+
+
+LRESULT DispCommand(LPCMDI lpcmdi,
+ HWND hwnd,
+ WPARAM wparam,
+ LPARAM lparam)
+{
+ LRESULT lRet = 0;
+ WORD wCommand = GET_WM_COMMAND_ID(wparam, lparam);
+ int icmd;
+
+ CMD *rgcmd = lpcmdi->rgcmd;
+ int ccmd = lpcmdi->ccmd;
+
+ /* Message packing of wparam and lparam have changed for Win32,
+ so use the GET_WM_COMMAND macro to unpack the commnad */
+
+ for (icmd = 0; icmd < ccmd; icmd++) {
+ if (rgcmd[icmd].wCommand == wCommand) {
+ return rgcmd[icmd].pfncmd(hwnd,
+ wCommand,
+ GET_WM_COMMAND_CMD(wparam, lparam),
+ GET_WM_COMMAND_HWND(wparam, lparam));
+ }
+ }
+
+ return DispDefault(lpcmdi->edwp, hwnd, WM_COMMAND, wparam, lparam);
+}
+
+
+
+/*
+ FUNCTION: DispDefault(EDWP, HWND, UINT, WPARAM, LPARAM)
+
+ PURPOSE: Call the appropriate default window procedure.
+
+ PARAMETERS:
+ edwp - Enumerate specifying the appropriate default winow procedure.
+ hwnd - The window handle
+ uMessage - The message number
+ wparam - Message specific data
+ lparam - Message specific data
+
+ RETURN VALUE:
+ If there is a default proc, return the value returned by the
+ default proc. Otherwise, return 0.
+
+ COMMENTS:
+ Calls the default procedure associated with edwp using the specified
+ parameters.
+ */
+
+LRESULT DispDefault(EDWP edwp,
+ HWND hwnd,
+ UINT uMessage,
+ WPARAM wparam,
+ LPARAM lparam)
+{
+ switch (edwp)
+ {
+ case edwpNone:
+ return 0;
+ case edwpWindow:
+ return DefWindowProc(hwnd, uMessage, wparam, lparam);
+ case edwpDialog:
+ return DefDlgProc(hwnd, uMessage, wparam, lparam);
+ case edwpMDIFrame:
+ return DefFrameProc(hwnd, NULL, uMessage, wparam, lparam);
+ case edwpMDIChild:
+ return DefMDIChildProc(hwnd, uMessage, wparam, lparam);
+ }
+ return 0;
+}
+
+/*****************************************************************************
+ Main Window messages
+ ****************************************************************************/
+
+/*
+ FUNCTION: WndProc(HWND, UINT, WPARAM, LPARAM)
+
+ PURPOSE: Processes messages for the main window.
+
+ PARAMETERS:
+ hwnd - window handle
+ uMessage - message number
+ wparam - additional information (dependant on message number)
+ lparam - additional information (dependant on message number)
+
+ RETURN VALUE:
+ The return value depends on the message number. If the message
+ is implemented in the message dispatch table, the return value is
+ the value returned by the message handling function. Otherwise,
+ the return value is the value returned by the default window procedure.
+
+ COMMENTS:
+ Call the DispMessage() function with the main window's message dispatch
+ information (msdiMain) and the message specific information.
+ */
+
+LRESULT CALLBACK WndProc(HWND hwnd,
+ UINT uMessage,
+ WPARAM wparam,
+ LPARAM lparam)
+{
+ return DispMessage(&msdiMain, hwnd, uMessage, wparam, lparam);
+}
+
+/*
+ FUNCTION: MsgCommand(HWND, UINT, WPARAM, LPARAM)
+
+ PURPOSE: Handle the WM_COMMAND messages for the main window.
+
+ PARAMETERS:
+ hwnd - window handle
+ uMessage - WM_COMMAND (Unused)
+ GET_WM_COMMAND_ID(wparam, lparam) - Command identifier
+ GET_WM_COMMAND_HWND(wparam, lparam) - Control handle
+
+ RETURN VALUE:
+ The return value depends on the message number. If the message
+ is implemented in the message dispatch table, the return value is
+ the value returned by the message handling function. Otherwise,
+ the return value is the value returned by the default window procedure.
+
+ COMMENTS:
+ Call the DispCommand() function with the main window's command dispatch
+ information (cmdiMain) and the command specific information.
+ */
+
+LRESULT MsgCommand(HWND hwnd, UINT uMessage, WPARAM wparam, LPARAM lparam)
+{
+ return DispCommand(&cmdiMain, hwnd, wparam, lparam);
+}
+
+
+/*
+ FUNCTION: MsgCreate(HWND, UINT, WPARAM, LPARAM)
+
+ PURPOSE: Handle the WM_CREATE messages for the main window.
+ and call InitCommonControls() API to initialize the
+ common control library.
+
+ PARAMETERS:
+ hwnd - window handle
+
+ RETURN VALUE:
+ Return 0 if the StatusBar and ToolBar Windows could be created
+ successfully. Otherwise, returns -1 to abort the main window
+ creation.
+
+ COMMENTS:
+ Call the CreateTSBars function with the main window's window handle
+ information (msdiMain).
+ */
+
+LRESULT MsgCreate(HWND hwnd, UINT uMessage, WPARAM wparam, LPARAM lparam)
+{
+ int nRet = -1;
+ FARPROC icce;
+
+ top_level = hwnd;
+
+ if (!(icce = GetProcAddress(GetModuleHandle("comctl32.dll"),
+ "InitCommonControlsEx"))) {
+#if 0
+ fprintf(stderr, "Not running the latest comctl32.dll\n");
+#endif
+ bVertToolbar = 0;
+ InitCommonControls() ; /* Initialize the common control library. */
+ }
+ else {
+ INITCOMMONCONTROLSEX icc = { sizeof(INITCOMMONCONTROLSEX),
+ ICC_BAR_CLASSES };
+ if ((*icce)(&icc) == FALSE)
+ Win32Error("InitCommonControlsEx");;
+ bVertToolbar = 1;
+ }
+
+ DragAcceptFiles(hwnd, TRUE);
+
+ return 0;
+}
+
+void UpdateGeometry()
+{
+ RECT r;
+ char buf[256];
+
+ /* Avoid updating when in iconic form */
+ if (IsIconic(hWndMain)) return;
+
+ /* Update the geometry string */
+ GetWindowRect(hWndMain, &r);
+
+ sprintf(buf, "%ux%u%+d%+d",
+ r.right - r.left,
+ r.bottom - r.top,
+ /* be safe, do not allow huge numbers */
+ (r.left < 0 ? 0 : r.left) % maneHorzRes,
+ (r.top < 0 ? 0 : r.top) % maneVertRes
+ );
+ if (geometry) free(geometry);
+ geometry = strdup(buf);
+}
+
+/*
+ FUNCTION: MsgSize(HWND, UINT, WPARAM, LPARAM)
+
+ PURPOSE: This function resizes the toolbar and statusbar controls.
+
+
+ PARAMETERS:
+
+ hwnd - Window handle (Used)
+ uMessage - Message number (Used)
+ wparam - Extra data (Used)
+ lparam - Extra data (Used)
+
+ RETURN VALUE:
+
+ Always returns 0 - Message handled
+
+ COMMENTS:
+
+ When the window procdure that has the status and tool bar controls
+ receive the WM_SIZE message, it has to pass the message on to these
+ controls so that these controls can adjust their size accordingly.
+ */
+
+
+LRESULT MsgSize(HWND hwnd, UINT uMessage, WPARAM wparam, LPARAM lparam)
+{
+ fSize = TRUE;
+
+ SendMessage(hWndStatusbar, uMessage, wparam, lparam);
+ SendMessage(hWndToolbar, uMessage, wparam, lparam);
+
+ /* Re-position the panes in the status bar */
+ InitializeStatusBar(hwnd);
+
+ /* Re-size client window relative to the tool/status bars */
+ if (wparam != SIZE_MINIMIZED)
+ SizeClientWindow(hwnd);
+
+ UpdateGeometry();
+
+ return 0;
+}
+/*
+ We need to update geometry in case of moving.
+ */
+LRESULT MsgMove(HWND hwnd, UINT uMessage, WPARAM wparam, LPARAM lparam)
+{
+ UpdateGeometry();
+ return 0;
+}
+
+void SetScrollBars(HWND hwnd)
+{
+ RECT r;
+
+ GetClientRect(hwnd, &r);
+
+ /* Scrollbars */
+ xMinScroll = 0;
+ xMaxScroll = max((unsigned)page_w, r.right) - 1;
+ /* mane.base_x = */xCurrentScroll = min(xCurrentScroll, xMaxScroll - max(r.right-1, 0));
+
+ si.cbSize = sizeof(si);
+ si.fMask = SIF_RANGE | SIF_PAGE | SIF_POS;
+ si.nMin = xMinScroll;
+ si.nMax = xMaxScroll;
+ si.nPage = r.right;
+ si.nPos = xCurrentScroll;
+ SetScrollInfo(hwnd, SB_HORZ, &si, TRUE);
+
+ yMinScroll = 0;
+ yMaxScroll = max((unsigned)page_h, r.bottom) - 1;
+ /* mane.base_y = */yCurrentScroll = min(yCurrentScroll, yMaxScroll - max(r.bottom-1, 0));
+
+ si.cbSize = sizeof(si);
+ si.fMask = SIF_RANGE | SIF_PAGE | SIF_POS;
+ si.nMin = yMinScroll;
+ si.nMax = yMaxScroll;
+ si.nPage = r.bottom;
+ si.nPos = yCurrentScroll;
+ SetScrollInfo(hwnd, SB_VERT, &si, TRUE);
+
+#ifdef _TRACE
+ fprintf(stderr, "Page %d x %d\nScrollbars to [%d, %d, %d] and [%d, %d, %d]\n",
+ r.right, r.bottom,
+ xMinScroll, xCurrentScroll, xMaxScroll,
+ yMinScroll, yCurrentScroll, yMaxScroll);
+#endif
+}
+
+void SizeClientWindow(HWND hwnd)
+{
+ int xNewSize, yNewSize;
+ POINT ptOldOrg;
+ int xorg, yorg;
+ RECT r;
+ int parentWidth, parentHeight;
+ /* Re-position the child window */
+
+ GetClientRect(hwnd, &r);
+ parentHeight = r.bottom;
+ parentWidth = r.right;
+ GetClientRect(hWndToolbar, &r);
+ tbHeight = r.bottom;
+ GetClientRect(hWndStatusbar, &r);
+ sbHeight = r.bottom;
+
+ maneRect.left = 0;
+ maneRect.right = parentWidth;
+ maneRect.top = 0;
+ maneRect.bottom = parentHeight - sbHeight -tbHeight - 1;
+
+ xNewSize = parentWidth;
+ yNewSize = parentHeight - sbHeight -tbHeight;
+
+ /* FIXME: try to SetWindowPos() instead */
+ SetWindowPos(hWndDraw, HWND_TOPMOST, 0, tbHeight+1,
+ xNewSize, yNewSize,
+ SWP_NOACTIVATE | SWP_DEFERERASE | SWP_SHOWWINDOW
+ | SWP_NOOWNERZORDER | SWP_NOZORDER);
+
+ GetClientRect(hWndDraw, &r);
+
+ maneWidth = r.right;
+ maneHeight = r.bottom;
+
+ SetScrollBars(hWndDraw);
+
+#if 1
+/* GdiFlush(); */
+/* UpdateWindow(hWndDraw); */
+ /* FIXME : adjust the position of the page */
+ if (maneDrawDC && hWndDraw && bInitComplete) {
+ GetWindowOrgEx(maneDrawDC, &ptOldOrg);
+ if (mane.win == hWndDraw && GetClientRect(hWndDraw, &maneRect)) {
+ int xorg = (int)(page_w - maneRect.right)/2;
+ int yorg = (int)(page_h - maneRect.bottom)/2;
+ xorg = min(0, xorg);
+ yorg = min(0, yorg);
+#if 0
+ fprintf(stderr, "Old org (%ld, %ld) New org (%ld, %ld) page %d %d rect %d %d\n",
+ ptOldOrg.x, ptOldOrg.y,
+ xorg, yorg, page_w, page_h, maneRect.right, maneRect.bottom);
+#endif
+ ScrollWindowEx(hWndDraw,
+ - xorg + ptOldOrg.x, - yorg + ptOldOrg.y,
+ NULL, NULL, (HRGN)NULL, (LPRECT)NULL,
+ SW_INVALIDATE | SW_ERASE);
+/* fprintf(stderr, "scrolled window by %d, %d\n", */
+/* - xorg + ptOldOrg.x, - yorg + ptOldOrg.y); */
+/* GdiFlush(); */
+/* UpdateWindow(hWndDraw); */
+ if (SetWindowOrgEx(maneDrawDC, xorg, yorg, NULL) == 0) {
+ Win32Error("MsgDrawPaint/SetWindowOrgEx(x,y)");
+ }
+/* fprintf(stderr, "Set new org @ (%ld, %ld)\n", xorg, yorg); */
+/* GdiFlush(); */
+/* UpdateWindow(hWndDraw); */
+ }
+ else {
+ Win32Error("MsgDrawPaint/GetClientRect(hwnd)");
+ }
+ }
+#endif
+}
+
+/*
+ FUNCTION: MsgDestroy(HWND, UINT, WPARAM, LPARAM)
+
+ PURPOSE: Calls PostQuitMessage().
+
+ PARAMETERS:
+
+ hwnd - Window handle (Unused)
+ uMessage - Message number (Unused)
+ wparam - Extra data (Unused)
+ lparam - Extra data (Unused)
+
+ RETURN VALUE:
+
+ Always returns 0 - Message handled
+
+ COMMENTS:
+ */
+
+
+LRESULT MsgDestroy(HWND hwnd, UINT uMessage, WPARAM wparam, LPARAM lparam)
+{
+ DragAcceptFiles(hwnd, FALSE);
+ SaveOptions();
+
+ PostQuitMessage(0);
+ return 0;
+}
+
+/*
+ FUNCTION: CmdExit(HWND, WORD, WORD, HWND)
+
+ PURPOSE: Exit the application.
+
+ PARAMETERS:
+ hwnd - The window.
+ wCommand - IDM_EXIT (unused)
+ wNotify - Notification number (unused)
+ hwndCtrl - NULL (unused)
+
+ RETURN VALUE:
+ Always returns 0 - command handled.
+
+ COMMENTS:
+ */
+
+
+LRESULT CmdExit(HWND hwnd, WORD wCommand, WORD wNotify, HWND hwndCtrl)
+{
+ DragAcceptFiles(hwnd, FALSE);
+ SaveOptions();
+
+ PostQuitMessage(0);
+ return 0;
+}
+
+/*
+ Status Bar functions
+ */
+
+LRESULT MsgDropFiles(HWND hwnd, UINT uMessage, WPARAM wparam, LPARAM lparam)
+{
+ WORD cFiles;
+ char lpszFile[MAX_PATH];
+
+ cFiles = DragQueryFile((HANDLE) wparam, 0xFFFFFFFF, (LPSTR) NULL, 0);
+ if (cFiles != 1) {
+ MessageBox(hWndMain, "Only one dvi file open.", NULL, MB_APPLMODAL | MB_ICONHAND | MB_OK);
+ }
+ DragQueryFile((HANDLE) wparam, 0, lpszFile, sizeof(lpszFile));
+ dvi_name = xstrdup(lpszFile);
+ DragFinish((HANDLE) wparam);
+
+ open_dvi_file();
+ if (reconfig() == FALSE) {
+ char buf[40];
+ mane.shrinkfactor +=3;
+ wsprintf(buf, "New shrink factor : %d\n", mane.shrinkfactor);
+ UpdateStatusBar(buf, 0, 0);
+ if (reconfig() == FALSE) {
+ MessageBox(hWndMain, "Can't allocate page bitmap !\r\nPlease report this error.", NULL, MB_APPLMODAL | MB_ICONERROR | MB_OK);
+ CleanExit(1);
+ }
+ }
+ redraw_page();
+ SetForegroundWindow(hwnd);
+
+ return 0;
+
+}
+#if 0
+/*
+ FUNCTION: MsgTimer(HWND, UINT, WPARAM, LPARAM)
+
+ PURPOSE: Calls GetLocalTime() to set the time on the status bar
+
+
+ PARAMETERS:
+
+ hwnd - Window handle (Unused)
+ uMessage - Message number (Unused)
+ wparam - Extra data (Unused)
+ lparam - Extra data (Unused)
+
+ RETURN VALUE:
+
+ Always returns 0 - Message handled
+
+ COMMENTS:
+
+ Every time the window procedure receives a Timer message, it calls
+ GetLocalTime() to obtain the time and then formats the time into
+ a string. The time sting is then displayed on the status bar.
+ */
+
+LRESULT MsgTimer(HWND hwnd, UINT uMessage, WPARAM wparam, LPARAM lparam)
+{
+ char szBuf[16]; /* Temp buffer. */
+ SYSTEMTIME sysTime;
+
+
+ GetLocalTime(&sysTime);
+
+ wsprintf(szBuf,
+ "%2d:%02d:%02d %s",
+ (sysTime.wHour == 0 ? 12 :
+ (sysTime.wHour <= 12 ? sysTime.wHour : sysTime.wHour -12)),
+ sysTime.wMinute,
+ sysTime.wSecond,
+ (sysTime.wHour < 12 ? "AM":"PM"));
+
+ UpdateStatusBar(szBuf, 8, 0);
+ return 0;
+}
+
+/*
+ FUNCTION: MsgMousemove(HWND, UINT, WPARAM, LPARAM)
+
+ PURPOSE: Obtains the Cursor position to display coordinates on
+ the status bar.
+
+ PARAMETERS:
+
+ hwnd - Window handle (Unused)
+ uMessage - Message number (Unused)
+ wparam - Extra data (Unused)
+ lparam - Extra data (Used)
+
+ RETURN VALUE:
+
+ Always returns 0 - Message handled
+
+ COMMENTS:
+
+ The mouse coordinates (x and y) are in the HI And LO words
+ of LPARAM
+ */
+
+
+LRESULT MsgMousemove(HWND hwnd, UINT uMessage, WPARAM wparam, LPARAM lparam)
+{
+ char szBuf[20]; /* Array for formatting mouse coordinates */
+
+ wsprintf(szBuf, "%d,%d", LOWORD(lparam), HIWORD(lparam));
+ UpdateStatusBar(szBuf, 6, 0);
+ return 0;
+}
+#endif
+
+/*
+ FUNCTION: MsgMenuSelect(HWND, UINT, WPARAM, LPARAM)
+
+ PURPOSE: Upadates menu selections on the status bar.
+
+
+ PARAMETERS:
+
+ hwnd - Window handle (Used)
+ uMessage - Message number (Used)
+ wparam - Extra data (Used)
+ lparam - Extra data (Used)
+
+ RETURN VALUE:
+
+ Always returns 0 - Message handled
+
+ COMMENTS:
+ This message is sent when the user selects menu items by
+ by pulling down a popup menu move the mouse around to highlite
+ different menu items.
+ */
+
+LRESULT MsgMenuSelect(HWND hwnd, UINT uMessage, WPARAM wparam, LPARAM lparam)
+{
+ static char szBuffer[128];
+ UINT nStringID = 0;
+ UINT fuFlags = GET_WM_MENUSELECT_FLAGS(wparam, lparam) & 0xffff;
+ UINT uCmd = GET_WM_MENUSELECT_CMD(wparam, lparam);
+ HMENU hMenu = GET_WM_MENUSELECT_HMENU(wparam, lparam);
+
+
+ szBuffer[0] = 0; /* First reset the buffer */
+
+
+ if (fuFlags == 0xffff && hMenu == NULL) /* Menu has been closed */
+ nStringID = IDS_DESCRIPTION;
+
+ else if (fuFlags & MFT_SEPARATOR) /* Ignore separators */
+ nStringID = 0;
+
+ else if (fuFlags & MF_POPUP) /* Popup menu */
+ {
+ if (fuFlags & MF_SYSMENU) /* System menu */
+ nStringID = IDS_SYSMENU;
+
+ else
+ /* Get string ID for popup menu from idPopup array. */
+ nStringID = ((uCmd < sizeof(idPopup)/sizeof(idPopup[0])) ?
+ idPopup[uCmd] : 0);
+ } /* for MF_POPUP */
+
+ else /* Must be a command item */
+ nStringID = uCmd; /* String ID == Command ID */
+
+ /* Load the string if we have an ID */
+ if (0 != nStringID)
+ LoadString(hInst, nStringID, szBuffer, sizeof(szBuffer));
+
+ /* Finally... send the string to the status bar */
+ UpdateStatusBar(szBuffer, 0, 0);
+
+ return 0;
+}
+
+
+/*
+ FUNCTION: InitializeStatusBar(HWND)
+
+ PURPOSE: Initialize statusbar control with time and mouse positions.
+
+
+ PARAMETERS:
+
+ hwndParent - Window handle of the status bar's parent
+
+
+ RETURN VALUE: NONE
+
+
+ COMMENTS:
+
+ This function initializes the time and mouse positions sections of
+ the statubar window. The Date for the time section is obtained by
+ calling SetTimer API. When the timer messages start comming in,
+ GetSytemTime() to fill the time section.
+ The WPARAM of SB_SETTEXT is divided into 2 parameters. The LOWORD
+ determines which section/part the text goes into, and the HIWORD
+ tells how the bar is drawn (popin or popout).
+ */
+
+void InitializeStatusBar(HWND hwndParent)
+{
+ const cSpaceInBetween = 8;
+ char szBuf[20];
+ int ptArray[7]; /* Array defining the number of parts/sections */
+ SIZE size; /* the Status bar will display. */
+ RECT rect;
+ HDC hDC;
+
+ /*
+ * Fill in the ptArray...
+ */
+
+ hDC = GetDC(hwndParent);
+ GetClientRect(hwndParent, &rect);
+
+ ptArray[6] = rect.right;
+
+ if (GetTextExtentPoint(hDC, "999999.999xx x 999999.999xx", 27, &size))
+ ptArray[5] = ptArray[6] - (size.cx) - cSpaceInBetween;
+ else
+ ptArray[5] = 0;
+
+ if (GetTextExtentPoint(hDC, "Cursor Pos:", 12, &size))
+ ptArray[4] = ptArray[5] - (size.cx) - cSpaceInBetween;
+ else
+ ptArray[4] = 0;
+
+ if (GetTextExtentPoint(hDC, "999", 2, &size))
+ ptArray[3] = ptArray[4] - (size.cx) - cSpaceInBetween;
+ else
+ ptArray[3] = 0;
+
+ if (GetTextExtentPoint(hDC, "Scaling:", 9, &size))
+ ptArray[2] = ptArray[3] - (size.cx) - cSpaceInBetween;
+ else
+ ptArray[2] = 0;
+
+ if (GetTextExtentPoint(hDC, "99999 of 99999", 14, &size))
+ ptArray[1] = ptArray[2] - (size.cx) - cSpaceInBetween;
+ else
+ ptArray[1] = 0;
+
+ if (GetTextExtentPoint(hDC, "Page:", 6, &size))
+ ptArray[0] = ptArray[1] - (size.cx) - cSpaceInBetween;
+ else
+ ptArray[0] = 0;
+
+ ReleaseDC(hwndParent, hDC);
+
+ SendMessage(hWndStatusbar,
+ SB_SETPARTS,
+ sizeof(ptArray)/sizeof(ptArray[0]),
+ (LPARAM)(LPINT)ptArray);
+
+ UpdateStatusBar(SZDESCRIPTION, 0, 0);
+ UpdateStatusBar("Page:", 1, SBT_POPOUT);
+ wsprintf(szBuf, "%5d of %5d", current_page+1, total_pages);
+ UpdateStatusBar(szBuf, 2, 0);
+ UpdateStatusBar("Page:", 1, SBT_POPOUT);
+ UpdateStatusBar("Scaling:", 3, SBT_POPOUT);
+ wsprintf(szBuf, "%2d", mane.shrinkfactor);
+ UpdateStatusBar(szBuf, 4, 0);
+ UpdateStatusBar("Cursor Pos:", 5, SBT_POPOUT);
+}
+
+/*
+ FUNCTION: CreateSBar(HWND, UINT, WPARAM, LPARAM)
+
+ PURPOSE: Calls CreateStatusWindow() to create the status bar
+
+
+ PARAMETERS:
+
+ hwndParent - Window handle of the status bar's parent
+
+ RETURN VALUE:
+
+ If both controls were created successfully Return TRUE,
+ else returns FALSE.
+
+ COMMENTS:
+ */
+
+BOOL CreateSBar(HWND hwndParent)
+{
+ hWndStatusbar = CreateStatusWindow(WS_CHILD | WS_VISIBLE | WS_BORDER,
+ SZDESCRIPTION,
+ hwndParent,
+ IDM_STATUSBAR);
+ if(hWndStatusbar)
+ {
+ InitializeStatusBar(hwndParent);
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+
+/*
+ FUNCTION: UpdateStatusBar(HWND)
+
+ PURPOSE: Updates the statusbar control with appropriate text
+
+
+ PARAMETERS:
+
+ lpszStatusString - text to be displayed
+ partNumber - which part of the status bar to display text in
+ displayFlags - display flags
+
+
+ RETURN VALUE: NONE
+
+
+ COMMENTS:
+ None
+ */
+
+
+void UpdateStatusBar(LPSTR lpszStatusString, WORD partNumber, WORD displayFlags)
+{
+
+ SendMessage(hWndStatusbar,
+ SB_SETTEXT,
+ partNumber | displayFlags,
+ (LPARAM)lpszStatusString);
+}
+
+/*
+ FUNCTION: CreateTBar(HWND)
+
+ PURPOSE: Calls CreateToolBarEx()
+
+
+ PARAMETERS:
+
+ hwnd - Window handle : Used for the hWndParent parameter of the control.
+
+ RETURN VALUE:
+
+ If toolbar control was created successfully Return TRUE,
+ else returns FALSE.
+
+ COMMENTS:
+ */
+
+
+BOOL CreateTBar(HWND hwnd)
+{
+ DWORD style = WS_CHILD | WS_VISIBLE | TBSTYLE_TOOLTIPS;
+
+ hWndToolbar = CreateToolbarEx(hwnd,
+ style,
+ IDR_TOOLBAR1,
+ NUMIMAGES,
+ hInst,
+ IDR_TOOLBAR1,
+ tbButton,
+ sizeof(tbButton)/sizeof(TBBUTTON),
+ BUTTONWIDTH,
+ BUTTONHEIGHT,
+ IMAGEWIDTH,
+ IMAGEHEIGHT,
+ sizeof(TBBUTTON));
+ if (hWndToolbar != NULL) {
+ ShowWindow(hWndToolbar, SW_SHOW);
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+/*
+ FUNCTION: MsgNotify(HWND, UINT, WPARAM, LPARAM)
+
+ PURPOSE: WM_NOTIFY is sent to the parent window to get the
+ tooltip text assoc'd with that toolbar button.
+
+ PARAMETERS:
+
+ hwnd - Window handle (Unused)
+ uMessage - Message number (Unused)
+ wparam - Extra data (Unused)
+ lparam - TOOLTIPTEXT FAR*
+
+ RETURN VALUE:
+ Always returns 0 - Message handled
+
+
+ COMMENTS:
+ This message fills in the lpszText field of the TOOLTIPTEXT
+ structure if code == TTN_NEEDTEXT
+ */
+
+LRESULT MsgNotify(HWND hwnd, UINT uMessage, WPARAM wparam, LPARAM lparam)
+{
+ LPTOOLTIPTEXT lpToolTipText;
+ static char szBuffer[64];
+
+ lpToolTipText = (LPTOOLTIPTEXT)lparam;
+ if (lpToolTipText->hdr.code == TTN_NEEDTEXT)
+ {
+ LoadString(hInst,
+ lpToolTipText->hdr.idFrom, /* string ID == command ID */
+ szBuffer,
+ sizeof(szBuffer));
+
+ lpToolTipText->lpszText = szBuffer;
+ }
+ return 0;
+}
+
+
+
+/*
+ Miscellaneous functions
+ */
+/*
+ FUNCTION: CenterWindow(HWND, HWND)
+
+ PURPOSE: Center one window over another.
+
+ PARAMETERS:
+ hwndChild - The handle of the window to be centered.
+ hwndParent- The handle of the window to center on.
+
+ RETURN VALUE:
+
+ TRUE - Success
+ FALSE - Failure
+
+ COMMENTS:
+
+ Dialog boxes take on the screen position that they were designed
+ at, which is not always appropriate. Centering the dialog over a
+ particular window usually results in a better position.
+ */
+
+BOOL CenterWindow(HWND hwndChild, HWND hwndParent)
+{
+ RECT rcChild, rcParent;
+ int cxChild, cyChild, cxParent, cyParent;
+ int cxScreen, cyScreen, xNew, yNew;
+ HDC hdc;
+
+ /* Get the Height and Width of the child window */
+ GetWindowRect(hwndChild, &rcChild);
+ cxChild = rcChild.right - rcChild.left;
+ cyChild = rcChild.bottom - rcChild.top;
+
+ /* Get the Height and Width of the parent window */
+ GetWindowRect(hwndParent, &rcParent);
+ cxParent = rcParent.right - rcParent.left;
+ cyParent = rcParent.bottom - rcParent.top;
+
+ /* Get the display limits */
+ hdc = GetDC(hwndChild);
+ cxScreen = GetDeviceCaps(hdc, HORZRES);
+ cyScreen = GetDeviceCaps(hdc, VERTRES);
+ ReleaseDC(hwndChild, hdc);
+
+ /* Calculate new X position, then adjust for screen */
+ xNew = rcParent.left + ((cxParent - cxChild) / 2);
+ if (xNew < 0)
+ {
+ xNew = 0;
+ }
+ else if ((xNew + cxChild) > cxScreen)
+ {
+ xNew = cxScreen - cxChild;
+ }
+
+ /* Calculate new Y position, then adjust for screen */
+ yNew = rcParent.top + ((cyParent - cyChild) / 2);
+ if (yNew < 0)
+ {
+ yNew = 0;
+ }
+ else if ((yNew + cyChild) > cyScreen)
+ {
+ yNew = cyScreen - cyChild;
+ }
+
+ /* Set it, and return */
+ return SetWindowPos(hwndChild,
+ NULL,
+ xNew, yNew,
+ 0, 0,
+ SWP_NOSIZE | SWP_NOZORDER);
+}
+
+
+/*
+ FUNCTION: CmdStub(HWND, WORD, WORD, HWND)
+
+ PURPOSE: Display statusbar updates by calling UpdateStatusBar
+
+ PARAMETERS:
+ hwnd - The window.
+ wCommand - Menu command ID
+ wNotify - Notification number (unused)
+ hwndCtrl - NULL (unused)
+
+ RETURN VALUE:
+ Always returns 0 - command handled.
+
+ COMMENTS:
+ Assumes there is a resource string describing this command with the
+ same ID as the command ID. Loads the string and calls UpdateStatusBar
+ to put the string into main pane of the status bar.
+ */
+
+LRESULT CmdStub(HWND hwnd, WORD wCommand, WORD wNotify, HWND hwndCtrl)
+{
+ char szBuffer[50];
+ int cbWritten = 0;
+
+ cbWritten = LoadString(hInst, wCommand, szBuffer, sizeof(szBuffer));
+ if(cbWritten == 0)
+ {
+ lstrcpy(szBuffer, "Unknown Command");
+ UpdateStatusBar(szBuffer, 0, 0);
+ }
+ else
+ {
+ UpdateStatusBar(szBuffer, 0, 0);
+ MessageBox (hwnd,
+ "Command Not Yet Implemented.\r\n",
+ "Windvi",
+ MB_OK | MB_ICONEXCLAMATION);
+ }
+ /*
+ * Once the command is executed, set the statusbar text to
+ * original text.
+ */
+ UpdateStatusBar(SZDESCRIPTION, 0, 0);
+
+ return 0;
+}
+/*
+ Utility functions
+*/
+
+#if 0
+
+/****************************************************************************
+ * *
+ * FUNCTION : PaletteSize(VOID FAR * pv) *
+ * *
+ * PURPOSE : Calculates the palette size in bytes. If the info. block *
+ * is of the BITMAPCOREHEADER type, the number of colors is *
+ * multiplied by 3 to give the palette size, otherwise the *
+ * number of colors is multiplied by 4. *
+ * *
+ * RETURNS : Palette size in number of bytes. *
+ * *
+ ****************************************************************************/
+WORD PaletteSize (VOID FAR * pv)
+{
+ LPBITMAPINFOHEADER lpbi;
+ WORD NumColors;
+ lpbi = (LPBITMAPINFOHEADER)pv;
+ /* NumColors = DibNumColors(lpbi); */
+ NumColors = lpbi->biBitCount;
+ if (lpbi->biSize == sizeof(BITMAPCOREHEADER))
+ return (WORD)(NumColors * sizeof(RGBTRIPLE));
+ else
+ return (WORD)(NumColors * sizeof(RGBQUAD));
+}
+
+/****************************************************************************
+ * *
+ * FUNCTION : DibBlt( HDC hdc, *
+ * int x0, int y0, *
+ * int dx, int dy, *
+ * HANDLE hdib, *
+ * int x1, int y1, *
+ * LONG rop) *
+ * *
+
+* PURPOSE : Draws a bitmap in CF_DIB format, using SetDIBits to device.*
+ * taking the same parameters as BitBlt(). *
+ * *
+ * RETURNS : TRUE - if function succeeds. *
+ * FALSE - otherwise. *
+ * *
+ ****************************************************************************/
+BOOL DibBlt (
+ HDC hdc,
+ INT x0,
+ INT y0,
+ INT dx,
+ INT dy,
+ HANDLE hdib,
+ INT x1,
+ INT y1,
+ LONG rop)
+{
+ LPBITMAPINFOHEADER lpbi;
+ LPSTR pBuf;
+ DIBSECTION ds;
+
+ if (!hdib)
+ return PatBlt(hdc,x0,y0,dx,dy,rop);
+
+ /* our dibs are created with CreateDIBsection(),
+ so are DIBSECTION. We need to retrieve them with GetObject().
+ FIXME : this does not work as-is.
+ */
+
+ if (GetObject(hdib, sizeof(DIBSECTION), &ds) == 0)
+ Win32Error("DibBlt/GetObject");
+
+ /* lpbi = (VOID FAR *)GlobalLock(hdib); */
+ lpbi = &(ds.dsBmih);
+
+ if (!lpbi)
+ return FALSE;
+
+ /* pBuf = (LPSTR)lpbi + (WORD)lpbi->biSize + PaletteSize(lpbi); */
+ pBuf = (LPSTR)lpbi + (WORD)lpbi->biSize +
+ lpbi->biBitCount * sizeof(RGBQUAD);
+ if (SetDIBitsToDevice (hdc, x0, y0, dx, dy,
+ x1,y1,
+ x1,
+ dy,
+ pBuf, (LPBITMAPINFO)lpbi,
+ DIB_RGB_COLORS ) == 0)
+ Win32Error("DibBlt/SetDIBitsToDevice");
+
+ /* GlobalUnlock(hdib); */
+ return TRUE;
+}
+
+#endif
+
+static char full_dviname[512];
+
+void CloseDviFile()
+{
+ char *fp, *name;
+
+ /* Nothing to close ? */
+ if (!dvi_file)
+ return;
+
+ if (dvistate != SAVED) {
+ /* Just in case we have tried to change directory : retain
+ the full name. */
+
+ /* Get the full file name */
+#if 1
+ /* Beware : might have added file:
+ FIXME: there should be a copy of original dvi_name
+ rather that parsing it back !
+ In fact, dvi_name must be made absolute first.
+ */
+ if (memicmp(dvi_name, "file:", 5) == 0) {
+ if (GetFullPathName(dvi_name+5, sizeof(full_dviname), full_dviname, &fp) == 0)
+ Win32Error("CloseDviFile/GetFullPathName");
+ }
+ else
+#endif
+ if (GetFullPathName(dvi_name, sizeof(full_dviname), full_dviname, &fp) == 0) {
+ Win32Error("CloseDviFile/GetFullPathName");
+ }
+
+ dvistate = SAVED;
+ dvipos = ftell(dvi_file);
+ fclose(dvi_file);
+ dvi_file = NULL;
+#if 0
+ fprintf(stderr, "Dvi file %s is closed\n", dvi_name);
+#endif
+ }
+}
+
+void ReopenDviFile()
+{
+ if (dvistate == SAVED && dvi_file == NULL) {
+ dvi_file = fopen(full_dviname, OPEN_MODE);
+ if (dvi_file) {
+ /* user may have destroyed it !
+ FIXME: this needs testing */
+ fseek(dvi_file, dvipos, SEEK_SET);
+ }
+ dvistate = RESTORED;
+#if 0
+ fprintf(stderr, "Dvi file %s is reopened\n", dvi_name);
+#endif
+ }
+}
+
+BOOL IsOpenedDviFile()
+{
+ return dvistate == RESTORED;
+}
+
+LRESULT MsgActivate(HWND hwnd, UINT uMessage, WPARAM wparam, LPARAM lparam)
+{
+ extern Boolean check_dvi_file();
+ int fActive = LOWORD(wparam);
+
+ if (debug & DBG_EVENT) {
+ fprintf(stderr, "Activate Draw: mag %s, set_home %s, init %scomplete, activated by %s\n",
+ (bMagDisp ? "on" : "off"),
+ (bSetHome ? "on" : "off"),
+ (bInitComplete ? "" : "in"),
+ (fActive == WA_CLICKACTIVE ? "click" : "other than click"));
+ }
+
+ if (!bInitComplete || !dvi_file)
+ return;
+
+ if (/* !bMagDisp && !bSetHome && */ bInitComplete) {
+ if (fActive == WA_ACTIVE)
+ bSkipFirstClick = FALSE;
+ else if (fActive == WA_CLICKACTIVE)
+ bSkipFirstClick = TRUE;
+ if (fActive == WA_ACTIVE || fActive == WA_CLICKACTIVE) {
+ /* We are being activated */
+ /* Reopen dvi file */
+ ReopenDviFile();
+ if (resource.scan_flag) {
+ if (dvi_file) check_dvi_file();
+ /* ChangePage(0); */
+ }
+ }
+ else if (fActive == WA_INACTIVE) {
+ /* We are being deactivated */
+ if (bMagDisp) {
+ /* Remove the mag glass !
+ Look at windraw.c for more precisions.
+ */
+ foreGC = ruleGC = highGC = maneDrawDC;
+ fprintf(stderr, "hiding mag glass\n");
+ ShowWindow(hWndMagnify, SW_HIDE);
+ bMagDisp = FALSE;
+ /* FIXME : is this needed ? */
+ bDrawKeep = FALSE;
+ UpdateWindow(hWndDraw);
+ /* restores the old shrink factor and redisplay page */
+ ClipCursor(NULL);
+ ReleaseCapture();
+ }
+ else if (bSetHome) {
+ /* Restore cursor */
+ bSetHome = FALSE;
+ ClipCursor(NULL);
+ ReleaseCapture();
+ SetCursor(hCursArrow);
+ }
+ /* Save dvi file params & close it if possible */
+ if (dvi_file) {
+ CloseDviFile();
+ }
+ }
+ }
+
+ return 0;
+}
+
+
+LRESULT MsgCopyData(HWND hwnd, UINT uMessage, WPARAM wparam, LPARAM lparam)
+{
+ char oldDir[256];
+ int fa;
+ struct data_exchange *lpDataEx = (struct data_exchange *)(((COPYDATASTRUCT *)lparam)->lpData);
+
+#if 0
+ MessageBox(hWndMain, lpDataEx->cwd, lpDataEx->dviname,
+ MB_APPLMODAL | MB_ICONINFORMATION);
+#endif
+ /* Should we check for new file existence ? */
+ GetCurrentDirectory(sizeof(oldDir), oldDir);
+ SetCurrentDirectory(lpDataEx->cwd);
+ NormalizeDviName(sizeof(lpDataEx->dviname), lpDataEx->dviname);
+ if (((fa = GetFileAttributes(lpDataEx->dviname)) != 0xFFFFFFFF)
+ && ((fa & FILE_ATTRIBUTE_DIRECTORY) != FILE_ATTRIBUTE_DIRECTORY)) {
+ CloseCurrentFile();
+ mane.shrinkfactor = lpDataEx->shrinkfactor;
+ current_page = lpDataEx->currentpage;
+ wsprintf(oldDir, "page %d shrink %d", current_page, mane.shrinkfactor);
+#if 0
+ MessageBox(hWndMain, oldDir, lpDataEx->dviname,
+ MB_APPLMODAL | MB_ICONINFORMATION);
+#endif
+ OpenCurrentFile(lpDataEx->dviname);
+ SetForegroundWindow(hwnd);
+ }
+ else {
+ MessageBox(hWndMain, "Can't find file !", lpDataEx->dviname,
+ MB_APPLMODAL | MB_ICONERROR);
+ SetCurrentDirectory(oldDir);
+ }
+ return TRUE;
+}
+
+#define TRSIZE 100
+
+/* BEGIN CHUNK events.c 1 */
+#ifdef SRC_SPECIALS
+#define src_jumpButton resource._src_jumpButton
+#endif
+/* END CHUNK events.c 1 */
+
+LRESULT MsgChar(HWND hwnd, UINT uMessage, WPARAM wparam, LPARAM lparam)
+{
+ char szBuf[80];
+ static BOOL has_arg = FALSE;
+ static int number = 0;
+ static int sign = 1;
+ char ch;
+ BOOL arg0;
+ int number0;
+/* BEGIN CHUNK events.c 3 */
+ int src_x, src_y;
+/* END CHUNK events.c 3 */
+
+ ch = wparam;
+
+#if 0
+ printf("char %c (%d) (%x) \n", ch, ch, ch);
+#endif
+ if (ch >= '0' && ch <= '9') {
+ has_arg = TRUE;
+ number = number * 10 + sign * (ch - '0');
+ return 0;
+ }
+ else if (ch == '-') {
+ has_arg = TRUE;
+ sign = -1;
+ number = 0;
+ return 0;
+ }
+ number0 = number;
+ number = 0;
+ sign = 1;
+ arg0 = has_arg;
+ has_arg = FALSE;
+#if 0
+ printf("arg0 %d number0 %d\n", arg0, number0);
+#endif
+ switch (wparam) {
+
+ case 'Z':
+ debug = (arg0 ? number0 : -1);
+ break;
+
+ case 'q':
+ case 'Q':
+ case '\003': /* control-C */
+ case '\004': /* control-D */
+#ifdef VMS
+ case '\032': /* control-Z */
+ if (MessageBox(hWndMain, "Really want to quit ?", "Exit",
+ MB_APPLMODAL | MB_ICONQUESTION | MB_OKCANCEL) == IDOK)
+ PostQuitMessage((ch == 'Q') ? 2 : 0);
+ break;
+#endif
+#if PS
+ ps_destroy();
+#endif
+
+ case 'n':
+ case 'f':
+ case ' ':
+ /* case '\r': */
+ /* case '\n': */
+ /* scroll forward; i.e. go to relative page */
+ ChangePage(arg0 ? number0 : 1);
+ break;
+#ifdef HTEX
+ case 'F': /* Follow link forward! */
+ {
+ int x, y;
+ if (pointerlocate(&x, &y)) {
+ /* screen_to_page(&mane,s_x,s_y,&page,&px,&py); */
+ (void) htex_handleref(current_page, x, y);
+#if 0
+ redraw_page();
+#endif
+ }
+ }
+ return 0; /* Should goto bad if problem arises? */
+ case 'B': /* Go back to previous anchor. */
+ htex_goback(); /* Should goto bad if problem arises? */
+#if 0
+ redraw_page();
+#endif
+ return 0;
+#endif
+
+ case 'p':
+ case 'b':
+ /* case '\b':
+ case '\177': Del */
+ /* scroll backward */
+ ChangePage( - (arg0 ? number0 : 1));
+ break;
+
+ case '<':
+ ChangePage(-current_page);
+ break;
+
+ case 'g':
+ case 'j':
+ case '>':
+ /* go to absolute page (last by default) */
+ ChangePage((arg0 ? number0 - pageno_correct :
+ total_pages - 1) - current_page);
+ break;
+
+ case '?':
+ case 'h':
+ case 'H': /* Help */
+ show_help();
+ return 0;
+
+ case 'P': /* declare current page */
+ pageno_correct = arg0 * number0 - current_page;
+ return 0;
+
+ case 'k':
+ resource.keep_flag = (arg0 ? number0 : !resource.keep_flag);
+ CheckMenuItem(hMenuMain, IDM_KEEPPOS, (resource.keep_flag ? MF_CHECKED : MF_UNCHECKED));
+ wsprintf(szBuf, "Home position %skept.", (resource.keep_flag ? "" : "not "));
+ UpdateStatusBar(szBuf, 0, 0);
+ break;
+
+ case '\f':
+ /* redisplay current page */
+ ChangePage(0);
+ break;
+
+ case '^':
+ home(TRUE);
+ break;
+
+ case 'l':
+ SendMessage(hWndDraw, WM_HSCROLL, MAKELONG(SB_PAGEUP, 0), 0L);
+ break;
+
+ case 'r':
+ SendMessage(hWndDraw, WM_HSCROLL, MAKELONG(SB_PAGEDOWN, 0), 0L);
+ break;
+
+ case 'u':
+ SendMessage(hWndDraw, WM_VSCROLL, MAKELONG(SB_PAGEUP, 0), 0L);
+ break;
+
+ case 'd':
+ SendMessage(hWndDraw, WM_VSCROLL, MAKELONG(SB_PAGEDOWN, 0), 0L);
+ break;
+
+ case 'c':
+#ifndef WIN32
+ scrollwindow(&mane, mane.base_x + eventp->xkey.x - clip_w/2,
+ mane.base_y + eventp->xkey.y - clip_h/2);
+ if (x_bar) paint_x_bar();
+ if (y_bar) paint_y_bar();
+ XWarpPointer(DISP, None, None, 0, 0, 0, 0,
+ clip_w/2 - eventp->xkey.x, clip_h/2 - eventp->xkey.y);
+ return;
+#else
+ break;
+#endif
+ case 'M':
+ {
+ POINT ptOrg = { 0, 0};
+ GetWindowOrgEx(maneDrawDC, &ptOrg);
+ home_x = min(xMousePos + xCurrentScroll + ptOrg.x, (unsigned) page_w) * mane.shrinkfactor;
+ home_y = min(yMousePos + yCurrentScroll + ptOrg.y, (unsigned) page_h) * mane.shrinkfactor;
+ if (resource.sidemargin) free(resource.sidemargin);
+ resource.sidemargin = pixtoa(home_x);
+ if (resource.topmargin) free(resource.topmargin);
+ resource.topmargin = pixtoa(home_y);
+
+ wsprintf(szBuf, "Setting home to %5d, %5d", home_x, home_y);
+ UpdateStatusBar(szBuf, 0, 0);
+ }
+ break;
+/* BEGIN CHUNK events.c 4 */
+#ifdef SRC_SPECIALS
+ case 'X':
+ {
+ POINT ptOrg = { 0, 0};
+ GetWindowOrgEx(maneDrawDC, &ptOrg);
+ src_x = min(xMousePos + ptOrg.x + xCurrentScroll, (unsigned) page_w) /* * mane.shrinkfactor */;
+ src_y = min(yMousePos + ptOrg.y + yCurrentScroll, (unsigned) page_h) /* * mane.shrinkfactor */;
+ /* just highlight next special without calling editor for it */
+ src_find_special(0, src_x, src_y);
+ }
+ return;
+#endif
+/* END CHUNK events.c 4 */
+
+ case 's':
+ if (!arg0) {
+ int temp;
+
+ number0 = ROUNDUP(unshrunk_page_w, window_w - 2);
+ temp = ROUNDUP(unshrunk_page_h, window_h - 2);
+ if (number0 < temp) number0 = temp;
+ }
+ if (number0 <= 0) goto bad;
+ if (number0 == mane.shrinkfactor) return 0;
+
+ ChangeZoom(number0);
+ break;
+
+/* BEGIN CHUNK events.c 6 */
+#ifdef SRC_SPECIALS
+ /*
+ * Control-S toggles visibility of src specials
+ * (mnemonic for isearch in Emacs ;-)
+ * Also changes the cursor to emphasize the new mode.
+ */
+ case '\023': /* Control-S */
+ if (src_evalMode) {
+ if (src_warn_verbosity >= SRC_WARNINGS_MEDIUM) {
+ Fprintf(stdout, "SRC specials OFF\n");
+ }
+ /* free src_arr */
+ src_cleanup();
+ src_evalMode = False;
+ SetCursor(hCursArrow);
+ }
+ else {
+ if (src_warn_verbosity >= SRC_WARNINGS_MEDIUM) {
+ Fprintf(stdout, "SRC specials ON\n");
+ }
+ src_evalMode = True;
+ /* used to have this in addition to emphasize the mode,
+ * but usage seems more coherent without it: */
+ /* src_tickVisibility = True; */
+ SetCursor(hCursSrc);
+ }
+ redraw_page();
+ break;
+ case 'T':
+ /*
+ * change shape of specials, but only when they're visible;
+ * this makes the key usable for other purposes in ordinary mode.
+ * However, it seems that in ordinary mode `T' already does the same
+ * as Ctrl-p: print the Unit/bitord/byteord stuff; what's
+ * the reason for this ???
+ */
+ if (src_evalMode) {
+ src_tickShape++;
+ if (src_tickShape > SPECIAL_SHAPE_MAX_NUM) {
+ src_tickShape = 0;
+ }
+ if (src_warn_verbosity >= SRC_WARNINGS_MEDIUM) {
+ Fprintf(stdout, "changing shape to \"%d\"\n", src_tickShape);
+ }
+ if (src_tickVisibility) {
+ redraw_page();
+ }
+ break;
+ }
+#ifndef PS_GS
+ case 'V':
+ if (src_evalMode) {
+ /*
+ * toggle visibility of src specials
+ */
+ if (src_tickVisibility) {
+ if (src_warn_verbosity >= SRC_WARNINGS_MEDIUM) {
+ Fprintf(stdout, "SRC special visibility OFF\n");
+ }
+ src_tickVisibility = False;
+ }
+ else {
+ if (src_warn_verbosity >= SRC_WARNINGS_MEDIUM) {
+ Fprintf(stdout, "SRC special visibility ON\n");
+ }
+ src_tickVisibility = True;
+ }
+ redraw_page();
+ return;
+ }
+#endif /* PS_GS */
+#endif /* SRC_SPECIALS */
+/* END CHUNK events.c 6 */
+ case 'S':
+ if (!arg0) goto bad;
+#ifdef GREY
+ if (use_grey) {
+ float newgamma = number0 != 0 ? number0 / 100.0 : 1.0;
+
+ if (newgamma == gamma) return 0;
+ gamma = newgamma;
+ init_colors();
+ ChangePage(0);
+ return 0;
+ }
+#endif
+ if (number0 < 0) goto bad;
+ if (number0 == density) return 0;
+ density = number0;
+ reset_fonts();
+ if (mane.shrinkfactor == 1) return 0;
+ ChangePage(0);
+ break;
+
+ case 't':
+ { /* toggle through magnifier ruler tick units */
+ extern void pixel_to_unit(void);
+ extern char * pos_format;
+ extern double p2u_factor;
+ char szBuf[80];
+ int k = 0;
+ static char *TeX_units[] = {
+ "bp", "cc", "cm", "dd", "in", "mm", "pc", "pt", "sp",
+ };
+ POINT ptOrg = { 0, 0};
+ GetWindowOrgEx(maneDrawDC, &ptOrg);
+
+ for (k = 0; k < sizeof(TeX_units)/sizeof(TeX_units[0]); ++k)
+ if (strcmp(resource._tick_units,TeX_units[k]) == 0)
+ break;
+ k++;
+ if (k >= sizeof(TeX_units)/sizeof(TeX_units[0]))
+ k = 0;
+ resource._tick_units = TeX_units[k];
+ pixel_to_unit();
+ wsprintf(szBuf, "Ruler units = %.2s\n", resource._tick_units);
+ UpdateStatusBar(szBuf, 0, 0);
+ sprintf(szBuf, pos_format,
+ (xMousePos + xCurrentScroll + ptOrg.x) * mane.shrinkfactor * p2u_factor,
+ (yMousePos + yCurrentScroll + ptOrg.y) * mane.shrinkfactor * p2u_factor);
+ UpdateStatusBar(szBuf, 6, 0);
+ }
+ break;
+
+ case 'G':
+ use_grey = (arg0 ? number0 : !use_grey);
+ if (use_grey) init_colors();
+ reset_fonts();
+ ChangePage(0);
+ break;
+
+ case 'D':
+ grid_mode = (arg0 ? number0 : !grid_mode );
+ init_page();
+ reconfig();
+ ChangePage(0);
+ break;
+
+
+#if PS
+ case 'v':
+ if (!arg0 || resource._postscript != !number0) {
+ resource._postscript = !resource._postscript;
+ if (resource._postscript) scanned_page = scanned_page_bak;
+ psp.toggle();
+ }
+ ChangePage(0);
+ break;
+#endif
+
+#ifdef SELFILE
+ case '\006': /* control-f */
+ ++dvi_time ; /* notice we want a new file in check_dvi_file */
+ ChangePage(0);
+ break ;
+#endif /* SELFILE */
+
+#if PS_GS
+ case 'V':
+/* BEGIN CHUNK events.c 7 */
+#ifdef SRC_SPECIALS
+ if (src_evalMode) {
+ /*
+ * toggle visibility of src specials
+ */
+ if (src_tickVisibility) {
+ if (src_warn_verbosity >= SRC_WARNINGS_MEDIUM) {
+ Fprintf(stdout, "SRC special visibility OFF\n");
+ }
+ src_tickVisibility = False;
+ }
+ else {
+ if (src_warn_verbosity >= SRC_WARNINGS_MEDIUM) {
+ Fprintf(stdout, "SRC special visibility ON\n");
+ }
+ src_tickVisibility = True;
+ }
+ redraw_page();
+ return;
+ }
+ else {
+#endif
+/* END CHUNK events.c 7 */
+ if (!arg0 || resource.gs_alpha != !number0)
+ resource.gs_alpha = !resource.gs_alpha;
+ break;
+/* BEGIN CHUNK events.c 8 */
+#ifdef SRC_SPECIALS
+ }
+#endif
+/* END CHUNK events.c 8 */
+#endif
+
+ case 'R':
+ /* reread DVI file */
+ --dvi_time; /* then it will notice a change */
+ ChangePage(0);
+ break;
+ default:
+ break;
+ }
+
+ goto good;
+
+ bad:
+ if (MessageBeep(0xFFFFFFFF) == 0)
+ Win32Error("HandleKey/MessageBeep");
+ good:
+ return 0;
+}
+
+LRESULT MsgKeyDown(HWND hwnd, UINT uMessage, WPARAM wparam, LPARAM lparam)
+{
+ WORD wScrollNotify = 0xFFFF;
+ UINT msg = WM_VSCROLL;
+ int new_zoom = shrink_factor,
+ rel_page = 0;
+
+#define SHIFTED 0x8000
+#define KEYCOUNT 0x000F
+
+ int ctrl = (GetKeyState(VK_CONTROL) & SHIFTED);
+ int shift = (GetKeyState(VK_SHIFT) & SHIFTED);
+ int l_alt = (GetKeyState(VK_LMENU) & SHIFTED);
+ int r_alt = (GetKeyState(VK_RMENU) & SHIFTED);
+ int count = lparam & KEYCOUNT;
+
+#if 0
+ fprintf(stderr, "ctrl = %x, shift = %x, wparam = %x, count = %x\n",
+ ctrl, shift, wparam, count);
+#endif
+
+ switch (wparam) {
+ case VK_LEFT:
+ msg = WM_HSCROLL;
+ if (ctrl)
+ wScrollNotify = SB_LEFT;
+ else if (shift)
+ wScrollNotify = SB_PAGELEFT;
+ else
+ wScrollNotify = SB_LINELEFT;
+ break;
+
+ case VK_RIGHT:
+ msg = WM_HSCROLL;
+ if (ctrl)
+ wScrollNotify = SB_RIGHT;
+ else if (shift)
+ wScrollNotify = SB_PAGERIGHT;
+ else
+ wScrollNotify = SB_LINERIGHT;
+ break;
+
+ case VK_UP:
+ msg = WM_VSCROLL;
+ if (ctrl)
+ wScrollNotify = SB_TOP;
+ else if (shift)
+ wScrollNotify = SB_PAGEUP;
+ else
+ wScrollNotify = SB_LINEUP;
+ break;
+
+ case VK_DOWN:
+ msg = WM_VSCROLL;
+ if (ctrl)
+ wScrollNotify = SB_BOTTOM;
+ else if (shift)
+ wScrollNotify = SB_PAGEDOWN;
+ else
+ wScrollNotify = SB_LINEDOWN;
+ break;
+
+ case VK_PRIOR:
+ if (ctrl)
+ ChangePage(-current_page);
+ wScrollNotify = SB_PAGEUP;
+ break;
+
+ case VK_NEXT:
+ if (ctrl)
+ ChangePage(total_pages - 1 - current_page);
+ wScrollNotify = SB_PAGEDOWN;
+ break;
+
+ case VK_END:
+ /* Only vertical end */
+ wScrollNotify = SB_BOTTOM;
+ break;
+
+ case VK_HOME:
+ home(TRUE);
+ break;
+
+ case VK_ADD:
+ new_zoom -= count;
+ break;
+
+ case VK_SUBTRACT:
+ new_zoom += count;
+ break;
+
+ case VK_RETURN:
+ rel_page = count;
+ break;
+
+ case VK_BACK:
+ rel_page = -count;
+ break;
+
+ case 'L':
+ if (ctrl) {
+ ChangePage(0);
+ }
+ break;
+
+ }
+#if 0
+ fprintf(stderr, "wScrollNotify = %x msg = %x\n", wScrollNotify, msg);
+#endif
+ if (new_zoom != shrink_factor)
+ ChangeZoom(new_zoom);
+ if (rel_page != 0)
+ ChangePage(rel_page);
+ if (wScrollNotify != 0xFFFF) {
+ int i;
+ for (i = 0; i < count; i++)
+ SendMessage(hWndDraw, msg, MAKELONG(wScrollNotify, 0), 0L);
+ }
+ return 0;
+}
+
+
+LRESULT CmdOpen (HWND hwnd, WORD wCommand, WORD wNotify, HWND hwndCtrl)
+{
+ extern FILE *select_filename(int, int);
+ extern void open_dvi_file();
+
+ if (dvi_file = select_filename(TRUE, TRUE)) {
+ open_dvi_file();
+ if (reconfig() == FALSE) {
+ char buf[40];
+ mane.shrinkfactor +=3;
+ wsprintf(buf, "New shrink factor : %d\n", mane.shrinkfactor);
+ UpdateStatusBar(buf, 0, 0);
+ if (reconfig() == FALSE) {
+ MessageBox(hWndMain, "Can't allocate page bitmap !\r\nPlease report this error.", NULL, MB_APPLMODAL | MB_ICONERROR | MB_OK);
+ CleanExit(1);
+ }
+ };
+#if 0
+ redraw_page();
+#else
+ ChangeZoom(resource.shrinkfactor);
+#endif
+ ChangePage(0);
+ SetForegroundWindow(hwnd);
+ }
+ return 0;
+}
+
+LRESULT CmdOpenRecentFile (HWND hwnd, WORD wCommand, WORD wNotify, HWND hwndCtrl)
+{
+ extern void UpdateMainMenuUsedFiles(void);
+
+ int nCount = wCommand - IDM_FILE_RECENT;
+ char *new_name, *new_cwd, *last_sep, *p;
+ char oldDir[260];
+ int fa, i;
+
+ new_name = strdup(p = lpLastUsedFiles[nCount]);
+
+ /* shift the first files down to this one */
+ for (i = nCount; i >= 1; i--)
+ lpLastUsedFiles[i] = lpLastUsedFiles[i-1];
+ lpLastUsedFiles[0] = p;
+ UpdateMainMenuUsedFiles();
+
+ if ((last_sep = strrchr(new_name, '/')) == NULL)
+ last_sep = strrchr(new_name, '\\');
+
+ if (!last_sep)
+ return 0;
+
+ *last_sep = '\0';
+ new_cwd = new_name;
+ new_name = last_sep+1;
+
+ /* Should we check for new file existence ? */
+ GetCurrentDirectory(sizeof(oldDir), oldDir);
+ SetCurrentDirectory(new_cwd);
+ if (((fa = GetFileAttributes(new_name)) != 0xFFFFFFFF)
+ && ((fa & FILE_ATTRIBUTE_DIRECTORY) != FILE_ATTRIBUTE_DIRECTORY)) {
+ CloseCurrentFile();
+ current_page = 0;
+#if 0
+ MessageBox(hWndMain, oldDir, lpDataEx->dviname,
+ MB_APPLMODAL | MB_ICONINFORMATION);
+#endif
+ OpenCurrentFile(new_name);
+ if (reconfig() == FALSE) {
+ char buf[40];
+ mane.shrinkfactor +=3;
+ wsprintf(buf, "New shrink factor : %d\n", mane.shrinkfactor);
+ UpdateStatusBar(buf, 0, 0);
+ if (reconfig() == FALSE) {
+ MessageBox(hWndMain, "Can't allocate page bitmap !\r\nPlease report this error.", NULL, MB_APPLMODAL | MB_ICONERROR | MB_OK);
+ CleanExit(1);
+ }
+ };
+#if 0
+ redraw_page();
+#endif
+ ChangePage(0);
+ SetForegroundWindow(hwnd);
+ }
+ else {
+ MessageBox(hWndMain, "Can't find file !", new_name,
+ MB_APPLMODAL | MB_ICONERROR);
+ SetCurrentDirectory(oldDir);
+ }
+ free(new_cwd);
+ return 0;
+}
+
+LRESULT CmdClose (HWND hwnd, WORD wCommand, WORD wNotify, HWND hwndCtrl)
+{
+ if (dvi_file)
+ CloseDviFile();
+ if (dvi_name) {
+ free(dvi_name);
+ dvi_name = NULL;
+ set_icon_and_title("", NULL, NULL, 1);
+ }
+ redraw_page();
+ return 0;
+}
+
+/* Choose a decent shrink factor, given the page size
+ and the screen params */
+int ChooseShrink()
+{
+ extern HWND hWndMain, hWndDraw;
+ RECT rcTotal, rcDraw;
+ int total_width, total_height, draw_width, draw_height;
+ int usable_screen_width, usable_screen_height;
+ int xNewSize, yNewSize;
+ int shrink_x, shrink_y;
+ char szBuf[80];
+
+ /*
+ Principle : get the size of the non-drawing area
+ remove it from the size of the screen
+ and calculate the best shrink factor of this size
+ next resize the frame window
+ */
+ GetWindowRect(hWndMain, &rcTotal);
+ GetWindowRect(hWndDraw, &rcDraw);
+ total_width = rcTotal.right - rcTotal.left;
+ total_height = rcTotal.bottom - rcTotal.top;
+ draw_width = rcDraw.right - rcDraw.left;
+ draw_height = rcDraw.bottom - rcDraw.top;
+ usable_screen_width = maneHorzRes - (total_width - draw_width);
+ usable_screen_height = maneVertRes - (total_height - draw_height);
+
+ shrink_x = ROUNDUP(unshrunk_page_w, draw_width);
+ shrink_y = ROUNDUP(unshrunk_page_h, draw_height);
+ if (shrink_x > shrink_y) shrink_x = shrink_y;
+
+ xNewSize = ROUNDUP(unshrunk_page_w,shrink_x)
+ + (total_width - draw_width) + 1;
+ yNewSize = ROUNDUP(unshrunk_page_h,shrink_x)
+ + (total_height - draw_height) + 1;
+
+ wsprintf(szBuf, "Shrink choosen %d (%d x %d)", shrink_x,
+ xNewSize, yNewSize);
+ UpdateStatusBar(szBuf, 0, 0);
+ return shrink_x;
+}
+
+void ChangeZoom(int new_shrink)
+{
+ char szBuf[20];
+
+ if (new_shrink <= 0 || new_shrink == mane.shrinkfactor)
+ return;
+
+ mane.shrinkfactor = new_shrink;
+ init_page();
+#if 0
+ fprintf(stderr, "new_shrink (%d) != bak_shrink (%d)\n",
+ new_shrink, bak_shrink);
+#endif
+ if (new_shrink != 1 && new_shrink != bak_shrink) {
+ bak_shrink = new_shrink;
+#ifdef GREY
+ /* if (use_grey) init_pix(RGB(0,0,0), RGB(255,255,255)); */
+ if (use_grey)
+ init_pix(string_to_colorref(resource.fore_color),
+ string_to_colorref(resource.back_color));
+#endif
+ }
+ if (reconfig() == FALSE) {
+ char buf[40];
+ mane.shrinkfactor += 1;
+ wsprintf(buf, "Can't allocate bitmap for this shrink factor.");
+ UpdateStatusBar(buf, 0, 0);
+ init_page();
+ if (reconfig() == FALSE) {
+ MessageBox(hWndMain, "Not enough storage for page bitmap\r\n",
+ NULL, MB_OK | MB_APPLMODAL | MB_ICONERROR);
+ CleanExit(1);
+ }
+ }
+ reset_fonts();
+ /* In case the ScrollBars will disappear */
+ SetScrollBars(hWndDraw);
+ redraw_page();
+ resource.shrinkfactor = mane.shrinkfactor;
+ wsprintf(szBuf, "%2d", mane.shrinkfactor);
+ UpdateStatusBar(szBuf, 4, 0);
+}
+
+LRESULT CmdZoomIn(HWND hwnd, WORD wCommand,
+ WORD wNotify, HWND hwndCtrl)
+{
+ ChangeZoom(mane.shrinkfactor - 1);
+ return 0;
+}
+
+LRESULT CmdZoomOut(HWND hwnd, WORD wCommand,
+ WORD wNotify, HWND hwndCtrl)
+{
+ ChangeZoom(mane.shrinkfactor + 1);
+ return 0;
+}
+
+LRESULT CmdTogglePS(HWND hwnd, WORD wCommand,
+ WORD wNotify, HWND hwndCtrl)
+{
+ resource._postscript = (resource._postscript ? 0 : 1);
+ CheckMenuItem(hMenuMain, IDM_TOGGLEPS, (resource._postscript ? MF_CHECKED : MF_UNCHECKED));
+ if (resource._postscript) scanned_page = scanned_page_bak;
+ psp.toggle();
+ redraw_page();
+ return 0;
+}
+
+LRESULT CmdToggleGrid(HWND hwnd, WORD wCommand,
+ WORD wNotify, HWND hwndCtrl)
+{
+ char szBuf[80];
+ float sep = 0.0;
+
+ resource._grid_mode = (resource._grid_mode + 1) % 4;
+ if (resource._grid_mode == 3) {
+ sep = (float)ROUNDUP(unshrunk_paper_unit, shrink_factor) / 4.0;
+ sprintf(szBuf, "Grid mode %4.2f pixels", sep);
+ }
+ else if (resource._grid_mode == 2) {
+ sep = (float)ROUNDUP(unshrunk_paper_unit, shrink_factor) / 2.0;
+ sprintf(szBuf, "Grid mode %4.2f pixels", sep);
+ }
+ else if (resource._grid_mode == 1) {
+ sep = (float)ROUNDUP(unshrunk_paper_unit, shrink_factor);
+ sprintf(szBuf, "Grid mode %4.2f pixels", sep);
+ }
+ else
+ sprintf(szBuf, "Grid mode off");
+
+ UpdateStatusBar(szBuf, 0, 0);
+ CheckMenuItem(hMenuMain, IDM_TOGGLEGRID, (resource._grid_mode ? MF_CHECKED : MF_UNCHECKED));
+ init_page();
+ redraw_page();
+ return 0;
+}
+
+/*
+ Warning : ChangePage takes a relative count
+ */
+void ChangePage(int count)
+{
+ extern int total_pages;
+ char szBuf[20];
+ if (count == 0) {
+ /* Explicit call to redraw the current page */
+ redraw_page();
+ }
+ else {
+ int next_page;
+#ifdef BOOK_MODE
+ if (resource.book_mode) {
+ if (count == 1 || count == -1) {
+ /* in this case, should be 2 */
+ next_page = current_page + 2*count;
+ }
+ /* ensure that the left page is even */
+ current_page = (current_page % 2 ? current_page - 1 : current_page);
+ }
+ else {
+ next_page = current_page + count;
+ }
+#else
+ next_page = current_page + count;
+#endif
+#if 1
+ next_page = min(next_page, total_pages - 1);
+ next_page = max(next_page, 0);
+ if (current_page != next_page) {
+ /* BEGIN CHUNK events.c 0 */
+#ifdef SRC_SPECIALS
+ src_delete_all_specials();
+#endif
+/* END CHUNK events.c 0 */
+ current_page = next_page;
+ warn_spec_now = warn_spec;
+ redraw_page();
+ }
+#else
+ if (0 <= next_page && next_page < total_pages) {
+ current_page = next_page;
+ warn_spec_now = warn_spec;
+ redraw_page();
+ }
+#endif
+ }
+#ifdef BOOK_MODE
+ if (resource.book_mode) {
+ wsprintf(szBuf, "%5d-%5d of %5d", current_page+1, current_page+2, total_pages);
+ }
+ else {
+ wsprintf(szBuf, "%5d of %5d", current_page+1, total_pages);
+ }
+#else
+ wsprintf(szBuf, "%5d of %5d", current_page+1, total_pages);
+#endif
+ UpdateStatusBar(szBuf, 2, 0);
+}
+
+LRESULT CmdNextPage(HWND hwnd, WORD wCommand,
+ WORD wNotify, HWND hwndCtrl)
+{
+ ChangePage(+1);
+ return 0;
+}
+
+LRESULT CmdPreviousPage(HWND hwnd, WORD wCommand,
+ WORD wNotify, HWND hwndCtrl)
+{
+ ChangePage(-1);
+ return 0;
+}
+
+LRESULT CmdNext5(HWND hwnd, WORD wCommand,
+ WORD wNotify, HWND hwndCtrl)
+{
+ ChangePage(+5);
+ return 0;
+}
+
+LRESULT CmdPrevious5(HWND hwnd, WORD wCommand,
+ WORD wNotify, HWND hwndCtrl)
+{
+ ChangePage(-5);
+ return 0;
+}
+
+LRESULT CmdNext10(HWND hwnd, WORD wCommand,
+ WORD wNotify, HWND hwndCtrl)
+{
+ ChangePage(+10);
+ return 0;
+}
+
+LRESULT CmdPrevious10(HWND hwnd, WORD wCommand,
+ WORD wNotify, HWND hwndCtrl)
+{
+ ChangePage(-10);
+ return 0;
+}
+
+LRESULT CmdFirstPage(HWND hwnd, WORD wCommand,
+ WORD wNotify, HWND hwndCtrl)
+{
+ ChangePage(- current_page);
+ return 0;
+}
+
+LRESULT CmdLastPage(HWND hwnd, WORD wCommand,
+ WORD wNotify, HWND hwndCtrl)
+{
+ ChangePage(total_pages - current_page - 1);
+ return 0;
+}
+
+LRESULT CmdRedrawPage(HWND hwnd, WORD wCommand,
+ WORD wNotify, HWND hwndCtrl)
+{
+ warn_spec_now = warn_spec;
+ redraw_page();
+ return 0;
+}
+
+LRESULT CmdKeepPosition(HWND hwnd, WORD wCommand,
+ WORD wNotify, HWND hwndCtrl)
+{
+ char szBuf[80];
+
+ resource.keep_flag = !resource.keep_flag;
+ CheckMenuItem(hMenuMain, IDM_KEEPPOS, (resource.keep_flag ? MF_CHECKED : MF_UNCHECKED));
+ wsprintf(szBuf, "Home position %s kept.", (resource.keep_flag ? "" : "not"));
+ UpdateStatusBar(szBuf, 0, 0);
+ return 0;
+}
+
+LRESULT CmdGotoPage(HWND hwnd, WORD wCommand,
+ WORD wNotify, HWND hwndCtrl)
+{
+ DialogBox(hInst, "DlgGotoPage", hwnd, (DLGPROC)DlgGotoPage);
+ return 0;
+}
+
+LRESULT CmdSrcSpecials(HWND hwnd, WORD wCommand,
+ WORD wNotify, HWND hwndCtrl)
+{
+ /* BEGIN CHUNK events.c 2 */
+#ifdef SRC_SPECIALS
+ if (src_evalMode) {
+ if (src_warn_verbosity >= SRC_WARNINGS_MEDIUM) {
+ Fprintf(stdout, "SRC specials OFF\n");
+ }
+ /* free src_arr */
+ src_cleanup();
+ src_evalMode = False;
+ SetCursor(hCursArrow);
+ }
+ else {
+ if (src_warn_verbosity >= SRC_WARNINGS_MEDIUM) {
+ Fprintf(stdout, "SRC specials ON\n");
+ }
+ src_evalMode = True;
+ /* used to have this too to make the mode clearer, but usage seems more coherent without it: */
+ /* src_tickVisibility = True; */
+ SetCursor(hCursSrc);
+ }
+ redraw_page();
+#endif
+/* END CHUNK events.c 2 */
+ return 0;
+}
+
+#ifdef HTEX
+LRESULT CmdUrlBack(HWND hwnd, WORD wCommand,
+ WORD wNotify, HWND hwndCtrl)
+{
+ htex_goback();
+#if 0
+ redraw_page();
+#endif
+ return 0;
+}
+#endif
+
+LRESULT CmdViewLog(HWND hwnd, WORD wCommand,
+ WORD wNotify, HWND hwndCtrl)
+{
+ ShowWindow(hViewLog, SW_SHOW);
+ bLogShown = TRUE;
+ return 0;
+}
+
+void CleanUp()
+{
+#ifdef TRANSFORM
+ extern HRGN hClipRgn;
+#endif
+
+#ifdef PS
+#ifdef TRANSFORM
+ extern HANDLE hGsEvent;
+#endif
+#endif
+
+ extern HDC hdcDrawSave;
+
+#if 0
+ __asm int 3;
+#endif
+
+ _fcloseall();
+
+#ifdef PS
+ if (hGsDll) {
+ ps_destroy();
+ gs_dll_release();
+ }
+#endif
+
+#ifdef HTEX
+ htex_cleanup(0);
+#endif
+
+ remove_temporary_dir();
+
+#if 0
+ /* resources that should be freed */
+ /*
+ Colors
+ */
+ CRefFree(scan_fore_colors);
+#endif
+
+ FreeOptions();
+
+#if 0
+ MessageBox( NULL, "LogLoopThread finished", "", MB_OK|MB_ICONINFORMATION );
+#endif
+
+ /* close any handle */
+ fprintf(stderr, "\n");
+ _flushall();
+
+ fclose(stdin);
+ fclose(stdout);
+ fclose(stderr);
+
+ if (dvi_file)
+ Fclose(dvi_file);
+
+ /* terminate thread */
+ if (WaitForSingleObject(hViewLogThread, 2000) == WAIT_TIMEOUT) {
+ /* This is really unclean. From 20/04/99, it seems that closing
+ stdout and stderr is not enough to make the ReadFile()
+ call return broken_pipe. So we have to make it the hard way. */
+ // MessageBox( NULL, "ViewLog thread does not want to shut down...", "", MB_OK|MB_ICONINFORMATION );
+ TerminateThread(hViewLogThread, 1);
+ CloseHandleAndClear(&hViewLogThread);
+ PostMessage(hViewLog, WM_QUIT, 0, 0);
+ if (WaitForSingleObject(hLogLoopThread, 250) == WAIT_TIMEOUT) {
+ TerminateThread(hLogLoopThread, 1);
+ }
+ CloseHandleAndClear(&hLogLoopThread);
+ }
+
+ CloseHandleAndClear(&hLogIn);
+ CloseHandleAndClear(&hViewLogThread);
+
+
+ /* Deallocate gdi resources */
+ if (forePen && !DeleteObject(forePen))
+ Win32Error("CleanUp/DeleteObject/forePen");
+ if (foreBrush && !DeleteObject(foreBrush))
+ Win32Error("CleanUp/DeleteObject/foreBrush");
+ if (backBrush && !DeleteObject(backBrush))
+ Win32Error("CleanUp/DeleteObject/backBrush");
+ if (backTPicPen && !DeleteObject(backTPicPen))
+ Win32Error("CleanUp/DeleteObject/backTPicPen");
+ if (foreTPicPen && !DeleteObject(foreTPicPen))
+ Win32Error("CleanUp/DeleteObject/foreTPicPen");
+ if (foreTPicBrush && !DeleteObject(foreTPicBrush))
+ Win32Error("CleanUp/DeleteObject/foreTPicBrush");
+
+ if (resource.in_memory) {
+ if (oldmaneDIB) {
+ /* There is an old maneDIB, put it back in the DC
+ and delete the current one */
+ if ((maneDIB = SelectObject(maneDrawDC, oldmaneDIB)) == NULL)
+ Win32Error("reconfig/SelectObject");
+ if (DeleteObject(maneDIB) == FALSE)
+ Win32Error("DeleteObject/maneDIB");
+ }
+
+ if (oldmagDIB) {
+ /* There is an old magDIB, put it back in the DC
+ and delete the current one */
+ if ((magDIB = SelectObject(magMemDC, oldmagDIB)) == NULL)
+ Win32Error("SelectObject/oldmagDIB");
+ if (DeleteObject(magDIB) == FALSE)
+ Win32Error("DeleteObject/magDIB");
+ }
+
+ if (maneDrawDC && !DeleteDC(maneDrawDC)) Win32Error("CleanUp/DeleteDC/maneDrawDC");
+ if (magMemDC && !DeleteDC(magMemDC)) Win32Error("CleanUp/DeleteDC/magMemDC");
+ }
+
+ if (hdcDrawSave) DeleteDC(hdcDrawSave);
+
+#ifdef TRANSFORM
+ if (hClipRgn)
+ DeleteObject(hClipRgn);
+#endif
+}
+
+void CleanExit(int code)
+{
+ CleanUp();
+ ExitProcess(code);
+}
+/*
+ Be warned: the string has to be used before this function is called
+ a second time.
+ */
+LPTSTR GetStringRes (int id)
+{
+ static TCHAR buffer[MAX_PATH];
+
+ buffer[0]=0;
+ LoadString (GetModuleHandle (NULL), id, buffer, MAX_PATH);
+ return buffer;
+}
+
+
+LRESULT CmdHelpTopics(HWND hwnd, WORD wCommand, WORD wNotify, HWND hwndCtrl)
+{
+ ReadHelp (hwnd, SZAPPNAME".HTML");
+ return 0;
+}
+
+#if 0
+LRESULT CmdHelpContents(HWND hwnd, WORD wCommand, WORD wNotify, HWND hwndCtrl)
+{
+ BOOL bGotHelp;
+ /* Not called in Windows 95 */
+ bGotHelp = WinHelp (hwnd, SZAPPNAME".HLP", HELP_CONTENTS,(DWORD)0);
+ if (!bGotHelp) {
+ MessageBox (GetFocus(), GetStringRes(IDS_NO_HELP),
+ szAppName, MB_OK|MB_ICONHAND);
+ }
+ return 0;
+}
+
+LRESULT CmdHelpSearch(HWND hwnd, WORD wCommand, WORD wNotify, HWND hwndCtrl)
+{
+ /* Not called in Windows 95 */
+ if (!WinHelp(hwnd, SZAPPNAME".HLP", HELP_PARTIALKEY, (DWORD)(LPSTR)"")) {
+ MessageBox (GetFocus(), GetStringRes(IDS_NO_HELP),
+ szAppName, MB_OK|MB_ICONHAND);
+ }
+ return 0;
+}
+
+LRESULT CmdHelpHelp(HWND hwnd, WORD wCommand, WORD wNotify, HWND hwndCtrl)
+{
+ /* Not called in Windows 95 */
+ if(!WinHelp(hwnd, (LPSTR)NULL, HELP_HELPONHELP, 0)) {
+ MessageBox (GetFocus(), GetStringRes(IDS_NO_HELP),
+ szAppName, MB_OK|MB_ICONHAND);
+ }
+ return 0;
+}
+#endif
+
+/*F+F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F
+ Function: GetErrorMsg
+ Summary: Accepts a Win32 error code and retrieves a human readable
+ system message for it. Args: HRESULT hr
+ SCODE error code. LPTSTR pszMsg
+ Pointer string where message will be placed.
+ UINT uiSize Max size of the msg string.
+ Returns: BOOL TRUE if hr was error; FALSE if not.
+F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F-F*/
+BOOL GetErrorMsg(HRESULT hr, LPTSTR pszMsg, UINT uiSize)
+{
+ BOOL bErr = FAILED(hr);
+ DWORD dwSize;
+ if (bErr) {
+ memset(pszMsg, 0, uiSize * sizeof(TCHAR));
+ dwSize = FormatMessage(FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_SYSTEM,
+ NULL, hr, MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL),
+ pszMsg, uiSize, NULL);
+ if (dwSize>2) {
+ /* Take out the trailing CRLF. */
+ pszMsg[--dwSize] = 0;
+ pszMsg[--dwSize] = 0;
+ }
+ }
+ return bErr;
+}
+
+/*F+F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F
+ Function: HrMsg
+ Summary: HRESULT Error Message box. Takes standard result code,
+ looks it up in the system tables, and shows a message
+ box with the error code (in hex) and the associated
+ system message. Args: HWND hWndOwner,
+ Handle to owner parent window. LPTSTR pszTitle
+ User message string (eg, designating the attempted function).
+ Appears in dialog title bar. HRESULT hr,
+ Standard result code. Returns: void
+F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F-F*/
+void HrMsg(HWND hWndOwner, LPTSTR pszTitle, HRESULT hr)
+{
+ TCHAR szMsg[MAX_PATH];
+ TCHAR szErrMsg[MAX_PATH];
+ int iResult;
+ wsprintf(szMsg, TEXT("Error=0x%X:\r\n"), hr);
+ GetErrorMsg(hr, szErrMsg, MAX_PATH);
+ lstrcat(szMsg, szErrMsg);
+ iResult = MessageBox(hWndOwner, szMsg, pszTitle, MB_OK | MB_ICONEXCLAMATION);
+ return;
+}
+
+/*
+ We can replace the WinHelp() system by html files using this.
+ */
+void ReadHelp(HWND hWndOwner, LPTSTR pszHelpFile)
+{
+#define NOBROWSE_ERROR_STR "Can't run browser."
+#define NOHTM_ERROR_STR "Can't find .HTM file."
+#define ERROR_TITLE_STR "-Error-"
+ int iRes;
+ LPSTR lpFullHelpFile = NULL;
+ if (NULL != pszHelpFile) {
+ /* First check if the .HTM help file is there at all. */
+ lpFullHelpFile = kpse_var_expand("$TEXMFMAIN/doc/html/windvi/windvi.html");
+ MessageBox(hWndOwner, lpFullHelpFile, "Help File",
+ MB_OK | MB_ICONEXCLAMATION);
+ if (!lpFullHelpFile || GetFileAttributes(lpFullHelpFile) == -1)
+ lpFullHelpFile = kpse_find_file(pszHelpFile, kpse_texdoc_format, TRUE);
+ if (lpFullHelpFile) {
+ /* Use shell to invoke web browser on the HTML help file. */
+ iRes = (int) ShellExecute(hWndOwner, TEXT("open"), lpFullHelpFile,
+ NULL, NULL, SW_SHOWNORMAL);
+ if (iRes <= 32) {
+ /* If unable to browse then put up an error box. */
+ Win32Error(TEXT(NOBROWSE_ERROR_STR));
+ }
+ }
+ else {
+ /* If the .HTM file doesn't exist then put up an error box. */
+ iRes = MessageBox(hWndOwner, TEXT(NOHTM_ERROR_STR), TEXT(ERROR_TITLE_STR),
+ MB_OK | MB_ICONEXCLAMATION);
+ }
+ }
+ return;
+}
+
+/*
+ Add Last Used Files to main menu
+*/
+
+#define RECENT_POSITION 8
+
+void UpdateMainMenuUsedFiles()
+{
+ int nCount;
+ TCHAR szTemp[MAX_PATH + 6];
+ HMENU hMenu;
+ MENUITEMINFO ItemInfo;
+
+ /* Validate parameters. */
+ if (!IsWindow(hWndMain)) {
+ return;
+ }
+
+ if ((hMenu = GetSubMenu(GetMenu(hWndMain), 0)) == NULL)
+ Win32Error("UpdateMainMenuUsedFiled/GetSubMenu");
+
+ for (nCount = 0; nCount < iLastUsedFilesNum; nCount++) {
+ /* Only add strings that are not null or zero length. */
+ if ((lpLastUsedFiles[nCount] != NULL) && (lstrlen(lpLastUsedFiles[nCount]) != 0)) {
+ /* Build recent file menu string. */
+ wsprintf(szTemp, __TEXT("&%d %s"), nCount +1, lpLastUsedFiles[nCount]);
+
+ /* Determine if replacing item or inserting.*/
+ memset(&ItemInfo, 0, sizeof(MENUITEMINFO));
+ ItemInfo.cbSize = sizeof(MENUITEMINFO);
+ ItemInfo.fMask = MIIM_TYPE;
+ GetMenuItemInfo(hMenu, RECENT_POSITION + nCount, TRUE, &ItemInfo);
+ if (MFT_SEPARATOR == ItemInfo.fType) {
+ /* Insert item. MIIM_ID */
+ ItemInfo.fMask = MIIM_TYPE | MIIM_ID;
+ ItemInfo.wID = IDM_FILE_RECENT + nCount;
+ ItemInfo.fType = MFT_STRING;
+ ItemInfo.dwTypeData = szTemp;
+ ItemInfo.cch = lstrlen(ItemInfo.dwTypeData);
+ InsertMenuItem(hMenu, RECENT_POSITION + nCount, TRUE, &ItemInfo);
+ }
+ else {
+ /* Replace menu item. */
+ ItemInfo.fMask = MIIM_TYPE | MIIM_STATE;
+ ItemInfo.fState = MFS_ENABLED;
+ ItemInfo.fType = MFT_STRING;
+ ItemInfo.dwTypeData = szTemp;
+ ItemInfo.cch = lstrlen(ItemInfo.dwTypeData);
+ SetMenuItemInfo(hMenu, RECENT_POSITION + nCount, TRUE, &ItemInfo);
+ }
+ }
+ }
+ DrawMenuBar(hWndMain);
+}
+
+int GetSystemType()
+{
+ OSVERSIONINFOEX osvi;
+ BOOL bOsVersionInfoEx;
+ int result = -1;
+
+ /* Try calling GetVersionEx using the OSVERSIONINFOEX structure,
+ which is supported on Windows NT versions 5.0 and later.
+ If that fails, try using the OSVERSIONINFO structure,
+ which is supported on earlier versions of Windows and Windows NT */
+
+ ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX));
+ osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
+
+ if (! (bOsVersionInfoEx = GetVersionEx ( (OSVERSIONINFO *) &osvi) ) ) {
+ /* If OSVERSIONINFOEX doesn't work, try OSVERSIONINFO. */
+ osvi.dwOSVersionInfoSize = sizeof (OSVERSIONINFO);
+ if (! GetVersionEx ( (OSVERSIONINFO *) &osvi) ) {
+ fprintf(stderr, "GetVersion() failed \n");
+ MessageBox(NULL, "GetVersion() failed.", NULL, MB_APPLMODAL | MB_ICONHAND | MB_OK);
+ return -1;
+ }
+ }
+
+ switch (osvi.dwPlatformId) {
+ case VER_PLATFORM_WIN32_NT:
+ if (osvi.dwMajorVersion == 3)
+ result = WINNT3;
+ else if (osvi.dwMajorVersion == 4)
+ result = WINNT4;
+ else
+ result = WINNT5;
+ break;
+ case VER_PLATFORM_WIN32_WINDOWS:
+ if ((osvi.dwMajorVersion > 4) ||
+ ((osvi.dwMajorVersion == 4) && (osvi.dwMinorVersion > 0)))
+ result = WIN98;
+ else
+ result = WIN95;
+ break;
+ case VER_PLATFORM_WIN32s:
+ result = WIN31;
+ break;
+ }
+#if 0
+ fprintf (stderr, "version %d.%d (Build %d)\n",
+ osvi.dwMajorVersion,
+ osvi.dwMinorVersion,
+ osvi.dwBuildNumber & 0xFFFF);
+ if (bOsVersionInfoEx)
+ fprintf (stderr, "Service Pack %d.%d\n",
+ osvi.wServicePackMajor,
+ osvi.wServicePackMinor);
+#endif
+ return result;
+}
+
+void CloseHandleAndClear(HANDLE *h)
+{
+ if (h && *h != INVALID_HANDLE_VALUE) {
+ if (CloseHandle(*h) == FALSE) {
+ Win32Error("CloseHandle");
+ }
+ *h = INVALID_HANDLE_VALUE;
+ }
+}