1 /* Part of XPCE --- The SWI-Prolog GUI toolkit
2
3 Author: Jan Wielemaker and Anjo Anjewierden
4 E-mail: jan@swi.psy.uva.nl
5 WWW: http://www.swi.psy.uva.nl/projects/xpce/
6 Copyright (c) 1996-2013, University of Amsterdam
7 All rights reserved.
8
9 Redistribution and use in source and binary forms, with or without
10 modification, are permitted provided that the following conditions
11 are met:
12
13 1. Redistributions of source code must retain the above copyright
14 notice, this list of conditions and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright
17 notice, this list of conditions and the following disclaimer in
18 the documentation and/or other materials provided with the
19 distribution.
20
21 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24 FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25 COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27 BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
31 ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32 POSSIBILITY OF SUCH DAMAGE.
33 */
34
35 #include "include.h"
36 #include <h/unix.h>
37
38 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
39 Taken from MSVC20/samples/win32/mfedit.h.
40 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
41
42 #define META32_SIGNATURE 0x464D4520 // ' EMF'
43 #define ALDUS_ID 0x9AC6CDD7
44
45 typedef struct
46 { DWORD key;
47 WORD hmf;
48 SMALL_RECT bbox;
49 WORD inch;
50 DWORD reserved;
51 WORD checksum;
52 } APMFILEHEADER;
53 typedef APMFILEHEADER * PAPMFILEHEADER;
54 #define APMSIZE 22
55
56 #ifndef MAXPATHLEN
57 #define MAXPATHLEN 1024
58 #endif
59
60 Class ClassWinMF; /* the class handle */
61
62 NewClass(win_mf) /* class structure */
63 ABSTRACT_GRAPHICAL
64 FileObj file; /* Associated file */
65 StringObj summary; /* Summary description */
66 HENHMETAFILE hmf; /* The metafile handle */
67 End;
68
69 static status getDimensionsWinMF(WinMF mf);
70 static status getMhfWinMF(WinMF mf);
71
72 static Chain WinMetaFiles; /* @win_metafiles */
73
74 static status
initialiseWinMF(WinMF mf,FileObj f)75 initialiseWinMF(WinMF mf, FileObj f)
76 { initialiseGraphical(mf, ZERO, ZERO, ZERO, ZERO);
77
78 if ( isDefault(f) )
79 f = (FileObj) NIL;
80
81 assign(mf, file, f);
82 mf->hmf = NULL;
83
84 if ( notNil(f) )
85 { if ( !getDimensionsWinMF(mf) )
86 fail;
87 }
88
89 return prependChain(WinMetaFiles, mf);
90 }
91
92
93 static status
closeWinMF(WinMF mf)94 closeWinMF(WinMF mf)
95 { if ( mf->hmf )
96 { DeleteEnhMetaFile(mf->hmf);
97
98 mf->hmf = NULL;
99 }
100
101 succeed;
102 }
103
104
105 static status
unlinkWinMF(WinMF mf)106 unlinkWinMF(WinMF mf)
107 { closeWinMF(mf);
108 deleteChain(WinMetaFiles, mf);
109
110 return unlinkGraphical((Graphical) mf);
111 }
112
113
114 static void
closeAllWinMF(int rval)115 closeAllWinMF(int rval)
116 { if ( WinMetaFiles )
117 { Cell cell;
118
119 for_cell(cell, WinMetaFiles)
120 { WinMF mf = cell->value;
121
122 closeWinMF(mf);
123 }
124 }
125 }
126
127
128 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
129 Store/load windows metafile to/form file. Format:
130
131 * If the metafile has a file, just the slots and 'X'
132 * Otherwise, the slots, 'E', <size>, metafilebitx
133 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
134
135 static status
storeWinMF(WinMF mf,FileObj file)136 storeWinMF(WinMF mf, FileObj file)
137 { TRY(storeSlotsObject(mf, file));
138
139 if ( isNil(mf->file) && mf->hmf )
140 { UINT size;
141
142 if ( (size = GetEnhMetaFileBits(mf->hmf, 0, NULL)) )
143 { LPBYTE data = pceMalloc(size);
144 GetEnhMetaFileBits(mf->hmf, size, data);
145 Sputc('E', file->fd);
146 putstdw(size, file->fd);
147 Sfwrite(data, sizeof(char), size, file->fd);
148 pceFree(data);
149
150 succeed;
151 }
152 }
153
154 Sputc('X', file->fd);
155
156 succeed;
157 }
158
159
160 static status
loadFdWinMF(WinMF mf,IOSTREAM * fd,ClassDef def)161 loadFdWinMF(WinMF mf, IOSTREAM *fd, ClassDef def)
162 { TRY( loadSlotsObject(mf, fd, def) );
163 mf->hmf = NULL;
164
165 switch(Sgetc(fd))
166 { case 'X':
167 if ( notNil(mf->file) )
168 getDimensionsWinMF(mf);
169 break;
170 case 'E':
171 { UINT size = loadWord(fd);
172 LPBYTE data = pceMalloc(size);
173 Sfread(data, sizeof(char), size, fd);
174 mf->hmf = SetEnhMetaFileBits(size, data);
175 pceFree(data);
176 break;
177 }
178 default:
179 assert(0);
180 }
181
182 return prependChain(WinMetaFiles, mf);
183 }
184
185
186 static status
copyWinMF(WinMF to,WinMF from)187 copyWinMF(WinMF to, WinMF from)
188 { copyGraphical(to, from);
189
190 assign(to, file, NIL); /* ??? */
191 assign(to, summary, from->summary);
192
193 if ( from->hmf )
194 to->hmf = CopyEnhMetaFile(from->hmf, NULL);
195 else
196 from->hmf = NULL;
197
198 succeed;
199 }
200
201
202 static status
cloneWinMF(WinMF from,WinMF clone)203 cloneWinMF(WinMF from, WinMF clone)
204 { clonePceSlots(from, clone);
205 if ( from->hmf )
206 clone->hmf = CopyEnhMetaFile(from->hmf, NULL);
207
208 succeed;
209 }
210
211
212 void
set_area_from_rectl(Area a,RECTL * r)213 set_area_from_rectl(Area a, RECTL *r)
214 { assign(a, x, toInt(r->left));
215 assign(a, y, toInt(r->top));
216 assign(a, w, toInt(1 + r->right - r->left));
217 assign(a, h, toInt(1 + r->bottom - r->top));
218 }
219
220
221 static status
getDimensionsWinMF(WinMF mf)222 getDimensionsWinMF(WinMF mf)
223 { UINT hdrsize;
224
225 if ( !mf->hmf )
226 { if ( !getMhfWinMF(mf) )
227 fail;
228 }
229
230 if ( (hdrsize = GetEnhMetaFileHeader(mf->hmf, 0, NULL)) )
231 { ENHMETAHEADER *hdr = alloca(hdrsize);
232
233 GetEnhMetaFileHeader(mf->hmf, hdrsize, hdr);
234 set_area_from_rectl(mf->area, &hdr->rclBounds);
235 if ( hdr->nDescription )
236 { char *s = (char *)hdr + hdr->offDescription;
237 string str;
238
239 str_set_n_ascii(&str, hdr->nDescription, s);
240 assign(mf, summary, StringToString(&str));
241 }
242
243 succeed;
244 }
245
246 fail;
247 }
248
249
250 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
251 Taken from MSVC20/samples/win32/mfedit.c and modified to fit into XPCE's
252 format.
253 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
254
255 static HENHMETAFILE
hemfLoadMetafile(WinMF mf,const char * szFile)256 hemfLoadMetafile(WinMF mf, const char *szFile)
257 { HMETAFILE ghmf, hmf;
258 UINT uiSize;
259 LPVOID pvData;
260 HDC hDCDrawSurf;
261 HENHMETAFILE hemf = NULL;
262
263 HANDLE hFile, hMapFile;
264 LPVOID pMapFile;
265 LPENHMETAHEADER pemh;
266
267 BOOL bSuccess;
268
269 bSuccess = TRUE;
270
271 if ( (hFile=CreateFile(szFile,
272 GENERIC_READ, FILE_SHARE_READ, NULL,
273 OPEN_EXISTING, FILE_ATTRIBUTE_READONLY,
274 NULL)) == (HANDLE)-1 )
275 { errorPce(mf, NAME_winMetafile, NAME_open, APIError());
276 return 0L;
277 }
278
279 /* Create a map file of the opened file */
280
281 if ( (hMapFile=CreateFileMapping(hFile, NULL,
282 PAGE_READONLY, 0, 0, "MapF")) == NULL )
283 { errorPce(mf, NAME_winMetafile, NAME_map, APIError());
284 bSuccess = FALSE;
285 goto ErrorExit1;
286 }
287
288 /* Map a view of the whole file */
289
290 if ( (pMapFile = MapViewOfFile(hMapFile, FILE_MAP_READ, 0, 0, 0)) == NULL)
291 { errorPce(mf, NAME_winMetafile, NAME_view, APIError());
292 bSuccess = FALSE;
293 goto ErrorExit2;
294 }
295
296 /* First check that if it is an enhanced metafile */
297
298 pemh = (LPENHMETAHEADER) pMapFile;
299 if ( pemh->dSignature == META32_SIGNATURE )
300 { hemf = GetEnhMetaFile(szFile);
301 goto HLM_EXIT;
302 }
303
304 /* If it has an ALDUS header skip it
305 Notice: APMSIZE is used because the HANDLE and RECT of the structure
306 depends on the environment
307 */
308 if ( *((LPDWORD)pemh) == ALDUS_ID )
309 { //METAFILEPICT mfp;
310 PAPMFILEHEADER aldushdr = (PAPMFILEHEADER) pMapFile;
311
312 DEBUG(NAME_winMetafile,
313 Cprintf("ALDUS Header: inch = %d, size = %d x %d\n",
314 aldushdr->inch,
315 aldushdr->bbox.Right,
316 aldushdr->bbox.Bottom));
317
318 uiSize = *((LPDWORD) ((PBYTE)pMapFile + APMSIZE + 6));
319 hDCDrawSurf = GetDC(NULL);
320
321 /* Notice: mtSize is size of the file in word.
322 if LPMETAFILEPICT is NULL
323 MM_ANISOTROPIC mode and default device size will be used.
324 */
325 hemf = SetWinMetaFileBits(uiSize*2L,
326 (PBYTE)pMapFile + APMSIZE, hDCDrawSurf, NULL);
327 #if 0
328 switch ( aldushdr->inch )
329 { /* !!! End up in an upside down image */
330 case 1440:
331 mfp.mm = MM_TWIPS;
332 break;
333 case 2540:
334 mfp.mm = MM_HIMETRIC;
335 break;
336 case 254:
337 mfp.mm = MM_LOMETRIC;
338 break;
339 case 1000:
340 mfp.mm = MM_HIENGLISH;
341 break;
342 case 100:
343 mfp.mm = MM_LOENGLISH;
344 break;
345 default:
346 mfp.mm = MM_ANISOTROPIC;
347 mfp.xExt = (((PAPMFILEHEADER) pMapFile)->bbox.Right -
348 ((PAPMFILEHEADER) pMapFile)->bbox.Left) *
349 ((PAPMFILEHEADER) pMapFile)->inch * 2560;
350 mfp.yExt = (((PAPMFILEHEADER) pMapFile)->bbox.Bottom -
351 ((PAPMFILEHEADER) pMapFile)->bbox.Top) *
352 ((PAPMFILEHEADER) pMapFile)->inch * 2560;
353 break;
354 }
355 mfp.hMF = 0;
356 hemf = SetWinMetaFileBits(uiSize*2L,
357 (PBYTE)pMapFile + APMSIZE, hDCDrawSurf, &mfp);
358 #endif
359
360 if ( !hemf )
361 { errorPce(mf, NAME_winMetafile,
362 CtoName("SetWinMetaFileBits"), APIError());
363 }
364
365 ghmf = SetMetaFileBitsEx(uiSize*2L, (PBYTE)pMapFile + APMSIZE);
366 if ( !ghmf )
367 { errorPce(mf, NAME_winMetafile,
368 CtoName("SetMetaFileBitsEx"), APIError());
369 }
370
371 ReleaseDC(NULL, hDCDrawSurf);
372
373 goto HLM_EXIT;
374 }
375
376 /* It is a Windows 3x format metafile (hopefully) */
377
378 if (!(hmf = GetMetaFile((LPCSTR)szFile)))
379 { errorPce(mf, NAME_winMetafile, CtoName("GetMetaFile"), APIError());
380 bSuccess = FALSE;
381 goto ErrorExit3;
382 }
383
384 if ( !(uiSize = GetMetaFileBitsEx(hmf, 0, NULL)) )
385 { errorPce(mf, NAME_winMetafile, CtoName("GetMetaFileBitsEx-1"), APIError());
386 return NULL;
387 }
388
389 if ((pvData = (LPVOID) LocalAlloc(LMEM_FIXED, uiSize)) == NULL)
390 { errorPce(mf, NAME_winMetafile, CtoName("alloc"), APIError());
391 bSuccess = FALSE;
392 goto ErrorExit3;
393 }
394
395 if (!(uiSize = GetMetaFileBitsEx(hmf, uiSize, pvData)))
396 { errorPce(mf, NAME_winMetafile, CtoName("GetMetaFileBitsEx-2"), APIError());
397 bSuccess = FALSE;
398 goto ErrorExit3;
399 }
400
401 DeleteMetaFile(hmf);
402
403 hDCDrawSurf = GetDC(NULL);
404 hemf = SetWinMetaFileBits(uiSize, (LPBYTE)pvData, hDCDrawSurf, NULL);
405 ghmf = SetMetaFileBitsEx(uiSize, (LPBYTE) pvData);
406
407 LocalFree(pvData);
408
409 ReleaseDC(NULL, hDCDrawSurf);
410
411 HLM_EXIT:
412 ErrorExit3:
413 UnmapViewOfFile(pMapFile);
414
415 ErrorExit2:
416 CloseHandle(hMapFile);
417 ErrorExit1:
418 CloseHandle(hFile);
419
420 if (bSuccess)
421 return hemf;
422 else
423 return 0L;
424 }
425
426
427 static status
getMhfWinMF(WinMF mf)428 getMhfWinMF(WinMF mf)
429 { if ( !mf->hmf && notNil(mf->file) )
430 { CharArray path = getClassVariableValueObject(mf, NAME_path);
431
432 if ( findFile(mf->file, path ? path : (CharArray) DEFAULT, NAME_read) )
433 { char *rawfn = strName(getOsNameFile(mf->file));
434
435 #if O_XOS
436 char fn[MAXPATHLEN];
437 if ( !_xos_os_filename(rawfn, fn, sizeof(fn)) )
438 return errorPce(mf, NAME_representation, NAME_nameTooLong);
439 #else
440 char *fn = rawfn;
441 #endif
442
443 if ( (mf->hmf = hemfLoadMetafile(mf, fn)) )
444 succeed;
445 }
446 }
447
448 fail;
449 }
450
451
452 static status
RedrawAreaWinMF(WinMF mf,Area a)453 RedrawAreaWinMF(WinMF mf, Area a)
454 { int x, y, w, h;
455
456 initialiseDeviceGraphical(mf, &x, &y, &w, &h);
457
458 if ( mf->hmf )
459 r_winmf(mf->hmf, x, y, w, h);
460
461 return RedrawAreaGraphical(mf, a);
462 }
463
464 /*******************************
465 * PAINTING IN IT *
466 *******************************/
467
468 static status
drawInWinMF(WinMF mf,Any obj,Point pos)469 drawInWinMF(WinMF mf, Any obj, Point pos)
470 { Int oldx, oldy;
471 Device dev;
472 wchar_t *fn;
473 wchar_t *descr;
474 Area bb;
475
476 if ( notDefault(pos) && instanceOfObject(obj, ClassGraphical) )
477 { Graphical gr = obj;
478
479 oldx = gr->area->x;
480 oldy = gr->area->y;
481 dev = gr->device;
482 gr->device = NIL;
483 setGraphical(gr, pos->x, pos->y, DEFAULT, DEFAULT);
484 } else
485 { oldx = oldy = DEFAULT;
486 dev = NIL; /* keep compiler happy */
487 }
488
489 if ( isNil(mf->file) )
490 fn = NULL;
491 else
492 fn = charArrayToWC((CharArray)getOsNameFile(mf->file), NULL);
493
494 if ( isNil(mf->summary) )
495 descr = NULL;
496 else /* application\0summary\0\0 */
497 { size_t slen;
498 wchar_t *summary, *s;
499 wchar_t *app = L"XPCE";
500
501 summary = charArrayToWC((CharArray)mf->summary, &slen);
502 descr = alloca((slen + wcslen(app) + 3)*sizeof(wchar_t));
503 wcscpy(descr, summary);
504 s = descr + slen;
505 *s++ = L'\0';
506 wcscpy(s, app);
507 s += wcslen(app) + 1;
508 *s++ = L'\0';
509 }
510
511 if ( instanceOfObject(obj, ClassGraphical) )
512 { Graphical gr = obj;
513
514 ComputeGraphical(gr);
515 bb = gr->area;
516 } else /* if ( instanceOfObject(obj, ClassChain) ) */
517 { Cell cell;
518
519 bb = answerObject(ClassArea, EAV);
520 for_cell(cell, (Chain)obj)
521 { Graphical gr = cell->value;
522
523 if ( instanceOfObject(gr, ClassGraphical) )
524 { ComputeGraphical(gr);
525 unionNormalisedArea(bb, gr->area);
526 }
527 }
528 }
529
530
531 CHANGING_GRAPHICAL(mf,
532 d_winmf(fn,
533 valInt(bb->x), valInt(bb->y), valInt(bb->w), valInt(bb->h),
534 descr);
535
536 if ( instanceOfObject(obj, ClassGraphical) )
537 { Graphical gr = obj;
538
539 RedrawArea(gr, gr->area);
540 } else
541 { Chain ch = obj;
542 Cell cell;
543
544 for_cell(cell, ch)
545 { if ( instanceOfObject(cell->value, ClassGraphical) )
546 { Graphical gr = cell->value;
547
548 RedrawArea(gr, gr->area);
549 }
550 }
551 }
552
553 mf->hmf = d_winmfdone();
554 copyArea(mf->area, bb);
555 doneObject(bb);
556 changedEntireImageGraphical(mf));
557
558 if ( notDefault(oldx) )
559 { Graphical gr = obj;
560
561 setGraphical(gr, oldx, oldy, DEFAULT, DEFAULT);
562 gr->device = dev;
563 }
564
565 succeed;
566 }
567
568
569 static status
saveALDUS(WinMF mf,HMETAFILE ghmf,FileObj file,int width,int height,int mapping)570 saveALDUS(WinMF mf, HMETAFILE ghmf, FileObj file,
571 int width, int height, int mapping)
572 { UINT uiSize;
573 int rval = TRUE;
574
575 uiSize = GetMetaFileBitsEx(ghmf, 0, NULL);
576
577 if ( !send(file, NAME_kind, NAME_binary, EAV) ||
578 !send(file, NAME_open, NAME_write, EAV) )
579 fail;
580
581 if ( uiSize )
582 { APMFILEHEADER AldHdr;
583 WORD *p;
584 void * buf;
585
586 AldHdr.key = ALDUS_ID;
587 AldHdr.hmf = 0; // Unused; must be zero
588 AldHdr.bbox.Left = 0; // in metafile units
589 AldHdr.bbox.Top = 0;
590
591 switch (mapping)
592 { case MM_HIENGLISH:
593 AldHdr.inch = 1000;
594 AldHdr.bbox.Right = (SHORT)width;
595 AldHdr.bbox.Bottom = (SHORT)height;
596 break;
597 case MM_HIMETRIC:
598 AldHdr.inch = 1440;
599 AldHdr.bbox.Right = (SHORT)(width / 2540 * 1440);
600 AldHdr.bbox.Bottom = (SHORT)(height / 2540 * 1440);
601 break;
602 case MM_LOENGLISH:
603 AldHdr.inch = 100;
604 AldHdr.bbox.Right = (SHORT)width;
605 AldHdr.bbox.Bottom = (SHORT)height;
606 break;
607 case MM_LOMETRIC:
608 AldHdr.inch = 254;
609 AldHdr.bbox.Right = (SHORT)width;
610 AldHdr.bbox.Bottom = (SHORT)height;
611 break;
612 case MM_TEXT:
613 { HDC hdc = GetDC(NULL);
614
615 AldHdr.inch = (WORD) ((float)GetDeviceCaps(hdc, HORZRES) * 25.4 /
616 (float)GetDeviceCaps(hdc, HORZSIZE));
617 AldHdr.bbox.Right = (SHORT)width;
618 AldHdr.bbox.Bottom = (SHORT)height;
619
620 DEBUG(NAME_winMetafile,
621 Cprintf("HORZRES = %d, HORZSIZE = %d, inch = %d right = %d\n",
622 GetDeviceCaps(hdc, HORZRES),
623 GetDeviceCaps(hdc, HORZSIZE),
624 AldHdr.inch,
625 AldHdr.bbox.Right));
626
627 ReleaseDC(NULL, hdc);
628 break;
629 }
630 case MM_TWIPS:
631 AldHdr.inch = 1440;
632 AldHdr.bbox.Right = (SHORT)width;
633 AldHdr.bbox.Bottom = (SHORT)height;
634 break;
635 default:
636 AldHdr.inch = 1440;
637 AldHdr.bbox.Right = (SHORT)((width * 1440) / 2540);
638 AldHdr.bbox.Bottom = (SHORT)((height * 1440) / 2540);
639 break;
640 }
641
642
643 AldHdr.reserved = 0;
644 AldHdr.checksum = 0;
645 for (p = (WORD *)&AldHdr; p < (WORD *)&(AldHdr.checksum); ++p)
646 AldHdr.checksum ^= *p;
647
648 if ( Sfwrite(&AldHdr, APMSIZE, 1, file->fd) != 1 )
649 { reportErrorFile(file);
650 closeFile(file);
651 fail;
652 }
653
654 buf = pceMalloc(uiSize);
655 GetMetaFileBitsEx(ghmf, uiSize, buf);
656 if ( Sfwrite(buf, sizeof(char), uiSize, file->fd) != uiSize )
657 { reportErrorFile(file);
658 closeFile(file);
659 pceFree(buf);
660
661 fail;
662 }
663 pceFree(buf);
664
665 return closeFile(file);
666 }
667
668 return rval;
669 }
670
671
672 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
673 Get a Windows 3.x format metafile from the XPCE object. I'm not sure
674 whether the allocated memory block should be freed or not. Some
675 analogous cases in mfedit indicate me SetMetaFileBitsEx() probably
676 copies the data, so the code below should be fine.
677 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
678
679 static HMETAFILE
convert_enh_metafile(WinMF mf,HDC hdc)680 convert_enh_metafile(WinMF mf, HDC hdc)
681 { void *data = NULL;
682 int len, l2;
683 int fnMapMode = MM_ANISOTROPIC;
684 int omap = SetMapMode(hdc, fnMapMode);
685 HMETAFILE hmf;
686 /* get old format bits */
687
688 if ( !(len = GetWinMetaFileBits(mf->hmf, 0, NULL, fnMapMode, hdc)) )
689 { errorPce(mf, NAME_winMetafile,
690 CtoName("GetWinMetaFileBits"), APIError());
691 return NULL;
692 }
693
694 data = pceMalloc(len);
695 l2 = GetWinMetaFileBits(mf->hmf, len, data, fnMapMode, hdc);
696 SetMapMode(hdc, omap);
697 assert(l2 == len);
698 /* make old format metafile */
699 hmf = SetMetaFileBitsEx(l2, data);
700 pceFree(data);
701
702 return hmf;
703 }
704
705
706
707 static status
saveWinMF(WinMF mf,FileObj file,Name format)708 saveWinMF(WinMF mf, FileObj file, Name format)
709 { char *rawfn = strName(getOsNameFile(file));
710 #if O_XOS
711 char fn[MAXPATHLEN];
712 if ( !_xos_os_filename(rawfn, fn, sizeof(fn)) )
713 return errorPce(mf, NAME_representation, NAME_nameTooLong);
714 #else
715 char *fn = rawfn;
716 #endif
717
718 if ( !mf->hmf )
719 fail;
720
721
722 if ( isDefault(format) )
723 { if ( suffixCharArray((CharArray)file->name,
724 (CharArray)CtoName(".wmf"),
725 ON) )
726 format = NAME_aldus;
727 else if ( suffixCharArray((CharArray)file->name,
728 (CharArray)CtoName(".emf"),
729 ON) )
730 format = NAME_emf;
731 else
732 format = getClassVariableValueObject(mf, NAME_format);
733 }
734
735 if ( format == NAME_wmf || format == NAME_aldus )
736 { HDC hdc = GetDC(NULL);
737 HMETAFILE ohmf = convert_enh_metafile(mf, hdc);
738 HMETAFILE ohmf2 = NULL;
739 status rval = SUCCEED;
740
741 ReleaseDC(NULL, hdc);
742
743 if ( format == NAME_wmf )
744 { if ( !(ohmf2 = CopyMetaFile(ohmf, fn)) )
745 { DeleteMetaFile(ohmf);
746 return errorPce(mf, NAME_winMetafile,
747 CtoName("CopyMetaFile"), APIError());
748 }
749 } else /* ALDUS */
750 rval = saveALDUS(mf, ohmf, file,
751 valInt(mf->area->w), valInt(mf->area->h),
752 MM_TEXT);
753
754 DeleteMetaFile(ohmf2);
755 DeleteMetaFile(ohmf);
756
757 return rval;
758 } else /* save as enhanced format */
759 { HENHMETAFILE h2;
760
761 if ( (h2 = CopyEnhMetaFile(mf->hmf, fn)) )
762 { DeleteEnhMetaFile(h2);
763 succeed;
764 } else
765 return errorPce(mf, NAME_winMetafile,
766 CtoName("CopyEnhMetaFile"), APIError());
767 }
768 }
769
770 /*******************************
771 * WINDOWS CUT/PASTE *
772 *******************************/
773
774 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
775 Copy a metafile to the windows clipboard. I'm not really sure about the
776 immediate delete, but that is what mfedit is doing. Also, shouldn't this
777 use GlobalAlloc() somehow??
778 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
779
780 status
ws_on_clipboard_metafile(WinMF mf,Name type)781 ws_on_clipboard_metafile(WinMF mf, Name type)
782 { if ( mf->hmf )
783 { if ( type == NAME_emf )
784 { HENHMETAFILE hmftmp = CopyEnhMetaFile(mf->hmf, NULL);
785
786 if ( hmftmp )
787 { SetClipboardData(CF_ENHMETAFILE, hmftmp);
788 DeleteEnhMetaFile(hmftmp);
789
790 succeed;
791 }
792 } else /* if ( type == NAME_wmf ) */
793 { HGLOBAL hmem;
794 LPMETAFILEPICT lpmfp;
795 HDC hdc = GetDC(NULL);
796 int hmm = GetDeviceCaps(hdc, HORZSIZE);
797 int hpxl = GetDeviceCaps(hdc, HORZRES);
798 int vmm = GetDeviceCaps(hdc, VERTSIZE);
799 int vpxl = GetDeviceCaps(hdc, VERTRES);
800
801 if ( !(hmem = GlobalAlloc(GMEM_ZEROINIT|GMEM_MOVEABLE|GMEM_DDESHARE,
802 sizeof(METAFILEPICT))) )
803 { errorPce(mf, NAME_winMetafile, CtoName("GlobalAlloc"), APIError());
804 fail;
805 }
806
807 lpmfp = (LPMETAFILEPICT)GlobalLock(hmem);
808 lpmfp->mm = MM_ANISOTROPIC;
809
810 lpmfp->xExt = (valInt(mf->area->w)*hmm*100)/hpxl;
811 lpmfp->yExt = (valInt(mf->area->h)*vmm*100)/vpxl;
812 lpmfp->hMF = convert_enh_metafile(mf, hdc); /* Reclaim??? */
813
814 GlobalUnlock(hmem);
815 SetClipboardData(CF_METAFILEPICT, hmem);
816
817 ReleaseDC(NULL, hdc);
818 }
819 }
820
821 fail;
822 }
823
824
825 WinMF
CtoWinMetafile(HENHMETAFILE hmf)826 CtoWinMetafile(HENHMETAFILE hmf)
827 { WinMF mf = answerObject(ClassWinMF, EAV);
828
829 mf->hmf = hmf;
830 getDimensionsWinMF(mf);
831
832 answer(mf);
833 }
834
835
836 /*******************************
837 * CLASS DECLARATION *
838 *******************************/
839
840 /* Type declarations */
841
842 static char *T_drawIn[] =
843 { "graphical|chain", "at=[point]" };
844 static char *T_save[] =
845 { "in=file", "format=[{aldus,wmf,emf}]" };
846
847 /* Instance Variables */
848
849 static vardecl var_winmf[] =
850 { IV(NAME_file, "file*", IV_GET,
851 NAME_storage, "Associated physical file"),
852 IV(NAME_summary, "string*", IV_BOTH,
853 NAME_manual, "Description associated with the file"), /* TBD:group */
854 IV(NAME_handle, "alien:HENHMETAFILE", IV_NONE,
855 NAME_storage, "Handle to the Win32 metafile"),
856 };
857
858 /* Send Methods */
859
860 static senddecl send_winmf[] =
861 { SM(NAME_initialise, 1, "[file]*", initialiseWinMF,
862 DEFAULT, "Create box from width and height"),
863 SM(NAME_unlink, 0, NULL, unlinkWinMF,
864 DEFAULT, "Remove from @win_metafiles"),
865 SM(NAME_drawIn, 2, T_drawIn, drawInWinMF,
866 NAME_copy, "Paint graphical in metafile"),
867 SM(NAME_copy, 1, "win_metafile", copyWinMF,
868 NAME_copy, "Copy the argument to the receiver"),
869 SM(NAME_save, 2, T_save, saveWinMF,
870 NAME_file, "Save contents in specified file"),
871 };
872
873 /* Get Methods */
874
875 #define get_winmf NULL
876 /*
877 static getdecl get_winmf[] =
878 {
879 };
880 */
881
882 /* Resources */
883
884 static classvardecl rc_winmf[] =
885 { RC(NAME_path, "string",
886 "\".:mf:~/lib/mf:$PCEHOME/mf:\"",
887 "Search path for loading Windows metafiles"),
888 RC(NAME_format, "{emf,wmf,aldus}",
889 "aldus",
890 "Default save format")
891 };
892
893 /* Class Declaration */
894
895 static Name winmf_termnames[] = { NAME_file };
896
897 ClassDecl(winmf_decls,
898 var_winmf, send_winmf, get_winmf, rc_winmf,
899 1, winmf_termnames,
900 "$Rev$");
901
902
903 status
makeClassWinMF(Class class)904 makeClassWinMF(Class class)
905 { declareClass(class, &winmf_decls);
906
907 setRedrawFunctionClass(class, RedrawAreaWinMF);
908 WinMetaFiles = globalObject(NAME_winMetafiles, ClassChain, EAV);
909 setLoadStoreFunctionClass(class, loadFdWinMF, storeWinMF);
910 setCloneFunctionClass(class, cloneWinMF);
911
912 at_pce_exit(closeAllWinMF, ATEXIT_FIFO);
913
914 succeed;
915 }
916