dtcm: Resolve CID 87713
[oweals/cde.git] / cde / programs / dtpad / printJob.c
1 /*
2  * CDE - Common Desktop Environment
3  *
4  * Copyright (c) 1993-2012, The Open Group. All rights reserved.
5  *
6  * These libraries and programs are free software; you can
7  * redistribute them and/or modify them under the terms of the GNU
8  * Lesser General Public License as published by the Free Software
9  * Foundation; either version 2 of the License, or (at your option)
10  * any later version.
11  *
12  * These libraries and programs are distributed in the hope that
13  * they will be useful, but WITHOUT ANY WARRANTY; without even the
14  * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15  * PURPOSE. See the GNU Lesser General Public License for more
16  * details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with these librararies and programs; if not, write
20  * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21  * Floor, Boston, MA 02110-1301 USA
22  */
23 /* $TOG: printJob.c /main/29 1997/08/01 14:32:04 samborn $ */
24 /**********************************<+>*************************************
25 ***************************************************************************
26 **
27 **  File:        printJob.c
28 **
29 **  Project:     HP DT dtpad, a memo maker type editor based on the
30 **               Dt Editor widget.
31 **
32 **  Description:  Routines which manipulate the print setup dialog
33 **
34 **************************************************************************
35 **********************************<+>*************************************/
36 /*
37  *                   Common Desktop Environment
38  *
39  *   (c) Copyright 1993, 1994, 1995 Hewlett-Packard Company
40  *   (c) Copyright 1993, 1994, 1995 International Business Machines Corp.
41  *   (c) Copyright 1993, 1994, 1995 Sun Microsystems, Inc.
42  *   (c) Copyright 1993, 1994, 1995 Novell, Inc.
43  *   (c) Copyright 1995 Digital Equipment Corp.
44  *   (c) Copyright 1995 Fujitsu Limited
45  *   (c) Copyright 1995 Hitachi, Ltd.
46  *
47  *
48  *                     RESTRICTED RIGHTS LEGEND
49  *
50  *Use, duplication, or disclosure by the U.S. Government is subject to
51  *restrictions as set forth in subparagraph (c)(1)(ii) of the Rights in
52  *Technical Data and Computer Software clause in DFARS 252.227-7013.  Rights
53  *for non-DOD U.S. Government Departments and Agencies are as set forth in
54  *FAR 52.227-19(c)(1,2).
55
56  *Hewlett-Packard Company, 3000 Hanover Street, Palo Alto, CA 94304 U.S.A.
57  *International Business Machines Corp., Route 100, Somers, NY 10589 U.S.A.
58  *Sun Microsystems, Inc., 2550 Garcia Avenue, Mountain View, CA 94043 U.S.A.
59  *Novell, Inc., 190 River Road, Summit, NJ 07901 U.S.A.
60  *Digital Equipment Corp., 111 Powdermill Road, Maynard, MA 01754, U.S.A.
61  *Fujitsu Limited, 1015, Kamikodanaka Nakahara-Ku, Kawasaki 211, Japan
62  *Hitachi, Ltd., 6, Kanda Surugadai 4-Chome, Chiyoda-ku, Tokyo 101, Japan
63  */
64
65
66 #include <errno.h>
67 #include <pwd.h>
68 #include <stdio.h>
69 #include <string.h>
70 #include <sys/types.h>
71 #include <time.h>
72
73 #include <X11/Intrinsic.h>
74 #include <X11/Shell.h>
75 #include <Xm/Xm.h>
76 #include <Xm/DialogS.h>
77 #include <Xm/Form.h>
78 #include <Xm/Label.h>
79 #include <Xm/Print.h>
80 #include <Dt/Editor.h>
81 #include <Dt/Print.h>
82
83 #include "dtpad.h"
84
85 static void     _pjCreatePrintShell(PrintJob *pJob);
86 static void     _pjCreateOutputWidgets(PrintJob *pJob);
87 static void     _pjDoPrint(PrintJob*);
88 static void     _pjUpdatePageHeaders(
89                                 PrintJob*,
90                                 PrintStringTypeEnum,
91                                 PrintStringTypeEnum,
92                                 PrintStringTypeEnum,
93                                 PrintStringTypeEnum);
94 static void     _pjFinishedPrintToFile(
95                                 Display*,
96                                 XPContext,
97                                 XPGetDocStatus,
98                                 XPointer);
99 static char *   _pjGetPageHeaderString(PrintJob*, PrintStringTypeEnum);
100
101 static void     _pjCancelCB (Widget, XtPointer client_data, XtPointer);
102 static void     _pjCloseDisplayCB (Widget, XtPointer client_data, XtPointer);
103 static void     _pjPdmSetupCB (Widget, XtPointer client_data, XtPointer);
104 static void     _pjPdmNotificationCB (Widget, XtPointer client_data, XtPointer);
105 static void     _pjPrintCB (Widget, XtPointer client_data, XtPointer);
106 static void     _pjPrintOnePageCB(Widget, XtPointer, XtPointer);
107
108 static void     _pjRegisterActivePrintDisplay(Display*);
109 static void     _pjUnregisterActivePrintDisplay(Display*);
110
111 static Display  *_pjErrorPrintDisplay = NULL;
112 static Display  **_pjActivePrintDisplay = NULL;
113 static int      _pjMaxActivePrintDisplay = 0;
114
115 /************************************************************************
116  * PrintJobCreate
117  *      Creates a new print job for the specified document file.
118  ************************************************************************/
119 PrintJob *
120 PrintJobCreate(
121         char *documentName,
122         char *tempFileName,
123         Boolean silent,
124         Editor *pPad
125         )
126 {
127     PrintJob *pJob;
128
129     pJob = (PrintJob *) XtMalloc( sizeof(PrintJob) );
130     memset(pJob, 0, sizeof(PrintJob));
131
132     pJob->pPad = pPad;
133     pJob->parentShell = pPad->app_shell;
134     pJob->documentName = strdup(documentName);
135     pJob->tempFileName = strdup(tempFileName);
136     pJob->silent = silent;
137
138     pJob->pOutput = NULL;
139     pJob->pSetup = NULL;
140     pJob->pShell = NULL;
141     pJob->printData = (DtPrintSetupData*) XtMalloc(sizeof(DtPrintSetupData));
142     memset(pJob->printData, 0, sizeof(DtPrintSetupData));
143
144     pJob->npagesDone = 0;
145     pJob->npagesTotal = 0;
146
147     pJob->nextpageShell = NULL;
148     pJob->nextpageButton = NULL;
149
150     return pJob;
151 }
152
153 /************************************************************************
154  * PrintJobDestroy
155  *      Destroys the specified PrintJob.
156  ************************************************************************/
157 void
158 PrintJobDestroy(PrintJob *pJob)
159 {
160     if (pJob == NULL)
161       return;
162
163     if (pJob->pPad)
164     {
165         pJob->pPad->numPendingTasks--;
166         ClearStatusMessage(pJob->pPad);
167         XtSetSensitive(pJob->pPad->fileStuff.fileWidgets.printBtn, True);
168         /*
169         XtSetSensitive(pJob->pPad->fileStuff.fileWidgets.silentPrintBtn, True);
170         */
171     }
172     if (pJob->documentName != NULL)
173     {
174         free((char*) pJob->documentName);
175         pJob->documentName = NULL;
176     }
177     if (pJob->tempFileName != NULL)
178     {
179         free((char*) pJob->tempFileName);
180         pJob->tempFileName = NULL;
181     }
182     if (pJob->pOutput != NULL)
183     {
184         PrintOutputDestroy(pJob->pOutput);
185         pJob->pOutput = NULL;
186     }
187     if (pJob->pShell != NULL)
188     {
189         _pjRegisterActivePrintDisplay(XtDisplay(pJob->pShell));
190         if (XtDisplay(pJob->pShell) == PrintJobGetErrorPrintDisplay())
191         {
192             char *errMsg;
193
194             /*
195              * Need to display an error dialog;
196              */
197             errMsg =
198               GETMESSAGE(
199                 14, 24,
200                 "The X Print Server is temporarily out of resources.");
201
202             Warning(pJob->pPad, (char *) errMsg, XmDIALOG_ERROR);
203             PrintJobSetErrorPrintDisplay(NULL);
204         }
205
206         XtDestroyWidget(pJob->pShell);
207         pJob->pShell = NULL;
208     }
209     if (pJob->pSetup != NULL)
210     {
211         PrintSetupDestroy(pJob->pSetup);
212         pJob->pSetup = NULL;
213     }
214     if (pJob->printData)
215     {
216         DtPrintFreeSetupData(pJob->printData);
217         XtFree((XtPointer) pJob->printData);
218         pJob->printData = NULL;
219     }
220     if (pJob->nextpageShell)
221     {
222         XtDestroyWidget(pJob->nextpageShell);
223         pJob->nextpageShell = NULL;
224     }
225
226     XtFree((char *) pJob);
227 }
228
229 /************************************************************************
230  * PrintJobExecute
231  *      Executes the specified PrintJob
232  ************************************************************************/
233 void
234 PrintJobExecute(PrintJob *pJob)
235 {
236     if (pJob == NULL) return;
237
238     pJob->pSetup = PrintSetupCreate(
239                                 pJob->parentShell,
240                                 pJob->documentName,
241                                 pJob->pPad->xrdb.wordWrap,
242                                 pJob->pPad,
243                                 (XtCallbackProc) _pjCancelCB, pJob,
244                                 (XtCallbackProc) _pjCloseDisplayCB, pJob,
245                                 (XtCallbackProc) _pjPrintCB, pJob,
246                                 (XtCallbackProc) _pjPdmSetupCB, pJob);
247     if (pJob->silent)
248     {
249         /*
250          * The DtPrintSetupDialog will display itself automatically
251          * along with an error message in the event of an error.
252          */
253         if (FALSE == PrintSetupGetDefaultPrintData(
254                                                 pJob->pSetup,
255                                                 pJob->printData))
256           return;
257
258         _pjCreatePrintShell(pJob);
259         _pjDoPrint(pJob);
260     }
261     else
262       PrintSetupDisplay(pJob->pSetup);
263 }
264
265 /************************************************************************
266  * PrintJobCancel
267  *      Cancels and deletes the specified print job.
268  ************************************************************************/
269 void
270 PrintJobCancel(PrintJob *pJob)
271 {
272     PrintJobDestroy(pJob);
273 }
274
275
276 /************************************************************************
277  * PrintJobGetErrorPrintDisplay
278  *      Returns the last print display on which an error occured.
279  ************************************************************************/
280 Display *
281 PrintJobGetErrorPrintDisplay()
282 {
283     return _pjErrorPrintDisplay;
284 }
285
286 /************************************************************************
287  * PrintJobSetErrorPrintDisplay
288  *      Save a pointer to the print display on which an error occured.
289  ************************************************************************/
290 void
291 PrintJobSetErrorPrintDisplay(Display *display)
292 {
293     _pjErrorPrintDisplay = display;
294 }
295
296 /************************************************************************
297  * PrintJobIsActivePrintDisplay
298  *      Save a pointer to the print display on which an error occured.
299  ************************************************************************/
300 Boolean
301 PrintJobIsActivePrintDisplay(Display *display)
302 {
303     int i;
304
305     for (i = 0; i < _pjMaxActivePrintDisplay; i++)
306       if (display == _pjActivePrintDisplay[i])
307         return True;
308
309     return False;
310 }
311
312 /************************************************************************
313  * _pjRegisterActivePrintDisplay
314  *      Save the Display pointer for an active print display connection
315  ************************************************************************/
316 static void
317 _pjRegisterActivePrintDisplay(Display *display)
318 {
319     size_t size;
320     int i;
321
322     if (0 == _pjMaxActivePrintDisplay)
323     {
324         _pjMaxActivePrintDisplay = 10;
325         size = _pjMaxActivePrintDisplay * sizeof(Display*);
326         _pjActivePrintDisplay = (Display**) malloc(size);
327         memset((char*) _pjActivePrintDisplay, 0, size);
328     }
329
330     for (i = 0; i < _pjMaxActivePrintDisplay; i++)
331     {
332         if (NULL == _pjActivePrintDisplay[i])
333         {
334             _pjActivePrintDisplay[i] = display;
335             return;
336         }
337     }
338
339     size = _pjMaxActivePrintDisplay * sizeof(Display*);
340     _pjActivePrintDisplay =
341         (Display**) realloc((void*) _pjActivePrintDisplay, 2*size);
342     memset((char*) (_pjActivePrintDisplay + size), 0, size);
343     _pjActivePrintDisplay[_pjMaxActivePrintDisplay] = display;
344     _pjMaxActivePrintDisplay *= 2;
345 }
346
347 /************************************************************************
348  * _pjUnregisterActivePrintDisplay
349  *      Delete the Display pointer for an active print display connection
350  ************************************************************************/
351 static void
352 _pjUnregisterActivePrintDisplay(Display *display)
353 {
354     int i;
355
356     for (i = 0; i < _pjMaxActivePrintDisplay; i++)
357       if (display == _pjActivePrintDisplay[i])
358         _pjActivePrintDisplay[i] = NULL;
359 }
360
361
362 /************************************************************************
363  * _pjCreatePrintShell
364  *      Creates the print shell (XmPrintShell or XmDialogShell) to control
365  *      printing.
366  ************************************************************************/
367 static void
368 _pjCreatePrintShell(PrintJob *pJob)
369 {
370     DtPrintSetupData    *psd = NULL;
371
372     if (pJob == NULL ||
373         pJob->pShell != NULL ||
374         pJob->parentShell == NULL ||
375         pJob->pSetup == NULL) return;
376
377 #if defined(PRINTING_SUPPORTED)
378     
379     /*
380      * Create the print shell and
381      * the print output widgets
382      */
383 #ifdef PRINT_TO_VIDEO
384     /*
385      * Create a dialog shell widget on the video display.
386      */
387     pJob->pShell = XmCreateDialogShell(
388                                 pJob->parentShell,
389                                 "PrintVideo",
390                                 NULL, 0);
391     {
392         XmString    xms;
393
394         pJob->nextpageShell = XmCreateDialogShell(
395                                         pJob->parentShell,
396                                         "PrintNextPage",
397                                         NULL, 0);
398
399         xms = XmStringCreateLocalized("Push for Next Page");
400         pJob->nextpageButton = XtVaCreateManagedWidget(
401                                         "NextPageButton",
402                                         xmPushButtonWidgetClass,
403                                         pJob->nextpageShell,
404                                         XmNlabelString, xms,
405                                         XmNwidth, 200,
406                                         XmNheight, 200,
407                                         NULL);
408         XmStringFree(xms);
409
410         XtAddCallback(
411                 pJob->nextpageButton,
412                 XmNactivateCallback,
413                 _pjPrintOnePageCB,
414                 (XtPointer) pJob);
415
416         XtManageChild(pJob->nextpageShell);
417         XtRealizeWidget(pJob->nextpageShell);
418     }
419 #else
420
421     /*
422      * Create an XmPrintShell widget on the print display.  
423      */ 
424     psd = pJob->printData;
425     if (psd != NULL)
426       pJob->pShell = XmPrintSetup(
427                 pJob->parentShell,
428                 XpGetScreenOfContext(psd->print_display, psd->print_context),
429                 "Print",
430                 NULL, 0);
431
432     XtAddCallback(
433                 pJob->pShell,
434                 XmNpageSetupCallback,
435                 _pjPrintOnePageCB,
436                 (XtPointer) pJob);
437     XtAddCallback(
438                 pJob->pShell,
439                 XmNpdmNotificationCallback,
440                 _pjPdmNotificationCB,
441                 (XtPointer) pJob);
442 #endif
443
444     if (pJob->pShell == NULL) return;
445 #endif  /* PRINTING_SUPPORTED */
446
447 }
448
449
450
451 /************************************************************************
452  * _pjCreateOutputWidgets
453  *      Actually run the specified PrintJob.
454  *      Creates the PrintOutput object to be used for printing.
455  *      Initializes the mailbox to iterate through the messages.
456  *      Calls spoolOne to send a print job to the Xp server.
457  ************************************************************************/
458 static void
459 _pjCreateOutputWidgets(PrintJob *pJob)
460 {
461     DtEditorErrorCode   errorCode;
462     Boolean             parseError;
463     DtPrintSetupData    *psd = NULL;
464     int                 save_data;
465
466     /*
467      * Notify the user that we're printing
468      */
469     /* TBD:  Is there a status bar on pPad? */
470
471     if (pJob->pShell == NULL)
472     {
473         {/* TBD error dialog */}
474         PrintJobDestroy(pJob);
475         return;
476     }
477
478     pJob->pOutput = PrintOutputCreate(pJob->pShell);
479     PrintOutputSetWordWrap(pJob->pOutput, PrintSetupUseWordWrap(pJob->pSetup));
480     PrintOutputSetPageMargins(
481         pJob->pOutput,
482         PrintSetupGetMarginSpec(pJob->pSetup, DTPRINT_OPTION_MARGIN_TOP),
483         PrintSetupGetMarginSpec(pJob->pSetup, DTPRINT_OPTION_MARGIN_RIGHT),
484         PrintSetupGetMarginSpec(pJob->pSetup, DTPRINT_OPTION_MARGIN_BOTTOM),
485         PrintSetupGetMarginSpec(pJob->pSetup, DTPRINT_OPTION_MARGIN_LEFT),
486         &parseError
487         );
488     if (parseError)
489     {
490         /*
491          * Display an error dialog.
492         DtMailGenDialog *genDialog = new DtMailGenDialog(
493                                                         "Dialog",
494                                                         _parent->baseWidget());
495          */
496         char    *i18nMsg;
497         char    *errMsg;
498
499         i18nMsg = GETMESSAGE(
500                         14, 1,
501                         "One of the following margin specifiers \n has incorrect syntax: \n %s \n %s \n %s \n %s \nContinue using default margins?"
502                         );
503
504         errMsg = (char *) XtMalloc(1024);
505         sprintf(
506             errMsg,
507             i18nMsg,
508             PrintSetupGetMarginSpec(pJob->pSetup, DTPRINT_OPTION_MARGIN_TOP),
509             PrintSetupGetMarginSpec(pJob->pSetup, DTPRINT_OPTION_MARGIN_RIGHT),
510             PrintSetupGetMarginSpec(pJob->pSetup, DTPRINT_OPTION_MARGIN_BOTTOM),
511             PrintSetupGetMarginSpec(pJob->pSetup, DTPRINT_OPTION_MARGIN_LEFT)
512             );
513
514         Warning(pJob->pPad, (char *) errMsg, XmDIALOG_WARNING);
515         XtFree(errMsg);
516     }
517
518     /*
519      * Load the file
520      */
521     errorCode = PrintOutputLoadFile(pJob->pOutput, pJob->tempFileName);
522     switch (errorCode)
523     {
524         case DtEDITOR_NO_ERRORS:
525         case DtEDITOR_READ_ONLY_FILE:
526             break;
527         case DtEDITOR_NONEXISTENT_FILE:
528             Warning(
529                 pJob->pPad,
530                 (char *) GETMESSAGE(14, 2, "File does not exist."),
531                 XmDIALOG_WARNING);
532             break;
533         case DtEDITOR_DIRECTORY:
534             Warning(
535                 pJob->pPad,
536                 (char *) GETMESSAGE(14, 3, "Specified file is a directory."),
537                 XmDIALOG_WARNING);
538             break;
539         case DtEDITOR_CHAR_SPECIAL_FILE:
540         case DtEDITOR_BLOCK_MODE_FILE:
541             Warning(
542                 pJob->pPad,
543                 (char *) GETMESSAGE(14, 4, "File type error."),
544                 XmDIALOG_WARNING);
545             break;
546         case DtEDITOR_NULLS_REMOVED:
547             Warning(
548                 pJob->pPad,
549                 (char *) GETMESSAGE(14, 5, "File contains NULL characters."),
550                 XmDIALOG_WARNING);
551             break;
552         case DtEDITOR_INSUFFICIENT_MEMORY:
553             Warning(
554                 pJob->pPad,
555                 (char*)
556                 GETMESSAGE(14, 6, "Unable to load file (insufficient memory)."),
557                 XmDIALOG_ERROR);
558                 break;
559         case DtEDITOR_NO_FILE_ACCESS:
560         case DtEDITOR_UNREADABLE_FILE:
561         default:
562             Warning(
563                 pJob->pPad,
564                 (char *)
565                 GETMESSAGE(14, 7, "File does not have read permissions"),
566                 XmDIALOG_WARNING);
567             break;
568     }
569
570     XtRealizeWidget( pJob->pShell );
571
572     PrintOutputFirstPage(pJob->pOutput);
573     pJob->npagesTotal = PrintOutputGetNumLines(pJob->pOutput) +
574                         PrintOutputGetLinesPerPage(pJob->pOutput) - 1;
575     pJob->npagesTotal /= PrintOutputGetLinesPerPage(pJob->pOutput);
576     pJob->npagesDone = 0;
577 }
578
579
580
581
582 /************************************************************************
583  * _pjDoPrint
584  *      Actually run the specified PrintJob.
585  *      Creates the PrintOutput object to be used for printing.
586  *      Initializes the mailbox to iterate through the messages.
587  *      Calls spoolOne to send a print job to the Xp server.
588  ************************************************************************/
589 static void
590 _pjDoPrint(PrintJob *pJob)
591 {
592 #if defined(PRINTING_SUPPORTED)
593
594     static char         buf[1024];
595     static char         *format;
596     DtPrintSetupData    *psd = NULL;
597     int                 dest = XPSpool;
598
599     /*
600      * Notify the user that we're printing
601      */
602     if (pJob->pPad != NULL) {
603         pJob->pPad->numPendingTasks++;
604         format = GETMESSAGE(14, 21, "Printing %s ...");
605         sprintf(buf, format, pJob->documentName);
606         SetStatusMessage(pJob->pPad, buf);
607         XtSetSensitive(pJob->pPad->fileStuff.fileWidgets.printBtn, False);
608     }
609
610 #ifndef PRINT_TO_VIDEO
611     psd = pJob->printData;
612
613     if (psd->destination == DtPRINT_TO_FILE)
614       dest = XPGetData;
615
616     _pjRegisterActivePrintDisplay(XtDisplay(pJob->pShell));
617     XpStartJob(XtDisplay(pJob->pShell), dest);
618     XFlush(XtDisplay(pJob->pShell));
619
620     if (psd->destination == DtPRINT_TO_FILE)
621     {
622         if (FALSE == XmPrintToFile(
623                                 XtDisplay(pJob->pShell),
624                                 psd->dest_info,
625                                 _pjFinishedPrintToFile,
626                                 (XPointer) pJob))
627         {
628             char        *fmt = "%s\n%s:  %s";
629             char        *message;
630             char        *appmessage = NULL;
631             char        *sysmessage = strerror(errno);
632
633             appmessage = (char *) GETMESSAGE(
634                             14, 14,
635                             "'Print to File' was unsuccessful.");
636             
637             if (NULL == sysmessage)
638             {
639                 message = XtMalloc(strlen(appmessage) + 1);
640                 sprintf(message, "%s", appmessage);
641             }
642             else
643             {
644                 message = XtMalloc(
645                                 strlen(appmessage) +
646                                 strlen(sysmessage) +
647                                 strlen(psd->dest_info) +
648                                 strlen(fmt) + 1);
649                 sprintf(message, fmt, appmessage, psd->dest_info, sysmessage);
650             }
651             
652             Warning(pJob->pPad, message, XmDIALOG_WARNING);
653             XtFree(message);
654             
655             XpCancelJob(XtDisplay(pJob->pShell), False);
656             PrintJobDestroy(pJob);
657         }
658     }
659 #endif
660 #endif  /* PRINTING_SUPPORTED */
661
662
663 }
664
665 /************************************************************************
666  * _pjUpdatePageHeaders
667  *      Configures the header and footer string in the PrintOutput. 
668  ************************************************************************/
669 static void
670 _pjUpdatePageHeaders(
671                 PrintJob                *pJob,
672                 PrintStringTypeEnum     hl_type,
673                 PrintStringTypeEnum     hr_type,
674                 PrintStringTypeEnum     fl_type,
675                 PrintStringTypeEnum     fr_type
676                 )
677 {
678     char *hl_string,
679          *hr_string,
680          *fl_string,
681          *fr_string;
682
683     if (pJob == (PrintJob *) NULL) return;
684
685     hl_string = _pjGetPageHeaderString(pJob, hl_type);
686     hr_string = _pjGetPageHeaderString(pJob, hr_type);
687     fl_string = _pjGetPageHeaderString(pJob, fl_type);
688     fr_string = _pjGetPageHeaderString(pJob, fr_type);
689
690     if (PRINT_NONE_STRING_TYPE_ENUM == hl_type &&
691         PRINT_NONE_STRING_TYPE_ENUM == hr_type)
692       PrintOutputHideHeaders(pJob->pOutput);
693     else
694       PrintOutputShowHeaders(pJob->pOutput);
695
696     if (PRINT_NONE_STRING_TYPE_ENUM == fl_type &&
697         PRINT_NONE_STRING_TYPE_ENUM == fr_type)
698       PrintOutputHideFooters(pJob->pOutput);
699     else
700       PrintOutputShowFooters(pJob->pOutput);
701
702
703     PrintOutputSetHdrFtrStrings(
704                                 pJob->pOutput,
705                                 hl_string,
706                                 hr_string,
707                                 fl_string,
708                                 fr_string
709                                 );
710     free(hl_string);
711     free(hr_string);
712     free(fl_string);
713     free(fr_string);
714 }
715
716 /************************************************************************
717  * _pjGetPageHeaderString
718  *      Returns a header and footer string of the specified type.
719  ************************************************************************/
720 static char *
721 _pjGetPageHeaderString(PrintJob *pJob, PrintStringTypeEnum type)
722 {
723     char *format,
724          *buf = (char *) NULL;
725
726     switch (type)
727     {
728         case PRINT_NONE_STRING_TYPE_ENUM:
729             buf = strdup(" ");
730             break;
731         case PRINT_DATE_STRING_TYPE_ENUM:
732             {
733                 time_t  clock;
734                 char    *date;
735
736                 clock = time((time_t*) NULL);
737                 date = ctime(&clock);
738                 /* Strip off the trailing newline. */
739                 date[strlen(date)-1] = '\0';
740                 format = GETMESSAGE(14, 8, "Date:  %s");
741                 buf = (char *) malloc(strlen(format) + strlen(date) + 1);
742                 if (buf != (char *) NULL)
743                   sprintf(buf, format, date);
744             }
745             break;
746         case PRINT_DOCNAME_STRING_TYPE_ENUM:
747             {
748                 unsigned        buflen;
749
750                 format = GETMESSAGE(14, 9, "Document:  %s");
751                 buflen = strlen(format) + strlen(pJob->documentName) + 1;
752                 buf = (char *) malloc(buflen);
753                 if (buf != (char *) NULL)
754                   sprintf(buf, format, pJob->documentName);
755             }
756             break;
757         case PRINT_PAGE_NUMBER_STRING_TYPE_ENUM:
758             /*
759              * Allocate space for the format and the translated page number.
760              */
761             {
762                 format = GETMESSAGE(14, 10, "Page %d of %d");
763                 buf = (char *) malloc(strlen(format) + 16);
764                 if (buf != (char *) NULL)
765                   sprintf(buf, format, pJob->npagesDone, pJob->npagesTotal);
766             }
767             break;
768         case PRINT_USER_NAME_STRING_TYPE_ENUM:
769             /*
770              * Allocate space for the format and the username.
771              */
772             {
773                 struct passwd   *pw;
774
775                 format = GETMESSAGE(14, 11, "Document For:  %s");
776                 pw = getpwuid(getuid());
777                 buf = (char *) malloc(strlen(format) + strlen(pw->pw_name) + 1);
778                 if (buf != (char *) NULL)
779                   sprintf(buf, format, pw->pw_name);
780             }
781             break;
782         default:
783             buf = strdup("DEFAULT not impld");
784             break;
785     }
786     return buf;
787 }
788
789
790 /*
791  *
792  * Name: _pjFinishedPrintToFile
793  *
794  * Description:
795  *
796  *     App-specific print data holder allocate function.
797  *
798  */
799 static void _pjFinishedPrintToFile(
800                         Display         *display,
801                         XPContext       context,
802                         XPGetDocStatus  status,
803                         XPointer        client_data)
804 {
805     char        *message = NULL;
806     PrintJob    *pJob = (PrintJob *) client_data;
807     Editor      *pPad = pJob->pPad;
808
809     if (status != XPGetDocFinished)
810     {
811
812         message = (char *) GETMESSAGE(
813                                 14, 14,
814                                 "'Print to File' was unsuccessful.");
815         Warning(pPad, message, XmDIALOG_WARNING);
816     }
817     else if (display != PrintJobGetErrorPrintDisplay())
818     {
819
820         message = (char *) GETMESSAGE(
821                                 14, 15,
822                                 "'Print to File' completed successfully.");
823         Warning(pPad, message, XmDIALOG_INFORMATION);
824     }
825     PrintJobDestroy(pJob);
826 }
827
828
829 /*
830  * Name: _pjCancelCB
831  * Description:
832  *      An XtCallbackProc which can be added to the callback list of
833  *      a widget to cancel the print job passed back as client_data.
834  */
835 static void
836 _pjCancelCB (Widget widget, XtPointer client_data, XtPointer call_data)
837 {
838     PrintJob *pJob = (PrintJob *) client_data;
839
840     PrintJobDestroy(pJob);
841 }
842
843 /*
844  * Name: _pjCloseDisplayCB
845  * Description:
846  *      An XtCallbackProc which can be added to the callback list of
847  *      a widget to cancel the print job passed back as client_data.
848  */
849 static void
850 _pjCloseDisplayCB (Widget widget, XtPointer client_data, XtPointer call_data)
851 {
852     PrintJob *pJob = (PrintJob *) client_data;
853     DtPrintSetupCallbackStruct *pbs = (DtPrintSetupCallbackStruct *) call_data;
854
855     if (pJob->pShell != NULL)
856     {
857         XtDestroyWidget(pJob->pShell);
858         pJob->pShell = NULL;
859     }
860     DtPrintFreeSetupData(pJob->printData);
861 }
862
863 /*
864  * Name: _pjPrintCB
865  * Description:
866  *      An XtCallbackProc which can be added to the callback list of
867  *      a widget to execute the print job passed back as client_data.
868  */
869 static void
870 _pjPrintCB (Widget widget, XtPointer client_data, XtPointer call_data)
871 {
872     PrintJob *pJob = (PrintJob *) client_data;
873     DtPrintSetupCallbackStruct *pbs = (DtPrintSetupCallbackStruct *) call_data;
874
875     DtPrintCopySetupData(pJob->printData, pbs->print_data);
876     _pjCreatePrintShell(pJob);
877     _pjDoPrint(pJob);
878 }
879
880
881 /*
882  * Name: _pjPdmSetupCB
883  * Description:
884  *      An XtCallbackProc which can be added to the callback list of
885  *      a widget to popup the PDM for the print job.
886  */
887 static void
888 _pjPdmSetupCB(Widget print_setup, XtPointer client_data, XtPointer call_data)
889 {
890 #if defined(PRINTING_SUPPORTED)
891     char        *pname = "_pjPdmSetupCB";
892     PrintJob    *pJob = (PrintJob *) client_data;
893     DtPrintSetupCallbackStruct
894                 *pbs = (DtPrintSetupCallbackStruct *) call_data;
895
896     DtPrintCopySetupData(pJob->printData, pbs->print_data);
897     _pjCreatePrintShell(pJob);
898
899     /* Pop up the PDM */
900     if (pJob->pShell)
901     {
902         Widget  shell = print_setup;
903
904         while (! (shell == NULL || XtIsShell(shell)) )
905           shell = XtParent(shell);
906
907         if (shell)
908           XmPrintPopupPDM(pJob->pShell, shell);
909         else
910           fprintf(stderr, "Internal Error %s:  Missing XmPrintShell.", pname);
911     }
912 #endif  /* PRINTING_SUPPORTED */
913 }
914
915
916 /************************************************************************
917  * _pjPdmNotificationCB
918  *      XmNpdmNotificationCallback for the XmPrintShell
919  ************************************************************************/
920 static void
921 _pjPdmNotificationCB (Widget widget, XtPointer client_data, XtPointer call_data)
922 {
923 #if defined(PRINTING_SUPPORTED)
924     PrintJob                    *pJob = (PrintJob*) client_data;
925     XmPrintShellCallbackStruct  *pscbs = (XmPrintShellCallbackStruct*)call_data;
926     char                        *message = NULL;
927
928     switch (pscbs->reason)
929     {
930     
931         case XmCR_PDM_NONE:
932         case XmCR_PDM_START_ERROR:
933         case XmCR_PDM_START_VXAUTH:
934         case XmCR_PDM_START_PXAUTH:
935             message = (char *) GETMESSAGE(
936                         14, 25,
937                         "Print Dialog Manager error - setup failed.");
938             break;
939         default:
940             message = NULL;
941             break;
942     }
943
944     if (message != NULL)
945       Warning( pJob->pPad, message, XmDIALOG_WARNING);
946 #endif  /* PRINTING_SUPPORTED */
947 }
948
949
950
951 /************************************************************************
952  * _pjPrintOnePageCB
953  *      XmNpageSetupCallback for the XmPrintShell
954  ************************************************************************/
955 static void
956 _pjPrintOnePageCB(
957                 Widget widget,
958                 XtPointer client_data,
959                 XtPointer call_data
960                 )
961 {
962 #if defined(PRINTING_SUPPORTED)
963     PrintJob    *pJob = (PrintJob *) client_data;
964
965     XmPrintShellCallbackStruct  *pscbs = (XmPrintShellCallbackStruct*)call_data;
966     int                         top = 0;
967
968     if (pJob->pOutput == NULL)
969     {
970         XtArgVal        width0, height0;
971         Dimension       width, height;
972
973         width = 0; height=0;
974         XtVaGetValues(
975                 pJob->pShell,
976                 XmNwidth, &width0,
977                 XmNheight, &height0,
978                 NULL);
979         width = (Dimension)width0;
980         height = (Dimension)height0;
981
982 #if defined(PRINT_TO_VIDEO)
983         printf("PrintShell in _pjPrintOnePageCB: <W %d - H %d>\n",width,height);
984 #endif
985
986         if (width < 100 || height < 100)
987         {
988             width = 2550; height=3250;
989             XtVaSetValues(
990                 pJob->pShell,
991                 XmNwidth, width,
992                 XmNheight, height,
993                 NULL);
994             width = 0; height=0;
995             XtVaGetValues(
996                 pJob->pShell,
997                 XmNwidth, &width,
998                 XmNheight, &height,
999                 NULL);
1000 #if defined(PRINT_TO_VIDEO)
1001             printf(
1002               "PrintShell in _pjPrintOnePageCB: <W %d - H %d>\n",width,height);
1003 #endif
1004         }
1005         _pjCreateOutputWidgets(pJob);
1006     }
1007
1008 #ifdef PRINT_TO_VIDEO
1009     if (pJob->npagesDone > 0 && pJob->npagesDone == pJob->npagesTotal)
1010 #else
1011     if (pscbs->last_page)
1012 #endif
1013     {
1014         DtPrintSetupData    *psd = pJob->printData;
1015
1016         /*
1017          * This spool job is done.  Clean up.
1018          * If this is a print to file job,
1019          * clean up in the job finished callback.
1020          */
1021         if (psd->destination != DtPRINT_TO_FILE)
1022           PrintJobDestroy(pJob);
1023         return;
1024     }
1025
1026     if (pJob->npagesDone > 0 && PrintOutputPageDown(pJob->pOutput) == FALSE)
1027     {
1028 #ifndef PRINT_TO_VIDEO
1029         pscbs->last_page = TRUE;
1030 #endif
1031         return;
1032     }
1033
1034     /*
1035      * Update header and footer strings.
1036      */
1037     pJob->npagesDone++;
1038     _pjUpdatePageHeaders(
1039         pJob,
1040         PrintSetupGetHdrFtrSpec(pJob->pSetup, DTPRINT_OPTION_HEADER_LEFT),
1041         PrintSetupGetHdrFtrSpec(pJob->pSetup, DTPRINT_OPTION_HEADER_RIGHT),
1042         PrintSetupGetHdrFtrSpec(pJob->pSetup, DTPRINT_OPTION_FOOTER_LEFT),
1043         PrintSetupGetHdrFtrSpec(pJob->pSetup, DTPRINT_OPTION_FOOTER_RIGHT)
1044         );
1045
1046     /*
1047      * Notify the user that we're printing
1048      */
1049     if (pJob->pPad != NULL)
1050     {
1051         static char     buf[1024];
1052         char            *format;
1053
1054         format = GETMESSAGE(14, 22, "Printing %s: page %d of %d ...");
1055         sprintf(buf, format,
1056                 pJob->documentName,
1057                 pJob->npagesDone,
1058                 pJob->npagesTotal);
1059         SetStatusMessage(pJob->pPad, buf);
1060     }
1061
1062 #ifndef PRINT_TO_VIDEO
1063     if (pJob->npagesDone >= pJob->npagesTotal)
1064       pscbs->last_page = TRUE;
1065 #endif
1066
1067 #endif /* PRINTING_SUPPORTED */
1068 }