msvcrt: Import erff implementation from musl.
[wine.git] / programs / view / view.c
blobad29734828bfa760cfcb203314173d8690d7a362
1 /*
2 * Copyright 1998 Douglas Ridgway
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 #include <windows.h>
20 #include <commdlg.h>
21 #include <stdio.h>
23 #include "resource.h"
25 static HINSTANCE hInst;
26 static HWND hMainWnd;
27 static const WCHAR szAppName[] = L"View";
28 static WCHAR szTitle[MAX_PATH];
29 static WCHAR szFileTitle[MAX_PATH];
31 static HMETAFILE hmf;
32 static HENHMETAFILE enhmf;
33 static int deltax = 0, deltay = 0;
34 static int width = 0, height = 0;
35 static BOOL isAldus, isEnhanced;
37 #include "pshpack1.h"
38 typedef struct
40 DWORD key;
41 WORD hmf;
42 SMALL_RECT bbox;
43 WORD inch;
44 DWORD reserved;
45 WORD checksum;
46 } APMFILEHEADER;
47 #include "poppack.h"
49 #define APMHEADER_KEY 0x9AC6CDD7l
52 static BOOL FileOpen(HWND hWnd, WCHAR *fn, int fnsz)
54 WCHAR filter[120], metafileFilter[100];
55 OPENFILENAMEW ofn = { sizeof(OPENFILENAMEW),
56 0, 0, NULL, NULL, 0, 0, NULL,
57 fnsz, NULL, 0, NULL, NULL,
58 OFN_SHOWHELP, 0, 0, NULL, 0, NULL };
60 LoadStringW( hInst, IDS_OPEN_META_STRING, metafileFilter, ARRAY_SIZE(metafileFilter) );
61 swprintf( filter, ARRAY_SIZE(filter), L"%s%c*.wmf;*.emf%c", metafileFilter, 0, 0 );
63 ofn.lpstrFilter = filter;
64 ofn.hwndOwner = hWnd;
65 ofn.lpstrFile = fn;
66 if( fnsz < 1 )
67 return FALSE;
68 *fn = 0;
69 return GetOpenFileNameW(&ofn);
72 static BOOL FileIsEnhanced( LPCWSTR szFileName )
74 ENHMETAHEADER enh;
75 HANDLE handle;
76 DWORD size;
78 handle = CreateFileW( szFileName, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE,
79 NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0 );
80 if (handle == INVALID_HANDLE_VALUE)
81 return FALSE;
83 if (!ReadFile( handle, &enh, sizeof(ENHMETAHEADER), &size, NULL ) || size != sizeof(ENHMETAHEADER) )
85 CloseHandle( handle );
86 return FALSE;
88 CloseHandle( handle );
90 /* Is it enhanced? */
91 return (enh.dSignature == ENHMETA_SIGNATURE);
94 static BOOL FileIsPlaceable( LPCWSTR szFileName )
96 APMFILEHEADER apmh;
97 HANDLE handle;
98 DWORD size;
100 handle = CreateFileW( szFileName, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE,
101 NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0 );
102 if (handle == INVALID_HANDLE_VALUE)
103 return FALSE;
105 if (!ReadFile( handle, &apmh, sizeof(APMFILEHEADER), &size, NULL ) || size != sizeof(APMFILEHEADER))
107 CloseHandle( handle );
108 return FALSE;
110 CloseHandle( handle );
112 /* Is it placeable? */
113 return (apmh.key == APMHEADER_KEY);
116 static HMETAFILE GetPlaceableMetaFile( LPCWSTR szFileName )
118 LPBYTE lpData;
119 METAHEADER mfHeader;
120 APMFILEHEADER APMHeader;
121 HANDLE handle;
122 DWORD size;
123 HMETAFILE hmf;
124 WORD checksum, *p;
125 HDC hdc;
126 int i;
128 handle = CreateFileW( szFileName, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE,
129 NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0 );
130 if (handle == INVALID_HANDLE_VALUE)
131 return 0;
133 if (!ReadFile( handle, &APMHeader, sizeof(APMFILEHEADER), &size, NULL ) || size != sizeof(APMFILEHEADER))
135 CloseHandle( handle );
136 return 0;
138 checksum = 0;
139 p = (WORD *) &APMHeader;
141 for(i=0; i<10; i++)
142 checksum ^= *p++;
143 if (checksum != APMHeader.checksum) {
144 char msg[128];
145 sprintf(msg, "Computed checksum %04x != stored checksum %04x\n",
146 checksum, APMHeader.checksum);
147 MessageBoxA(hMainWnd, msg, "Checksum failed", MB_OK);
148 CloseHandle( handle );
149 return 0;
152 if (!ReadFile( handle, &mfHeader, sizeof(METAHEADER), &size, NULL) || size != sizeof(METAHEADER))
154 CloseHandle( handle );
155 return 0;
158 if (!(lpData = GlobalAlloc(GPTR, (mfHeader.mtSize * 2L))))
160 CloseHandle( handle );
161 return 0;
164 SetFilePointer( handle, sizeof(APMFILEHEADER), NULL, FILE_BEGIN );
165 if (!ReadFile(handle, lpData, mfHeader.mtSize * 2, &size, NULL ) || size != mfHeader.mtSize * 2)
167 GlobalFree(lpData);
168 CloseHandle( handle );
169 return 0;
171 CloseHandle( handle );
173 if (!(hmf = SetMetaFileBitsEx(mfHeader.mtSize*2, lpData))) {
174 GlobalFree(lpData);
175 return 0;
179 width = APMHeader.bbox.Right - APMHeader.bbox.Left;
180 height = APMHeader.bbox.Bottom - APMHeader.bbox.Top;
182 /* printf("Ok! width %d height %d inch %d\n", width, height, APMHeader.inch); */
183 hdc = GetDC(hMainWnd);
184 width = width * GetDeviceCaps(hdc, LOGPIXELSX)/APMHeader.inch;
185 height = height * GetDeviceCaps(hdc,LOGPIXELSY)/APMHeader.inch;
186 ReleaseDC(hMainWnd, hdc);
188 deltax = 0;
189 deltay = 0 ;
190 GlobalFree(lpData);
191 return hmf;
194 static void DoOpenFile(LPCWSTR filename)
196 if (!filename) return;
198 isAldus = FileIsPlaceable(filename);
199 if (isAldus) {
200 hmf = GetPlaceableMetaFile(filename);
201 } else {
202 RECT r;
203 isEnhanced = FileIsEnhanced(filename);
204 if (isEnhanced)
205 enhmf = GetEnhMetaFileW(filename);
206 else
207 hmf = GetMetaFileW(filename);
208 GetClientRect(hMainWnd, &r);
209 width = r.right - r.left;
210 height = r.bottom - r.top;
212 InvalidateRect( hMainWnd, NULL, TRUE );
215 static void UpdateWindowCaption(void)
217 WCHAR szCaption[MAX_PATH];
218 WCHAR szView[MAX_PATH];
220 LoadStringW(hInst, IDS_DESCRIPTION, szView, ARRAY_SIZE(szView));
222 if (szFileTitle[0] != '\0')
224 lstrcpyW(szCaption, szFileTitle);
225 LoadStringW(hInst, IDS_DESCRIPTION, szView, ARRAY_SIZE(szView));
226 lstrcatW(szCaption, L" - ");
227 lstrcatW(szCaption, szView);
229 else
230 lstrcpyW(szCaption, szView);
232 SetWindowTextW(hMainWnd, szCaption);
235 static LRESULT CALLBACK WndProc(HWND hwnd, UINT uMessage, WPARAM wparam, LPARAM lparam)
237 switch (uMessage)
239 case WM_PAINT:
241 PAINTSTRUCT ps;
242 BeginPaint(hwnd, &ps);
243 SetMapMode(ps.hdc, MM_ANISOTROPIC);
244 /* Set the window extent to a sane value in case the metafile doesn't */
245 SetWindowExtEx(ps.hdc, width, height, NULL);
246 SetViewportExtEx(ps.hdc, width, height, NULL);
247 SetViewportOrgEx(ps.hdc, deltax, deltay, NULL);
248 if (isEnhanced && enhmf)
250 RECT r;
251 GetClientRect(hwnd, &r);
252 PlayEnhMetaFile(ps.hdc, enhmf, &r);
254 else if (hmf)
255 PlayMetaFile(ps.hdc, hmf);
256 EndPaint(hwnd, &ps);
258 break;
260 case WM_COMMAND: /* message: command from application menu */
261 switch (LOWORD(wparam))
263 case IDM_OPEN:
265 WCHAR filename[MAX_PATH];
266 if (FileOpen(hwnd, filename, ARRAY_SIZE(filename)))
268 szFileTitle[0] = 0;
269 GetFileTitleW(filename, szFileTitle, ARRAY_SIZE(szFileTitle));
270 DoOpenFile(filename);
271 UpdateWindowCaption();
274 break;
276 case IDM_SET_EXT_TO_WIN:
278 RECT r;
279 GetClientRect(hwnd, &r);
280 width = r.right - r.left;
281 height = r.bottom - r.top;
282 deltax = deltay = 0;
283 InvalidateRect( hwnd, NULL, TRUE );
285 break;
288 case IDM_LEFT:
289 deltax += 100;
290 InvalidateRect( hwnd, NULL, TRUE );
291 break;
292 case IDM_RIGHT:
293 deltax -= 100;
294 InvalidateRect( hwnd, NULL, TRUE );
295 break;
296 case IDM_UP:
297 deltay += 100;
298 InvalidateRect( hwnd, NULL, TRUE );
299 break;
300 case IDM_DOWN:
301 deltay -= 100;
302 InvalidateRect( hwnd, NULL, TRUE );
303 break;
305 case IDM_EXIT:
306 DestroyWindow(hwnd);
307 break;
309 default:
310 return DefWindowProcW(hwnd, uMessage, wparam, lparam);
312 break;
314 case WM_DESTROY: /* message: window being destroyed */
315 PostQuitMessage(0);
316 break;
318 default: /* Passes it on if unprocessed */
319 return DefWindowProcW(hwnd, uMessage, wparam, lparam);
321 return 0;
324 static BOOL InitApplication(HINSTANCE hInstance)
326 WNDCLASSEXW wc;
328 /* Load the application description strings */
329 LoadStringW(hInstance, IDS_DESCRIPTION, szTitle, ARRAY_SIZE(szTitle));
331 /* Fill in window class structure with parameters that describe the
332 main window */
334 wc.cbSize = sizeof(WNDCLASSEXW);
335 wc.style = CS_HREDRAW | CS_VREDRAW; /* Class style(s) */
336 wc.lpfnWndProc = WndProc; /* Window Procedure */
337 wc.cbClsExtra = 0; /* No per-class extra data */
338 wc.cbWndExtra = 0; /* No per-window extra data */
339 wc.hInstance = hInstance; /* Owner of this class */
340 wc.hIcon = NULL;
341 wc.hIconSm = NULL;
342 wc.hCursor = LoadCursorW(NULL, (LPWSTR)IDC_ARROW);
343 wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); /* Default color */
344 wc.lpszMenuName = szAppName; /* Menu name from .rc */
345 wc.lpszClassName = szAppName; /* Name to register as */
347 if (!RegisterClassExW(&wc)) return FALSE;
349 /* Call module specific initialization functions here */
351 return TRUE;
354 static BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
356 /* Save the instance handle in a global variable for later use */
357 hInst = hInstance;
359 /* Create main window */
360 hMainWnd = CreateWindowW(szAppName, /* See RegisterClass() call */
361 szTitle, /* window title */
362 WS_OVERLAPPEDWINDOW, /* Window style */
363 CW_USEDEFAULT, 0, /* positioning */
364 CW_USEDEFAULT, 0, /* size */
365 NULL, /* Overlapped has no parent */
366 NULL, /* Use the window class menu */
367 hInstance,
368 NULL);
370 if (!hMainWnd)
371 return FALSE;
373 /* Call module specific instance initialization functions here */
375 /* show the window, and paint it for the first time */
376 ShowWindow(hMainWnd, nCmdShow);
377 UpdateWindow(hMainWnd);
379 return TRUE;
382 static void HandleCommandLine(LPWSTR cmdline)
384 /* skip white space */
385 while (*cmdline == ' ') cmdline++;
387 if (*cmdline)
389 /* file name is passed on the command line */
390 if (cmdline[0] == '"')
392 cmdline++;
393 cmdline[lstrlenW(cmdline) - 1] = 0;
395 szFileTitle[0] = 0;
396 GetFileTitleW(cmdline, szFileTitle, ARRAY_SIZE(szFileTitle));
397 DoOpenFile(cmdline);
398 UpdateWindowCaption();
402 int APIENTRY wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int nCmdShow)
404 MSG msg;
406 /* Other instances of app running? */
407 if (!hPrevInstance)
409 /* stuff to be done once */
410 if (!InitApplication(hInstance))
412 return FALSE; /* exit */
416 /* stuff to be done every time */
417 if (!InitInstance(hInstance, nCmdShow))
419 return FALSE;
422 HandleCommandLine(lpCmdLine);
424 /* Main loop */
425 /* Acquire and dispatch messages until a WM_QUIT message is received */
426 while (GetMessageW(&msg, NULL, 0, 0))
428 TranslateMessage(&msg);
429 DispatchMessageW(&msg);
432 return msg.wParam;