-Fixed MESSAGE functions that were thunking down to 16 bits implementation.
[wine] / graphics / psdrv / ps.c
1 /*
2  *      PostScript output functions
3  *
4  *      Copyright 1998  Huw D M Davies
5  *
6  */
7
8 #include <ctype.h>
9 #include <string.h>
10 #include "windows.h"
11 #include "psdrv.h"
12 #include "print.h"
13 #include "debug.h"
14
15 static char psheader[] = /* title llx lly urx ury orientation */
16 "%%!PS-Adobe-3.0\n"
17 "%%%%Creator: Wine PostScript Driver\n"
18 "%%%%Title: %s\n"
19 "%%%%BoundingBox: %d %d %d %d\n"
20 "%%%%Pages: (atend)\n"
21 "%%%%Orientation: %s\n"
22 "%%%%EndComments\n";
23
24 static char psbeginprolog[] = 
25 "%%BeginProlog\n";
26
27 static char psendprolog[] =
28 "%%EndProlog\n";
29
30 static char psvectorstart[] =
31 "/ANSIEncoding [\n";
32
33 static char psvectorend[] =
34 "] def\n";
35
36 static char psprolog[] = /* output ANSIEncoding vector first */
37 "/reencodefont {\n"
38 "  findfont\n"
39 "  dup length dict begin\n"
40 "  {1 index /FID ne {def} {pop pop} ifelse} forall\n"
41 "  /Encoding ANSIEncoding def\n"
42 "  currentdict\n"
43 "  end\n"
44 "  definefont pop\n"
45 "} bind def\n"
46 "/tmpmtrx matrix def\n"
47 "/hatch {\n"
48 "  pathbbox\n"
49 "  /b exch def /r exch def /t exch def /l exch def /gap 32 def\n"
50 "  l cvi gap idiv gap mul\n"
51 "  gap\n"
52 "  r cvi gap idiv gap mul\n"
53 "  {t moveto 0 b t sub rlineto}\n"
54 "  for\n"
55 "} bind def\n";
56
57 static char psbeginsetup[] =
58 "%%BeginSetup\n";
59
60 static char psendsetup[] =
61 "%%EndSetup\n";
62
63 static char psbeginfeature[] = /* feature, value */
64 "mark {\n"
65 "%%%%BeginFeature: %s %s\n";
66
67 static char psendfeature[] =
68 "\n%%EndFeature\n"
69 "} stopped cleartomark\n";
70
71 static char psnewpage[] = /* name, number, xres, yres, xtrans, ytrans, rot */
72 "%%%%Page: %s %d\n"
73 "%%%%BeginPageSetup\n"
74 "/pgsave save def\n"
75 "72 %d div 72 %d div scale\n"
76 "%d %d translate\n"
77 "1 -1 scale\n"
78 "%d rotate\n"
79 "%%%%EndPageSetup\n";
80
81 static char psendpage[] =
82 "pgsave restore\n"
83 "showpage\n";
84
85 static char psfooter[] = /* pages */
86 "%%%%Trailer\n"
87 "%%%%Pages: %d\n"
88 "%%%%EOF\n";
89
90 static char psmoveto[] = /* x, y */
91 "%d %d moveto\n";
92
93 static char pslineto[] = /* x, y */
94 "%d %d lineto\n";
95
96 static char psstroke[] = 
97 "stroke\n";
98
99 static char psrectangle[] = /* x, y, width, height, -width */
100 "%d %d moveto\n"
101 "%d 0 rlineto\n"
102 "0 %d rlineto\n"
103 "%d 0 rlineto\n"
104 "closepath\n";
105
106 static char psshow[] = /* string */
107 "(%s) show\n";
108
109 static char pssetfont[] = /* fontname, xscale, yscale, ascent, escapement */
110 "/%s findfont\n"
111 "[%d 0 0 %d 0 0]\n"
112 "%d 10 div matrix rotate\n"
113 "matrix concatmatrix\n"
114 "makefont setfont\n";
115
116 static char pssetlinewidth[] = /* width */
117 "%d setlinewidth\n";
118
119 static char pssetdash[] = /* dash, offset */
120 "[%s] %d setdash\n";
121
122 static char pssetgray[] = /* gray */
123 "%.2f setgray\n";
124
125 static char pssetrgbcolor[] = /* r, g, b */
126 "%.2f %.2f %.2f setrgbcolor\n";
127
128 static char psarc[] = /* x, y, w, h, ang1, ang2 */
129 "tmpmtrx currentmatrix pop\n"
130 "%d %d translate\n"
131 "%d %d scale\n"
132 "0 0 0.5 %.1f %.1f arc\n"
133 "tmpmtrx setmatrix\n";
134
135 static char psgsave[] =
136 "gsave\n";
137
138 static char psgrestore[] =
139 "grestore\n";
140
141 static char psfill[] =
142 "fill\n";
143
144 static char pseofill[] =
145 "eofill\n";
146
147 static char psclosepath[] =
148 "closepath\n";
149
150 static char psclip[] =
151 "clip\n";
152
153 static char pseoclip[] =
154 "eoclip\n";
155
156 static char pshatch[] =
157 "hatch\n";
158
159 static char psrotate[] = /* ang */
160 "%.1f rotate\n";
161
162 char *PSDRV_ANSIVector[256] = {
163 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
164 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 
165 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
166 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
167 "space",        "exclam",       "quotedbl",     "numbersign",
168 "dollar",       "percent",      "ampersand",    "quotesingle",
169 "parenleft",    "parenright",   "asterisk",     "plus",
170 "comma",        "hyphen",       "period",       "slash",
171 "zero",         "one",          "two",          "three",
172 "four",         "five",         "six",          "seven",
173 "eight",        "nine",         "colon",        "semicolon",
174 "less",         "equal",        "greater",      "question",
175 "at",           "A",            "B",            "C",
176 "D",            "E",            "F",            "G",
177 "H",            "I",            "J",            "K",
178 "L",            "M",            "N",            "O",
179 "P",            "Q",            "R",            "S",
180 "T",            "U",            "V",            "W",
181 "X",            "Y",            "Z",            "bracketleft",
182 "backslash",    "bracketright", "asciicircum",  "underscore",
183 "grave",        "a",            "b",            "c",
184 "d",            "e",            "f",            "g",
185 "h",            "i",            "j",            "k",
186 "l",            "m",            "n",            "o",
187 "p",            "q",            "r",            "s",
188 "t",            "u",            "v",            "w",
189 "x",            "y",            "z",            "braceleft",
190 "bar",          "braceright",   "asciitilde",   NULL,
191 NULL,           NULL,           NULL,           NULL,
192 NULL,           NULL,           NULL,           NULL,
193 NULL,           NULL,           NULL,           NULL,
194 NULL,           NULL,           NULL,           NULL,
195 NULL,           "quoteleft",    "quoteright",   NULL,
196 NULL,           NULL,           NULL,           NULL,
197 NULL,           NULL,           NULL,           NULL,
198 NULL,           NULL,           NULL,           NULL,
199 NULL,           "exclamdown",   "cent",         "sterling",
200 "currency",     "yen",          "brokenbar",    "section",
201 "dieresis",     "copyright",    "ordfeminine",  "guillemotleft",
202 "logicalnot",   "hyphen",       "registered",   "macron",
203 "degree",       "plusminus",    "twosuperior",  "threesuperior",
204 "acute",        "mu",           "paragraph",    "periodcentered",
205 "cedilla",      "onesuperior",  "ordmasculine", "guillemotright",
206 "onequarter",   "onehalf",      "threequarters","questiondown",
207 "Agrave",       "Aacute",       "Acircumflex",  "Atilde",
208 "Adieresis",    "Aring",        "AE",           "Ccedilla",
209 "Egrave",       "Eacute",       "Ecircumflex",  "Edieresis",
210 "Igrave",       "Iacute",       "Icircumflex",  "Idieresis",
211 "Eth",          "Ntilde",       "Ograve",       "Oacute",
212 "Ocircumflex",  "Otilde",       "Odieresis",    "multiply",
213 "Oslash",       "Ugrave",       "Uacute",       "Ucircumflex",
214 "Udieresis",    "Yacute",       "Thorn",        "germandbls",
215 "agrave",       "aacute",       "acircumflex",  "atilde",
216 "adieresis",    "aring",        "ae",           "ccedilla",
217 "egrave",       "eacute",       "ecircumflex",  "edieresis",
218 "igrave",       "iacute",       "icircumflex",  "idieresis",
219 "eth",          "ntilde",       "ograve",       "oacute",
220 "ocircumflex",  "otilde",       "odieresis",    "divide",
221 "oslash",       "ugrave",       "uacute",       "ucircumflex",
222 "udieresis",    "yacute",       "thorn",        "ydieresis"
223 };
224
225
226 char psreencodefont[] = /* newfontname basefontname*/
227 "/%s /%s reencodefont\n";
228
229
230 int PSDRV_WriteSpool(DC *dc, LPSTR lpData, WORD cch)
231 {
232     PSDRV_PDEVICE *physDev = (PSDRV_PDEVICE *)dc->physDev;
233
234     if(physDev->job.NeedPageHeader) {
235         physDev->job.PageNo++;
236         if( !PSDRV_WriteNewPage(dc) )
237             return FALSE;
238         physDev->job.NeedPageHeader = FALSE;
239     }
240     return WriteSpool( physDev->job.hJob, lpData, cch );
241 }
242
243
244 INT32 PSDRV_WriteFeature(HANDLE16 hJob, char *feature, char *value,
245                          char *invocation)
246 {
247
248     char *buf = (char *)HeapAlloc( PSDRV_Heap, 0, sizeof(psheader) +
249                              strlen(feature) + strlen(value));
250
251
252     sprintf(buf, psbeginfeature, feature, value);
253     WriteSpool( hJob, buf, strlen(buf) );
254
255     WriteSpool( hJob, invocation, strlen(invocation) );
256
257     WriteSpool( hJob, psendfeature, strlen(psendfeature) );
258     
259     HeapFree( PSDRV_Heap, 0, buf );
260     return 1;
261 }
262
263
264
265 INT32 PSDRV_WriteHeader( DC *dc, char *title, int len )
266 {
267     PSDRV_PDEVICE *physDev = (PSDRV_PDEVICE *)dc->physDev;
268     char *buf, *titlebuf, *orient, vectbuf[256];
269     INPUTSLOT *slot;
270     PAGESIZE *page;
271     int urx, ury, i, j;
272
273     titlebuf = (char *)HeapAlloc( PSDRV_Heap, 0, len+1 );
274     if(!titlebuf) {
275         WARN(psdrv, "HeapAlloc failed\n");
276         return 0;
277     }
278     memcpy(titlebuf, title, len);
279     titlebuf[len] = '\0';
280
281     buf = (char *)HeapAlloc( PSDRV_Heap, 0, sizeof(psheader) + len + 30);
282     if(!buf) {
283         WARN(psdrv, "HeapAlloc failed\n");
284         HeapFree( PSDRV_Heap, 0, titlebuf );
285         return 0;
286     }
287
288     if(physDev->Devmode->dmPublic.dmOrientation == DMORIENT_LANDSCAPE) {
289       /* BBox co-ords are in default user co-ord system so urx < ury even in
290          landscape mode */
291         urx = (int) (dc->w.devCaps->vertSize * 72.0 / 25.4);
292         ury = (int) (dc->w.devCaps->horzSize * 72.0 / 25.4);
293         orient = "Landscape";
294     } else {
295         urx = (int) (dc->w.devCaps->horzSize * 72.0 / 25.4);
296         ury = (int) (dc->w.devCaps->vertSize * 72.0 / 25.4);
297         orient = "Portrait";
298     }
299
300     /* FIXME should do something better with BBox */
301
302     sprintf(buf, psheader, title, 0, 0, urx, ury, orient);              
303
304     if( WriteSpool( physDev->job.hJob, buf, strlen(buf) ) != 
305                                                      strlen(buf) ) {
306         WARN(psdrv, "WriteSpool error\n");
307         HeapFree( PSDRV_Heap, 0, titlebuf );
308         HeapFree( PSDRV_Heap, 0, buf );
309         return 0;
310     }
311     HeapFree( PSDRV_Heap, 0, titlebuf );
312     HeapFree( PSDRV_Heap, 0, buf );
313
314     WriteSpool( physDev->job.hJob, psbeginprolog, strlen(psbeginprolog) );
315     WriteSpool( physDev->job.hJob, psvectorstart, strlen(psvectorstart) );
316     
317     for(i = 0; i < 256; i += 8) {
318         vectbuf[0] = '\0';
319         for(j = 0; j < 8; j++) {
320             strcat(vectbuf, "/");
321             if(PSDRV_ANSIVector[i+j]) {
322                 strcat(vectbuf, PSDRV_ANSIVector[i+j]);
323                 strcat(vectbuf, " ");
324             } else {
325                 strcat(vectbuf, ".notdef ");
326             }
327         }
328         strcat(vectbuf, "\n");
329         WriteSpool( physDev->job.hJob, vectbuf, strlen(vectbuf) );
330     }
331
332     WriteSpool( physDev->job.hJob, psvectorend, strlen(psvectorend) );
333     WriteSpool( physDev->job.hJob, psprolog, strlen(psprolog) );
334     WriteSpool( physDev->job.hJob, psendprolog, strlen(psendprolog) );
335
336
337     WriteSpool( physDev->job.hJob, psbeginsetup, strlen(psbeginsetup) );
338
339     for(slot = physDev->pi->ppd->InputSlots; slot; slot = slot->next) {
340         if(slot->WinBin == physDev->Devmode->dmPublic.dmDefaultSource) {
341             if(slot->InvocationString) {
342                 PSDRV_WriteFeature(physDev->job.hJob, "*InputSlot", slot->Name,
343                              slot->InvocationString);
344                 break;
345             }
346         }
347     }
348
349     for(page = physDev->pi->ppd->PageSizes; page; page = page->next) {
350         if(page->WinPage == physDev->Devmode->dmPublic.dmPaperSize) {
351             if(page->InvocationString) {
352                 PSDRV_WriteFeature(physDev->job.hJob, "*PageSize", page->Name,
353                              page->InvocationString);
354                 break;
355             }
356         }
357     }
358
359     WriteSpool( physDev->job.hJob, psendsetup, strlen(psendsetup) );
360
361
362     return 1;
363 }
364
365
366 INT32 PSDRV_WriteFooter( DC *dc )
367 {
368     PSDRV_PDEVICE *physDev = (PSDRV_PDEVICE *)dc->physDev;
369     char *buf;
370
371     buf = (char *)HeapAlloc( PSDRV_Heap, 0, sizeof(psfooter) + 100 );
372     if(!buf) {
373         WARN(psdrv, "HeapAlloc failed\n");
374         return 0;
375     }
376
377     sprintf(buf, psfooter, physDev->job.PageNo);
378
379     if( WriteSpool( physDev->job.hJob, buf, strlen(buf) ) != 
380                                                      strlen(buf) ) {
381         WARN(psdrv, "WriteSpool error\n");
382         HeapFree( PSDRV_Heap, 0, buf );
383         return 0;
384     }
385     HeapFree( PSDRV_Heap, 0, buf );
386     return 1;
387 }
388
389
390
391 INT32 PSDRV_WriteEndPage( DC *dc )
392 {
393     PSDRV_PDEVICE *physDev = (PSDRV_PDEVICE *)dc->physDev;
394
395     if( WriteSpool( physDev->job.hJob, psendpage, sizeof(psendpage)-1 ) != 
396                                                      sizeof(psendpage)-1 ) {
397         WARN(psdrv, "WriteSpool error\n");
398         return 0;
399     }
400     return 1;
401 }
402
403
404
405
406 INT32 PSDRV_WriteNewPage( DC *dc )
407 {
408     PSDRV_PDEVICE *physDev = (PSDRV_PDEVICE *)dc->physDev;
409     char *buf;
410     char name[100];
411     signed int xtrans, ytrans, rotation;
412
413     sprintf(name, "%d", physDev->job.PageNo);
414
415     buf = (char *)HeapAlloc( PSDRV_Heap, 0, sizeof(psnewpage) + 200 );
416     if(!buf) {
417         WARN(psdrv, "HeapAlloc failed\n");
418         return 0;
419     }
420
421     if(physDev->Devmode->dmPublic.dmOrientation == DMORIENT_LANDSCAPE) {
422         if(physDev->pi->ppd->LandscapeOrientation == -90) {
423             xtrans = dc->w.devCaps->vertRes;
424             ytrans = dc->w.devCaps->horzRes;
425             rotation = 90;
426         } else {
427             xtrans = ytrans = 0;
428             rotation = -90;
429         }
430     } else {
431         xtrans = 0;
432         ytrans = dc->w.devCaps->vertRes;
433         rotation = 0;
434     }
435
436     sprintf(buf, psnewpage, name, physDev->job.PageNo,
437             dc->w.devCaps->logPixelsX, dc->w.devCaps->logPixelsY,
438             xtrans, ytrans, rotation);
439
440     if( WriteSpool( physDev->job.hJob, buf, strlen(buf) ) != 
441                                                      strlen(buf) ) {
442         WARN(psdrv, "WriteSpool error\n");
443         HeapFree( PSDRV_Heap, 0, buf );
444         return 0;
445     }
446     HeapFree( PSDRV_Heap, 0, buf );
447     return 1;
448 }
449
450
451 BOOL32 PSDRV_WriteMoveTo(DC *dc, INT32 x, INT32 y)
452 {
453     char buf[100];
454
455     sprintf(buf, psmoveto, x, y);
456     return PSDRV_WriteSpool(dc, buf, strlen(buf));
457 }
458
459 BOOL32 PSDRV_WriteLineTo(DC *dc, INT32 x, INT32 y)
460 {
461     char buf[100];
462
463     sprintf(buf, pslineto, x, y);
464     return PSDRV_WriteSpool(dc, buf, strlen(buf));
465 }
466
467
468 BOOL32 PSDRV_WriteStroke(DC *dc)
469 {
470     return PSDRV_WriteSpool(dc, psstroke, sizeof(psstroke)-1);
471 }
472
473
474
475 BOOL32 PSDRV_WriteRectangle(DC *dc, INT32 x, INT32 y, INT32 width, 
476                         INT32 height)
477 {
478     char buf[100];
479
480     sprintf(buf, psrectangle, x, y, width, height, -width);
481     return PSDRV_WriteSpool(dc, buf, strlen(buf));
482 }
483
484 BOOL32 PSDRV_WriteArc(DC *dc, INT32 x, INT32 y, INT32 w, INT32 h, double ang1,
485                       double ang2)
486 {
487     char buf[256];
488
489     /* Make angles -ve and swap order because we're working with an upside
490        down y-axis */
491     sprintf(buf, psarc, x, y, w, h, -ang2, -ang1);
492     return PSDRV_WriteSpool(dc, buf, strlen(buf));
493 }
494
495 static char encodingext[] = "-ANSI";
496
497 BOOL32 PSDRV_WriteSetFont(DC *dc, BOOL32 UseANSI)
498 {
499     PSDRV_PDEVICE *physDev = (PSDRV_PDEVICE *)dc->physDev;
500     char *buf, *newbuf;
501
502     buf = (char *)HeapAlloc( PSDRV_Heap, 0,
503              sizeof(pssetfont) + strlen(physDev->font.afm->FontName) + 40);
504
505     if(!buf) {
506         WARN(psdrv, "HeapAlloc failed\n");
507         return FALSE;
508     }
509
510     newbuf = (char *)HeapAlloc( PSDRV_Heap, 0,
511               strlen(physDev->font.afm->FontName) + sizeof(encodingext));
512
513     if(!newbuf) {
514         WARN(psdrv, "HeapAlloc failed\n");
515         HeapFree(PSDRV_Heap, 0, buf);
516         return FALSE;
517     }
518
519     if(UseANSI)
520         sprintf(newbuf, "%s%s", physDev->font.afm->FontName, encodingext);
521     else
522         strcpy(newbuf, physDev->font.afm->FontName);
523
524     sprintf(buf, pssetfont, newbuf, 
525                 physDev->font.size, -physDev->font.size,
526                 -physDev->font.escapement);
527
528     PSDRV_WriteSpool(dc, buf, strlen(buf));
529     HeapFree(PSDRV_Heap, 0, buf);
530     return TRUE;
531 }    
532
533 BOOL32 PSDRV_WriteSetColor(DC *dc, PSCOLOR *color)
534 {
535     PSDRV_PDEVICE *physDev = (PSDRV_PDEVICE *)dc->physDev;
536     char buf[256];
537
538     if(PSDRV_CmpColor(&physDev->inkColor, color))
539         return TRUE;
540
541     PSDRV_CopyColor(&physDev->inkColor, color);
542     switch(color->type) {
543     case PSCOLOR_RGB:
544         sprintf(buf, pssetrgbcolor, color->value.rgb.r, color->value.rgb.g,
545                 color->value.rgb.b);
546         return PSDRV_WriteSpool(dc, buf, strlen(buf));
547
548     case PSCOLOR_GRAY:  
549         sprintf(buf, pssetgray, color->value.gray.i);
550         return PSDRV_WriteSpool(dc, buf, strlen(buf));
551         
552     default:
553         ERR(psdrv, "Unkonwn colour type %d\n", color->type);
554         break;
555     }
556
557     return FALSE;
558 }
559
560 BOOL32 PSDRV_WriteSetPen(DC *dc)
561 {
562     PSDRV_PDEVICE *physDev = (PSDRV_PDEVICE *)dc->physDev;
563     char buf[256];
564
565     sprintf(buf, pssetlinewidth, physDev->pen.width);
566     PSDRV_WriteSpool(dc, buf, strlen(buf));
567
568     if(physDev->pen.dash) {
569         sprintf(buf, pssetdash, physDev->pen.dash, 0);
570         PSDRV_WriteSpool(dc, buf, strlen(buf));
571     }
572
573     return TRUE;
574 }
575
576 BOOL32 PSDRV_WriteReencodeFont(DC *dc)
577 {
578     PSDRV_PDEVICE *physDev = (PSDRV_PDEVICE *)dc->physDev;
579     char *buf, *newbuf;
580  
581     buf = (char *)HeapAlloc( PSDRV_Heap, 0,
582              sizeof(psreencodefont) + 2 * strlen(physDev->font.afm->FontName) 
583                              + sizeof(encodingext));
584
585     if(!buf) {
586         WARN(psdrv, "HeapAlloc failed\n");
587         return FALSE;
588     }
589
590     newbuf = (char *)HeapAlloc( PSDRV_Heap, 0,
591               strlen(physDev->font.afm->FontName) + sizeof(encodingext));
592
593     if(!newbuf) {
594         WARN(psdrv, "HeapAlloc failed\n");
595         HeapFree(PSDRV_Heap, 0, buf);
596         return FALSE;
597     }
598
599     sprintf(newbuf, "%s%s", physDev->font.afm->FontName, encodingext);
600     sprintf(buf, psreencodefont, newbuf, physDev->font.afm->FontName);
601
602     PSDRV_WriteSpool(dc, buf, strlen(buf));
603
604     HeapFree(PSDRV_Heap, 0, newbuf);
605     HeapFree(PSDRV_Heap, 0, buf);
606     return TRUE;
607 }    
608
609 BOOL32 PSDRV_WriteShow(DC *dc, char *str, INT32 count)
610 {
611     char *buf, *buf1;
612     INT32 buflen = count + 10, i, done;
613
614     buf = (char *)HeapAlloc( PSDRV_Heap, 0, buflen );
615     
616     for(i = done = 0; i < count; i++) {
617         if(!isprint(str[i])) {
618             if(done + 4 >= buflen)
619                 buf = HeapReAlloc( PSDRV_Heap, 0, buf, buflen += 10 );
620             sprintf(buf + done, "\\%03o", (int)(unsigned char)str[i] );
621             done += 4;
622         } else if(str[i] == '\\' || str[i] == '(' || str[i] == ')' ) {
623             if(done + 2 >= buflen)
624                 buf = HeapReAlloc( PSDRV_Heap, 0, buf, buflen += 10 );
625             buf[done++] = '\\';
626             buf[done++] = str[i];
627         } else {
628             if(done + 1 >= buflen)
629                 buf = HeapReAlloc( PSDRV_Heap, 0, buf, buflen += 10 );
630             buf[done++] = str[i];
631         }
632     }
633     buf[done] = '\0';
634
635     buf1 = (char *)HeapAlloc( PSDRV_Heap, 0, sizeof(psshow) + done);
636
637     sprintf(buf1, psshow, buf);
638
639     PSDRV_WriteSpool(dc, buf1, strlen(buf1));
640     HeapFree(PSDRV_Heap, 0, buf);
641     HeapFree(PSDRV_Heap, 0, buf1);
642
643     return TRUE;
644 }    
645
646 BOOL32 PSDRV_WriteFill(DC *dc)
647 {
648     return PSDRV_WriteSpool(dc, psfill, sizeof(psfill)-1);
649 }
650
651 BOOL32 PSDRV_WriteEOFill(DC *dc)
652 {
653     return PSDRV_WriteSpool(dc, pseofill, sizeof(pseofill)-1);
654 }
655
656 BOOL32 PSDRV_WriteGSave(DC *dc)
657 {
658     return PSDRV_WriteSpool(dc, psgsave, sizeof(psgsave)-1);
659 }
660
661 BOOL32 PSDRV_WriteGRestore(DC *dc)
662 {
663     return PSDRV_WriteSpool(dc, psgrestore, sizeof(psgrestore)-1);
664 }
665
666 BOOL32 PSDRV_WriteClosePath(DC *dc)
667 {
668     return PSDRV_WriteSpool(dc, psclosepath, sizeof(psclosepath)-1);
669 }
670
671 BOOL32 PSDRV_WriteClip(DC *dc)
672 {
673     return PSDRV_WriteSpool(dc, psclip, sizeof(psclip)-1);
674 }
675
676 BOOL32 PSDRV_WriteEOClip(DC *dc)
677 {
678     return PSDRV_WriteSpool(dc, pseoclip, sizeof(pseoclip)-1);
679 }
680
681 BOOL32 PSDRV_WriteHatch(DC *dc)
682 {
683     return PSDRV_WriteSpool(dc, pshatch, sizeof(pshatch)-1);
684 }
685
686 BOOL32 PSDRV_WriteRotate(DC *dc, float ang)
687 {
688     char buf[256];
689
690     sprintf(buf, psrotate, ang);
691     return PSDRV_WriteSpool(dc, buf, strlen(buf));
692 }
693
694