view.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434
  1. /*
  2. * Copyright 1998 Douglas Ridgway
  3. *
  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.
  8. *
  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.
  13. *
  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
  17. */
  18. #include <windows.h>
  19. #include <commdlg.h>
  20. #include <stdio.h>
  21. #include "resource.h"
  22. static HINSTANCE hInst;
  23. static HWND hMainWnd;
  24. static const WCHAR szAppName[] = L"View";
  25. static WCHAR szTitle[MAX_PATH];
  26. static WCHAR szFileTitle[MAX_PATH];
  27. static HMETAFILE hmf;
  28. static HENHMETAFILE enhmf;
  29. static int deltax = 0, deltay = 0;
  30. static int width = 0, height = 0;
  31. static BOOL isAldus, isEnhanced;
  32. #include "pshpack1.h"
  33. typedef struct
  34. {
  35. DWORD key;
  36. WORD hmf;
  37. SMALL_RECT bbox;
  38. WORD inch;
  39. DWORD reserved;
  40. WORD checksum;
  41. } APMFILEHEADER;
  42. #include "poppack.h"
  43. #define APMHEADER_KEY 0x9AC6CDD7l
  44. static BOOL FileOpen(HWND hWnd, WCHAR *fn, int fnsz)
  45. {
  46. WCHAR filter[120], metafileFilter[100];
  47. OPENFILENAMEW ofn = { sizeof(OPENFILENAMEW),
  48. 0, 0, NULL, NULL, 0, 0, NULL,
  49. fnsz, NULL, 0, NULL, NULL,
  50. OFN_SHOWHELP, 0, 0, NULL, 0, NULL };
  51. LoadStringW( hInst, IDS_OPEN_META_STRING, metafileFilter, ARRAY_SIZE(metafileFilter) );
  52. swprintf( filter, ARRAY_SIZE(filter), L"%s%c*.wmf;*.emf%c", metafileFilter, 0, 0 );
  53. ofn.lpstrFilter = filter;
  54. ofn.hwndOwner = hWnd;
  55. ofn.lpstrFile = fn;
  56. if( fnsz < 1 )
  57. return FALSE;
  58. *fn = 0;
  59. return GetOpenFileNameW(&ofn);
  60. }
  61. static BOOL FileIsEnhanced( LPCWSTR szFileName )
  62. {
  63. ENHMETAHEADER enh;
  64. HANDLE handle;
  65. DWORD size;
  66. handle = CreateFileW( szFileName, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE,
  67. NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0 );
  68. if (handle == INVALID_HANDLE_VALUE)
  69. return FALSE;
  70. if (!ReadFile( handle, &enh, sizeof(ENHMETAHEADER), &size, NULL ) || size != sizeof(ENHMETAHEADER) )
  71. {
  72. CloseHandle( handle );
  73. return FALSE;
  74. }
  75. CloseHandle( handle );
  76. /* Is it enhanced? */
  77. return (enh.dSignature == ENHMETA_SIGNATURE);
  78. }
  79. static BOOL FileIsPlaceable( LPCWSTR szFileName )
  80. {
  81. APMFILEHEADER apmh;
  82. HANDLE handle;
  83. DWORD size;
  84. handle = CreateFileW( szFileName, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE,
  85. NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0 );
  86. if (handle == INVALID_HANDLE_VALUE)
  87. return FALSE;
  88. if (!ReadFile( handle, &apmh, sizeof(APMFILEHEADER), &size, NULL ) || size != sizeof(APMFILEHEADER))
  89. {
  90. CloseHandle( handle );
  91. return FALSE;
  92. }
  93. CloseHandle( handle );
  94. /* Is it placeable? */
  95. return (apmh.key == APMHEADER_KEY);
  96. }
  97. static HMETAFILE GetPlaceableMetaFile( LPCWSTR szFileName )
  98. {
  99. LPBYTE lpData;
  100. METAHEADER mfHeader;
  101. APMFILEHEADER APMHeader;
  102. HANDLE handle;
  103. DWORD size;
  104. HMETAFILE hmf;
  105. WORD checksum, *p;
  106. HDC hdc;
  107. int i;
  108. handle = CreateFileW( szFileName, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE,
  109. NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0 );
  110. if (handle == INVALID_HANDLE_VALUE)
  111. return 0;
  112. if (!ReadFile( handle, &APMHeader, sizeof(APMFILEHEADER), &size, NULL ) || size != sizeof(APMFILEHEADER))
  113. {
  114. CloseHandle( handle );
  115. return 0;
  116. }
  117. checksum = 0;
  118. p = (WORD *) &APMHeader;
  119. for(i=0; i<10; i++)
  120. checksum ^= *p++;
  121. if (checksum != APMHeader.checksum) {
  122. char msg[128];
  123. sprintf(msg, "Computed checksum %04x != stored checksum %04x\n",
  124. checksum, APMHeader.checksum);
  125. MessageBoxA(hMainWnd, msg, "Checksum failed", MB_OK);
  126. CloseHandle( handle );
  127. return 0;
  128. }
  129. if (!ReadFile( handle, &mfHeader, sizeof(METAHEADER), &size, NULL) || size != sizeof(METAHEADER))
  130. {
  131. CloseHandle( handle );
  132. return 0;
  133. }
  134. if (!(lpData = GlobalAlloc(GPTR, (mfHeader.mtSize * 2L))))
  135. {
  136. CloseHandle( handle );
  137. return 0;
  138. }
  139. SetFilePointer( handle, sizeof(APMFILEHEADER), NULL, FILE_BEGIN );
  140. if (!ReadFile(handle, lpData, mfHeader.mtSize * 2, &size, NULL ) || size != mfHeader.mtSize * 2)
  141. {
  142. GlobalFree(lpData);
  143. CloseHandle( handle );
  144. return 0;
  145. }
  146. CloseHandle( handle );
  147. if (!(hmf = SetMetaFileBitsEx(mfHeader.mtSize*2, lpData))) {
  148. GlobalFree(lpData);
  149. return 0;
  150. }
  151. width = APMHeader.bbox.Right - APMHeader.bbox.Left;
  152. height = APMHeader.bbox.Bottom - APMHeader.bbox.Top;
  153. /* printf("Ok! width %d height %d inch %d\n", width, height, APMHeader.inch); */
  154. hdc = GetDC(hMainWnd);
  155. width = width * GetDeviceCaps(hdc, LOGPIXELSX)/APMHeader.inch;
  156. height = height * GetDeviceCaps(hdc,LOGPIXELSY)/APMHeader.inch;
  157. ReleaseDC(hMainWnd, hdc);
  158. deltax = 0;
  159. deltay = 0 ;
  160. GlobalFree(lpData);
  161. return hmf;
  162. }
  163. static void DoOpenFile(LPCWSTR filename)
  164. {
  165. if (!filename) return;
  166. isAldus = FileIsPlaceable(filename);
  167. if (isAldus) {
  168. hmf = GetPlaceableMetaFile(filename);
  169. } else {
  170. RECT r;
  171. isEnhanced = FileIsEnhanced(filename);
  172. if (isEnhanced)
  173. enhmf = GetEnhMetaFileW(filename);
  174. else
  175. hmf = GetMetaFileW(filename);
  176. GetClientRect(hMainWnd, &r);
  177. width = r.right - r.left;
  178. height = r.bottom - r.top;
  179. }
  180. InvalidateRect( hMainWnd, NULL, TRUE );
  181. }
  182. static void UpdateWindowCaption(void)
  183. {
  184. WCHAR szCaption[MAX_PATH];
  185. WCHAR szView[MAX_PATH];
  186. LoadStringW(hInst, IDS_DESCRIPTION, szView, ARRAY_SIZE(szView));
  187. if (szFileTitle[0] != '\0')
  188. {
  189. lstrcpyW(szCaption, szFileTitle);
  190. LoadStringW(hInst, IDS_DESCRIPTION, szView, ARRAY_SIZE(szView));
  191. lstrcatW(szCaption, L" - ");
  192. lstrcatW(szCaption, szView);
  193. }
  194. else
  195. lstrcpyW(szCaption, szView);
  196. SetWindowTextW(hMainWnd, szCaption);
  197. }
  198. static LRESULT CALLBACK WndProc(HWND hwnd, UINT uMessage, WPARAM wparam, LPARAM lparam)
  199. {
  200. switch (uMessage)
  201. {
  202. case WM_PAINT:
  203. {
  204. PAINTSTRUCT ps;
  205. BeginPaint(hwnd, &ps);
  206. SetMapMode(ps.hdc, MM_ANISOTROPIC);
  207. /* Set the window extent to a sane value in case the metafile doesn't */
  208. SetWindowExtEx(ps.hdc, width, height, NULL);
  209. SetViewportExtEx(ps.hdc, width, height, NULL);
  210. SetViewportOrgEx(ps.hdc, deltax, deltay, NULL);
  211. if (isEnhanced && enhmf)
  212. {
  213. RECT r;
  214. GetClientRect(hwnd, &r);
  215. PlayEnhMetaFile(ps.hdc, enhmf, &r);
  216. }
  217. else if (hmf)
  218. PlayMetaFile(ps.hdc, hmf);
  219. EndPaint(hwnd, &ps);
  220. }
  221. break;
  222. case WM_COMMAND: /* message: command from application menu */
  223. switch (LOWORD(wparam))
  224. {
  225. case IDM_OPEN:
  226. {
  227. WCHAR filename[MAX_PATH];
  228. if (FileOpen(hwnd, filename, ARRAY_SIZE(filename)))
  229. {
  230. szFileTitle[0] = 0;
  231. GetFileTitleW(filename, szFileTitle, ARRAY_SIZE(szFileTitle));
  232. DoOpenFile(filename);
  233. UpdateWindowCaption();
  234. }
  235. }
  236. break;
  237. case IDM_SET_EXT_TO_WIN:
  238. {
  239. RECT r;
  240. GetClientRect(hwnd, &r);
  241. width = r.right - r.left;
  242. height = r.bottom - r.top;
  243. deltax = deltay = 0;
  244. InvalidateRect( hwnd, NULL, TRUE );
  245. }
  246. break;
  247. case IDM_LEFT:
  248. deltax += 100;
  249. InvalidateRect( hwnd, NULL, TRUE );
  250. break;
  251. case IDM_RIGHT:
  252. deltax -= 100;
  253. InvalidateRect( hwnd, NULL, TRUE );
  254. break;
  255. case IDM_UP:
  256. deltay += 100;
  257. InvalidateRect( hwnd, NULL, TRUE );
  258. break;
  259. case IDM_DOWN:
  260. deltay -= 100;
  261. InvalidateRect( hwnd, NULL, TRUE );
  262. break;
  263. case IDM_EXIT:
  264. DestroyWindow(hwnd);
  265. break;
  266. default:
  267. return DefWindowProcW(hwnd, uMessage, wparam, lparam);
  268. }
  269. break;
  270. case WM_DESTROY: /* message: window being destroyed */
  271. PostQuitMessage(0);
  272. break;
  273. default: /* Passes it on if unprocessed */
  274. return DefWindowProcW(hwnd, uMessage, wparam, lparam);
  275. }
  276. return 0;
  277. }
  278. static BOOL InitApplication(HINSTANCE hInstance)
  279. {
  280. WNDCLASSEXW wc;
  281. /* Load the application description strings */
  282. LoadStringW(hInstance, IDS_DESCRIPTION, szTitle, ARRAY_SIZE(szTitle));
  283. /* Fill in window class structure with parameters that describe the
  284. main window */
  285. wc.cbSize = sizeof(WNDCLASSEXW);
  286. wc.style = CS_HREDRAW | CS_VREDRAW; /* Class style(s) */
  287. wc.lpfnWndProc = WndProc; /* Window Procedure */
  288. wc.cbClsExtra = 0; /* No per-class extra data */
  289. wc.cbWndExtra = 0; /* No per-window extra data */
  290. wc.hInstance = hInstance; /* Owner of this class */
  291. wc.hIcon = NULL;
  292. wc.hIconSm = NULL;
  293. wc.hCursor = LoadCursorW(NULL, (LPWSTR)IDC_ARROW);
  294. wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); /* Default color */
  295. wc.lpszMenuName = szAppName; /* Menu name from .rc */
  296. wc.lpszClassName = szAppName; /* Name to register as */
  297. if (!RegisterClassExW(&wc)) return FALSE;
  298. /* Call module specific initialization functions here */
  299. return TRUE;
  300. }
  301. static BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
  302. {
  303. /* Save the instance handle in a global variable for later use */
  304. hInst = hInstance;
  305. /* Create main window */
  306. hMainWnd = CreateWindowW(szAppName, /* See RegisterClass() call */
  307. szTitle, /* window title */
  308. WS_OVERLAPPEDWINDOW, /* Window style */
  309. CW_USEDEFAULT, 0, /* positioning */
  310. CW_USEDEFAULT, 0, /* size */
  311. NULL, /* Overlapped has no parent */
  312. NULL, /* Use the window class menu */
  313. hInstance,
  314. NULL);
  315. if (!hMainWnd)
  316. return FALSE;
  317. /* Call module specific instance initialization functions here */
  318. /* show the window, and paint it for the first time */
  319. ShowWindow(hMainWnd, nCmdShow);
  320. UpdateWindow(hMainWnd);
  321. return TRUE;
  322. }
  323. static void HandleCommandLine(LPWSTR cmdline)
  324. {
  325. /* skip white space */
  326. while (*cmdline == ' ') cmdline++;
  327. if (*cmdline)
  328. {
  329. /* file name is passed on the command line */
  330. if (cmdline[0] == '"')
  331. {
  332. cmdline++;
  333. cmdline[lstrlenW(cmdline) - 1] = 0;
  334. }
  335. szFileTitle[0] = 0;
  336. GetFileTitleW(cmdline, szFileTitle, ARRAY_SIZE(szFileTitle));
  337. DoOpenFile(cmdline);
  338. UpdateWindowCaption();
  339. }
  340. }
  341. int APIENTRY wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int nCmdShow)
  342. {
  343. MSG msg;
  344. /* Other instances of app running? */
  345. if (!hPrevInstance)
  346. {
  347. /* stuff to be done once */
  348. if (!InitApplication(hInstance))
  349. {
  350. return FALSE; /* exit */
  351. }
  352. }
  353. /* stuff to be done every time */
  354. if (!InitInstance(hInstance, nCmdShow))
  355. {
  356. return FALSE;
  357. }
  358. HandleCommandLine(lpCmdLine);
  359. /* Main loop */
  360. /* Acquire and dispatch messages until a WM_QUIT message is received */
  361. while (GetMessageW(&msg, NULL, 0, 0))
  362. {
  363. TranslateMessage(&msg);
  364. DispatchMessageW(&msg);
  365. }
  366. return msg.wParam;
  367. }