view.c 11 KB

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