diff options
author | Karl Berry <karl@freefriends.org> | 2006-01-17 21:41:51 +0000 |
---|---|---|
committer | Karl Berry <karl@freefriends.org> | 2006-01-17 21:41:51 +0000 |
commit | 487ca4806cc046076293cf6cc5fbba0db282bac7 (patch) | |
tree | 847b412ab5158dd7bdd7ed7e5a4cc3fbca94be32 /Build/source/texk/web2c/window/win32.c | |
parent | a3d3111bfe26b8e5f5bc6049dfb2a4ca2edc7881 (diff) |
texk 1
git-svn-id: svn://tug.org/texlive/trunk@1485 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Build/source/texk/web2c/window/win32.c')
-rw-r--r-- | Build/source/texk/web2c/window/win32.c | 415 |
1 files changed, 415 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..1e85d8ba861 --- /dev/null +++ b/Build/source/texk/web2c/window/win32.c @@ -0,0 +1,415 @@ +/* + + Win32 interface for Metafont. + Author: Fabrice Popineau <Fabrice.Popineau@supelec.fr> + + */ + +#define EXTERN extern +#include "../mfd.h" + +#ifdef WIN32WIN +#include <windows.h> + +/* + 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 szAppName[] = "MF"; +static char szTitle[] = " MetaFont V2.718 Online Display"; +static HWND my_window; +static HDC my_dc; +static HDC drawing_dc; +static HBITMAP hbm; +static RGBQUAD black = {0,0,0,0}; +static RGBQUAD white = {255,255,255,0}; +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); + +int +mf_win32_initscreen() +{ + 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() +{ + 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 P4C(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 P4C(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); +} + +#if 0 +void Win32Error(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 ); +} +#endif + +LRESULT APIENTRY WndProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam) +{ + PAINTSTRUCT ps; + int retval; + +#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 */ |