view: Merge 3 C source files and a header file into one file.
[wine] / programs / view / view.c
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
19 #include <windows.h>
20 #include <windowsx.h>
21 #include "resource.h"
22
23 #include <stdio.h>
24
25 static HINSTANCE hInst;
26 static char szAppName[5] = "View";
27 static char szTitle[80];
28
29 static HMETAFILE hmf;
30 static int deltax = 0, deltay = 0;
31 static int width = 0, height = 0;
32 static BOOL isAldus;
33
34 #include "pshpack1.h"
35 typedef struct
36 {
37         DWORD           key;
38         WORD            hmf;
39         SMALL_RECT      bbox;
40         WORD            inch;
41         DWORD           reserved;
42         WORD            checksum;
43 } APMFILEHEADER;
44 #include "poppack.h"
45
46 #define APMHEADER_KEY   0x9AC6CDD7l
47
48
49 static BOOL FileOpen(HWND hWnd, char *fn, int fnsz)
50 {
51   OPENFILENAME ofn = { sizeof(OPENFILENAME),
52                        0, 0, NULL, NULL, 0, 0, NULL,
53                        fnsz, NULL, 0, NULL, NULL, 
54                        OFN_SHOWHELP, 0, 0, NULL, 0, NULL };
55   ofn.lpstrFilter = "Metafiles\0*.wmf\0";
56   ofn.hwndOwner = hWnd;
57   ofn.lpstrFile = fn;
58   if( fnsz < 1 )
59     return FALSE;
60   *fn = 0;
61   return GetOpenFileName(&ofn);
62 }
63
64 static BOOL FileIsPlaceable( LPCSTR szFileName )
65 {
66   HFILE         hInFile;
67   APMFILEHEADER apmh;
68
69   if( (hInFile = _lopen( szFileName, OF_READ ) ) == HFILE_ERROR )
70     return FALSE;
71
72   if( _lread( hInFile, &apmh, sizeof(APMFILEHEADER) )
73       != sizeof(APMFILEHEADER) )
74     {
75       _lclose( hInFile );
76       return FALSE;
77     }
78   _lclose( hInFile );
79
80   /* Is it placeable? */
81   return (apmh.key == APMHEADER_KEY);
82 }
83
84 static HMETAFILE GetPlaceableMetaFile( HWND hwnd, LPCSTR szFileName )
85 {
86   LPBYTE lpData;
87   METAHEADER mfHeader;
88   APMFILEHEADER APMHeader;
89   HFILE fh;
90   HMETAFILE hmf;
91   WORD checksum, *p;
92   HDC hdc;
93   int i;
94
95   if( (fh = _lopen( szFileName, OF_READ ) ) == HFILE_ERROR ) return 0;
96   _llseek(fh, 0, 0);
97   if (!_lread(fh, &APMHeader, sizeof(APMFILEHEADER))) return 0;
98   _llseek(fh, sizeof(APMFILEHEADER), 0);
99   checksum = 0;
100   p = (WORD *) &APMHeader;
101
102   for(i=0; i<10; i++)
103     checksum ^= *p++;
104   if (checksum != APMHeader.checksum) {
105     char msg[128];
106     sprintf(msg, "Computed checksum %04x != stored checksum %04x\n",
107            checksum, APMHeader.checksum);
108         MessageBox(hwnd, msg, "Checksum failed", MB_OK);
109     return 0;
110   }
111
112   if (!_lread(fh, &mfHeader, sizeof(METAHEADER))) return 0;
113
114   if (!(lpData = GlobalAlloc(GPTR, (mfHeader.mtSize * 2L)))) return 0;
115
116   _llseek(fh, sizeof(APMFILEHEADER), 0);
117   if (!_lread(fh, lpData, (UINT)(mfHeader.mtSize * 2L)))
118   {
119     GlobalFree(lpData);
120     _lclose(fh);
121     return 0;
122   }
123   _lclose(fh);
124
125   if (!(hmf = SetMetaFileBitsEx(mfHeader.mtSize*2, lpData)))
126     return 0;
127
128
129   width = APMHeader.bbox.Right - APMHeader.bbox.Left;
130   height = APMHeader.bbox.Bottom - APMHeader.bbox.Top;
131
132   /*      printf("Ok! width %d height %d inch %d\n", width, height, APMHeader.inch);  */
133   hdc = GetDC(hwnd);
134   width = width * GetDeviceCaps(hdc, LOGPIXELSX)/APMHeader.inch;
135   height = height * GetDeviceCaps(hdc,LOGPIXELSY)/APMHeader.inch;
136   ReleaseDC(hwnd, hdc);
137
138   deltax = 0;
139   deltay = 0 ;
140   return hmf;
141 }
142
143
144 static LRESULT CALLBACK WndProc(HWND hwnd, UINT uMessage, WPARAM wparam, LPARAM lparam)
145 {
146   switch (uMessage)
147     {
148     case WM_PAINT:
149       {
150         PAINTSTRUCT ps;
151         BeginPaint(hwnd, &ps);
152         SetMapMode(ps.hdc, MM_ANISOTROPIC);
153         /* Set the window extent to a sane value in case the metafile doesn't */
154         SetWindowExtEx(ps.hdc, width, height, NULL);
155         SetViewportExtEx(ps.hdc, width, height, NULL);
156         SetViewportOrgEx(ps.hdc, deltax, deltay, NULL);
157         if(hmf) PlayMetaFile(ps.hdc, hmf);
158         EndPaint(hwnd, &ps);
159       }
160       break;
161
162     case WM_COMMAND: /* message: command from application menu */
163       switch (GET_WM_COMMAND_ID(wparam,lparam))
164         {
165         case IDM_OPEN:
166           {
167             char filename[MAX_PATH];
168             if (FileOpen(hwnd, filename, sizeof(filename))) {
169               isAldus = FileIsPlaceable(filename);
170               if (isAldus) {
171                 hmf = GetPlaceableMetaFile(hwnd, filename);
172               } else {
173                 RECT r;
174                 hmf = GetMetaFile(filename);
175                 GetClientRect(hwnd, &r);
176                 width = r.right - r.left;
177                 height = r.bottom - r.top;
178               }
179               InvalidateRect( hwnd, NULL, TRUE );
180             }
181           }
182           break;
183
184         case IDM_SET_EXT_TO_WIN:
185           {
186             RECT r;
187             GetClientRect(hwnd, &r);
188             width = r.right - r.left;
189             height = r.bottom - r.top;
190             deltax = deltay = 0;
191             InvalidateRect( hwnd, NULL, TRUE );
192           }
193           break;
194
195
196         case IDM_LEFT:
197           deltax += 100;
198           InvalidateRect( hwnd, NULL, TRUE );
199           break;
200         case IDM_RIGHT:
201           deltax -= 100;
202           InvalidateRect( hwnd, NULL, TRUE );
203           break;
204         case IDM_UP:
205           deltay += 100;
206           InvalidateRect( hwnd, NULL, TRUE );
207           break;
208         case IDM_DOWN:
209           deltay -= 100;
210           InvalidateRect( hwnd, NULL, TRUE );
211           break;
212
213         case IDM_EXIT:
214           DestroyWindow(hwnd);
215           break;
216
217         default:
218           return DefWindowProc(hwnd, uMessage, wparam, lparam);
219         }
220       break;
221
222     case WM_DESTROY:  /* message: window being destroyed */
223       PostQuitMessage(0);
224       break;
225
226     default:          /* Passes it on if unprocessed */
227       return DefWindowProc(hwnd, uMessage, wparam, lparam);
228     }
229     return 0;
230 }
231
232 static BOOL InitApplication(HINSTANCE hInstance)
233 {
234   WNDCLASSEX wc;
235
236   /* Load the application description strings */
237   LoadString(hInstance, IDS_DESCRIPTION, szTitle, sizeof(szTitle));
238
239   /* Fill in window class structure with parameters that describe the
240      main window */
241
242   wc.cbSize = sizeof(WNDCLASSEX);
243
244   /* Load small icon image */
245   wc.hIconSm = LoadImage(hInstance, MAKEINTRESOURCEA(IDI_APPICON), IMAGE_ICON, 16, 16, 0);
246
247   wc.style         = CS_HREDRAW | CS_VREDRAW;             /* Class style(s) */
248   wc.lpfnWndProc   = WndProc;                             /* Window Procedure */
249   wc.cbClsExtra    = 0;                          /* No per-class extra data */
250   wc.cbWndExtra    = 0;                         /* No per-window extra data */
251   wc.hInstance     = hInstance;                      /* Owner of this class */
252   wc.hIcon         = LoadIcon(hInstance, szAppName);  /* Icon name from .rc */
253   wc.hCursor       = LoadCursor(NULL, IDC_ARROW);                 /* Cursor */
254   wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);           /* Default color */
255   wc.lpszMenuName  = szAppName;                       /* Menu name from .rc */
256   wc.lpszClassName = szAppName;                      /* Name to register as */
257
258   /* Register the window class and return FALSE if unsuccessful */
259
260   if (!RegisterClassEx(&wc))
261     {
262       if (!RegisterClass((LPWNDCLASS)&wc.style))
263       return FALSE;
264     }
265
266   /* Call module specific initialization functions here */
267
268   return TRUE;
269 }
270
271 static BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
272 {
273     HWND hwnd;
274
275     /* Save the instance handle in a global variable for later use */
276     hInst = hInstance;
277
278     /* Create main window */
279     hwnd = CreateWindow(szAppName,           /* See RegisterClass() call */
280                         szTitle,             /* window title */
281                         WS_OVERLAPPEDWINDOW, /* Window style */
282                         CW_USEDEFAULT, 0,    /* positioning */
283                         CW_USEDEFAULT, 0,    /* size */
284                         NULL,                /* Overlapped has no parent */
285                         NULL,                /* Use the window class menu */
286                         hInstance,
287                         NULL);
288
289     if (!hwnd)
290         return FALSE;
291
292     /* Call module specific instance initialization functions here */
293
294     /* show the window, and paint it for the first time */
295     ShowWindow(hwnd, nCmdShow);
296     UpdateWindow(hwnd);
297
298     return TRUE;
299 }
300
301 int APIENTRY WinMain(HINSTANCE hInstance,
302                      HINSTANCE hPrevInstance,
303                      LPSTR     lpCmdLine,
304                      int       nCmdShow)
305 {
306     MSG msg;
307     HANDLE hAccelTable;
308
309     /* Other instances of app running? */
310     if (!hPrevInstance)
311     {
312       /* stuff to be done once */
313       if (!InitApplication(hInstance))
314       {
315         return FALSE;      /* exit */
316       }
317     }
318
319     /* stuff to be done every time */
320     if (!InitInstance(hInstance, nCmdShow))
321     {
322       return FALSE;
323     }
324
325     hAccelTable = LoadAccelerators(hInstance, szAppName);
326
327     /* Main loop */
328     /* Acquire and dispatch messages until a WM_QUIT message is received */
329     while (GetMessage(&msg, NULL, 0, 0))
330     {
331       /* Add other Translation functions (for modeless dialogs
332       and/or MDI windows) here. */
333
334       if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
335         {
336             TranslateMessage(&msg);
337             DispatchMessage(&msg);
338         }
339     }
340
341     /* Add module specific instance free/delete functions here */
342
343     /* Returns the value from PostQuitMessage */
344     return msg.wParam;
345 }