summaryrefslogtreecommitdiff
path: root/Build/source/texk/web2c/window/win32.c
diff options
context:
space:
mode:
Diffstat (limited to 'Build/source/texk/web2c/window/win32.c')
-rw-r--r--Build/source/texk/web2c/window/win32.c422
1 files changed, 422 insertions, 0 deletions
diff --git a/Build/source/texk/web2c/window/win32.c b/Build/source/texk/web2c/window/win32.c
new file mode 100644
index 00000000000..a520202d3d4
--- /dev/null
+++ b/Build/source/texk/web2c/window/win32.c
@@ -0,0 +1,422 @@
+/*
+
+ Win32 interface for Metafont.
+ Author: Fabrice Popineau <Fabrice.Popineau@supelec.fr>
+
+ */
+
+#define EXTERN extern
+#include "../mfd.h"
+
+#ifdef WIN32WIN
+#include <windows.h>
+
+#ifndef min
+#define min(a,b) ((a) < (b) ? (a) : (b))
+#endif
+#ifndef max
+#define max(a,b) ((a) < (b) ? (b) : (a))
+#endif
+
+static void Win32Error(const char *caller);
+
+/*
+ The following constant enables some hack that should allow the
+ window to process its messages. Basically, the principle is to
+ create a thread which will do the message loop. Unfortunately,
+ it does not seem to work very well :-)
+ */
+#undef LOOPMSG
+#define LOOPMSG 1
+
+#undef DEBUG
+/* #define DEBUG 1 */
+
+static char szTitle[] = " MetaFont V2.718281 Online Display";
+static HWND my_window;
+static HDC my_dc;
+static HDC drawing_dc;
+static HBITMAP hbm;
+static MSG msg;
+static HANDLE hAccelTable;
+static HANDLE hMutex;
+/* Scrollbars' variables */
+static SCROLLINFO si;
+static int xMinScroll;
+static int xMaxScroll;
+static int xCurrentScroll;
+static int yMinScroll;
+static int yMaxScroll;
+static int yCurrentScroll;
+static BOOL fScroll;
+static BOOL fSize;
+
+#ifdef LOOPMSG
+void __cdecl InitGui(void*);
+#endif
+LRESULT CALLBACK WndProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam);
+
+#include <mfdisplay.h>
+
+int
+mf_win32_initscreen(void)
+{
+ int ret;
+ if ((ret = _beginthread(InitGui, 0, NULL)) == -1) {
+ fprintf(stderr, "_beginthread returned with %d\n", ret);
+ return 0;
+ }
+ else
+ return 1;
+}
+
+ /* This window should be registered into a class. And maybe the
+ message loop could run into a separate thread. */
+
+void __cdecl InitGui(void *param)
+{
+ HWND hparentwnd;
+ HANDLE hinst;
+ WNDCLASSEX wndclass;
+ char szFile[80];
+
+ hinst = GetModuleHandle(NULL);
+ GetModuleFileName (hinst, szFile, sizeof(szFile));
+#ifdef DEBUG
+ printf ("hinst = %x\n", hinst);
+ printf ("File = %s\n", szFile);
+#endif
+ /* Fill in window class structure with parameters that describe
+ the main window. */
+ /* CS_OWNDC : un DC pour chaque fenêtre de la classe */
+ wndclass.cbSize = sizeof(wndclass);
+ wndclass.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
+ wndclass.lpfnWndProc = (WNDPROC)WndProc;
+ wndclass.cbClsExtra = 0;
+ wndclass.cbWndExtra = 0;
+ wndclass.hInstance = hinst;
+ wndclass.hIcon = LoadIcon (NULL, IDI_APPLICATION);
+ wndclass.hIconSm = LoadIcon (NULL, IDI_APPLICATION);
+ wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
+ wndclass.hbrBackground = GetStockObject(WHITE_BRUSH);
+ wndclass.lpszClassName = szFile;
+ wndclass.lpszMenuName = NULL;
+
+ if (!RegisterClassEx(&wndclass))
+ Win32Error("Register class");
+
+ hparentwnd = GetFocus();
+ my_window = CreateWindow(szFile, szTitle,
+ WS_OVERLAPPEDWINDOW | WS_HSCROLL | WS_VSCROLL,
+ CW_USEDEFAULT, 0,
+ CW_USEDEFAULT, 0,
+ /* screenwidth, screendepth, */
+ hparentwnd, NULL, hinst, NULL);
+ if (!my_window) {
+ Win32Error("Create window");
+ }
+#ifdef DEBUG
+ fprintf(stderr, "my_window = %x\n", my_window);
+#endif
+
+#ifdef LOOPMSG
+ /* Acknowledge for UpdateWindow() (WM_PAINT message generated) */
+ hMutex = CreateMutex(NULL, FALSE, "DrawingMutex");
+ my_dc = GetDC(my_window);
+ /* Device context for drawing and the associated bitmap. */
+ drawing_dc = CreateCompatibleDC(my_dc);
+ hbm = CreateCompatibleBitmap(my_dc, screenwidth, screendepth);
+ SelectObject(drawing_dc, hbm);
+ /* Blank the bitmap */
+ SelectObject(drawing_dc, GetStockObject(WHITE_BRUSH));
+ PatBlt(drawing_dc, 0, 0, screenwidth, screendepth, PATCOPY);
+ hAccelTable = LoadAccelerators (hinst, szTitle);
+
+ ShowWindow(my_window, SW_SHOWNORMAL);
+ UpdateWindow(my_window);
+
+ /* Running the message loop */
+ while (GetMessage(&msg, my_window, 0, 0)) {
+ TranslateMessage(&msg);
+ DispatchMessage(&msg);
+ }
+
+#else
+ drawing_dc = my_dc = GetDC(my_window);
+#endif
+}
+
+/* Make sure the screen is up to date. (section 8.6 Handling the output
+buffer) */
+
+void
+mf_win32_updatescreen(void)
+{
+ RECT r;
+ r.left = 0;
+ r.top = 0;
+ r.right = screenwidth;
+ r.bottom = screendepth;
+
+ /* Send a WM_PAINT message to the window.
+ The rectangle should be invalidated for the message being sent. */
+ InvalidateRect(my_window, &r, FALSE);
+ UpdateWindow(my_window);
+}
+
+
+/* Blank the rectangular inside the given coordinates. We don't need to
+reset the foreground to black because we always set it at the beginning
+of paintrow (below). */
+
+void
+mf_win32_blankrectangle (screencol left,
+ screencol right,
+ screenrow top,
+ screenrow bottom)
+{
+ RECT r;
+ r.left = left;
+ r.top = top;
+ r.right = right+1; /* FIXME: must we fill the last row/column ? */
+ r.bottom = bottom+1;
+ /* Fixme : should synchronize with message processing. */
+ WaitForSingleObject(hMutex, INFINITE);
+ FillRect(drawing_dc, &r, GetStockObject(WHITE_BRUSH));
+ ReleaseMutex(hMutex);
+}
+
+
+/* Paint a row with the given ``transition specifications''. We might be
+able to do something here with drawing many lines. */
+
+void
+mf_win32_paintrow (screenrow row,
+ pixelcolor init_color,
+ transspec tvect,
+ register screencol vector_size)
+{
+ register int col;
+ HGDIOBJ CurrentPen;
+ HGDIOBJ WhitePen = GetStockObject(WHITE_PEN);
+ HGDIOBJ BlackPen = GetStockObject(BLACK_PEN);
+ /* FIXME: should sync with msg processing */
+ WaitForSingleObject(hMutex, INFINITE);
+ CurrentPen = (init_color == 0) ? WhitePen : BlackPen;
+ do {
+ col = *tvect++;
+ MoveToEx(drawing_dc, col, (int) row, NULL);
+ SelectObject(drawing_dc, CurrentPen);
+
+ /* (section 6.3.2 Drawing single and multiple lines)
+ */
+ LineTo(drawing_dc, (int) *tvect, (int) row);
+ CurrentPen = (CurrentPen == WhitePen) ? BlackPen : WhitePen;
+ } while (--vector_size > 0);
+ SelectObject(drawing_dc, GetStockObject(NULL_PEN));
+ ReleaseMutex(hMutex);
+}
+
+static void Win32Error(const char *caller)
+{
+ LPVOID lpMsgBuf;
+
+ FormatMessage(
+ FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
+ NULL,
+ GetLastError(),
+ MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), /* Default language */
+ (LPTSTR) &lpMsgBuf,
+ 0,
+ NULL
+ );
+ /* Display the string. */
+ MessageBox( NULL, lpMsgBuf, caller, MB_OK|MB_ICONINFORMATION );
+ /* Free the buffer. */
+ LocalFree( lpMsgBuf );
+}
+
+LRESULT APIENTRY WndProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam)
+{
+ PAINTSTRUCT ps;
+ int retval = 0;
+
+#ifdef DEBUG
+ fprintf(stderr, "Message %x\n", iMsg);
+#endif
+#ifdef LOOPMSG
+ WaitForSingleObject(hMutex, INFINITE);
+ switch (iMsg) {
+ case WM_CREATE:
+ xMinScroll = 0;
+ xMaxScroll = screenwidth;
+ xCurrentScroll = 0;
+
+ yMinScroll = 0;
+ yMaxScroll = screendepth;
+ yCurrentScroll = 0;
+
+ fScroll = FALSE;
+ fSize = FALSE;
+
+ break;
+ case WM_SIZE:
+ {
+ int xNewSize, yNewSize;
+ xNewSize = LOWORD(lParam);
+ yNewSize = HIWORD(lParam);
+
+ fSize = TRUE;
+
+ xMaxScroll = max(screenwidth, xNewSize);
+ xCurrentScroll = min(xCurrentScroll, xMaxScroll);
+
+ si.cbSize = sizeof(si);
+ si.fMask = SIF_RANGE | SIF_PAGE | SIF_POS;
+ si.nMin = xMinScroll;
+ si.nMax = xMaxScroll;
+ si.nPage = xNewSize;
+ si.nPos = xCurrentScroll;
+ SetScrollInfo(my_window, SB_HORZ, &si, TRUE);
+
+ yMaxScroll = max(screendepth, yNewSize);
+ yCurrentScroll = min(yCurrentScroll, yMaxScroll);
+
+ si.cbSize = sizeof(si);
+ si.fMask = SIF_RANGE | SIF_PAGE | SIF_POS;
+ si.nMin = yMinScroll;
+ si.nMax = yMaxScroll;
+ si.nPage = yNewSize;
+ si.nPos = yCurrentScroll;
+ SetScrollInfo(my_window, SB_VERT, &si, TRUE);
+ }
+ case WM_PAINT:
+ {
+#ifdef DEBUG
+ fprintf(stderr, "WM_PAINT message hbm = %x\n", hbm);
+#endif
+ BeginPaint(my_window, &ps);
+ /* Shouldn't repaint all the screen, but so easy! */
+ if (!BitBlt(my_dc,
+ 0, 0,
+ screenwidth, screendepth,
+ drawing_dc,
+ xCurrentScroll,
+ yCurrentScroll, SRCCOPY))
+ Win32Error("Bitblt");
+ EndPaint(my_window, &ps);
+ retval = 0;
+ break;
+ }
+ case WM_HSCROLL:
+ {
+ int xDelta;
+ int xNewPos;
+ int yDelta = 0;
+ switch (LOWORD(wParam)) {
+ case SB_PAGEUP:
+ xNewPos = xCurrentScroll - 50;
+ break;
+ case SB_PAGEDOWN:
+ xNewPos = xCurrentScroll + 50;
+ break;
+ case SB_LINEUP:
+ xNewPos = xCurrentScroll - 5;
+ break;
+ case SB_LINEDOWN:
+ xNewPos = xCurrentScroll + 5;
+ break;
+ case SB_THUMBPOSITION:
+ xNewPos = HIWORD(wParam);
+ break;
+ default:
+ xNewPos = xCurrentScroll;
+ }
+ xNewPos = max(0, xNewPos);
+ xNewPos = min(xMaxScroll, xNewPos);
+
+ if (xNewPos == xCurrentScroll)
+ break;
+
+ fScroll = TRUE;
+
+ xDelta = xNewPos - xCurrentScroll;
+ xCurrentScroll = xNewPos;
+
+ ScrollWindowEx(my_window, -xDelta, -yDelta, (CONST RECT *)NULL,
+ (CONST RECT *)NULL, (HRGN)NULL, (LPRECT)NULL,
+ SW_INVALIDATE);
+ UpdateWindow(my_window);
+
+ si.cbSize = sizeof(si);
+ si.fMask = SIF_POS;
+ si.nPos = xCurrentScroll;
+ SetScrollInfo(my_window, SB_HORZ, &si, TRUE);
+ }
+ break;
+
+ case WM_VSCROLL:
+ {
+ int xDelta = 0;
+ int yNewPos;
+ int yDelta;
+ switch (LOWORD(wParam)) {
+ case SB_PAGEUP:
+ yNewPos = yCurrentScroll - 50;
+ break;
+ case SB_PAGEDOWN:
+ yNewPos = yCurrentScroll + 50;
+ break;
+ case SB_LINEUP:
+ yNewPos = yCurrentScroll - 5;
+ break;
+ case SB_LINEDOWN:
+ yNewPos = yCurrentScroll + 5;
+ break;
+ case SB_THUMBPOSITION:
+ yNewPos = HIWORD(wParam);
+ break;
+ default:
+ yNewPos = yCurrentScroll;
+ }
+ yNewPos = max(0, yNewPos);
+ yNewPos = min(yMaxScroll, yNewPos);
+
+ if (yNewPos == yCurrentScroll)
+ break;
+
+ fScroll = TRUE;
+
+ yDelta = yNewPos - yCurrentScroll;
+ yCurrentScroll = yNewPos;
+
+ ScrollWindowEx(my_window, -xDelta, -yDelta, (CONST RECT *)NULL,
+ (CONST RECT *)NULL, (HRGN)NULL, (LPRECT)NULL,
+ SW_INVALIDATE);
+ UpdateWindow(my_window);
+
+ si.cbSize = sizeof(si);
+ si.fMask = SIF_POS;
+ si.nPos = yCurrentScroll;
+ SetScrollInfo(my_window, SB_VERT, &si, TRUE);
+ }
+ break;
+
+ case WM_DESTROY:
+ PostQuitMessage(0);
+ retval = 0;
+ break;
+ default:
+ retval = DefWindowProc(hwnd, iMsg, wParam, lParam);
+ break;
+ }
+ ReleaseMutex(hMutex);
+ return retval;
+#else
+ return DefWindowProc(hwnd, iMsg, wParam, lParam);
+#endif
+}
+
+#else
+int win32_dummy;
+#endif /* WIN32WIN */