Link with C++ linker
[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     /*
378      * Create the print shell and
379      * the print output widgets
380      */
381 #ifdef PRINT_TO_VIDEO
382     /*
383      * Create a dialog shell widget on the video display.
384      */
385     pJob->pShell = XmCreateDialogShell(
386                                 pJob->parentShell,
387                                 "PrintVideo",
388                                 NULL, 0);
389     {
390         XmString    xms;
391
392         pJob->nextpageShell = XmCreateDialogShell(
393                                         pJob->parentShell,
394                                         "PrintNextPage",
395                                         NULL, 0);
396
397         xms = XmStringCreateLocalized("Push for Next Page");
398         pJob->nextpageButton = XtVaCreateManagedWidget(
399                                         "NextPageButton",
400                                         xmPushButtonWidgetClass,
401                                         pJob->nextpageShell,
402                                         XmNlabelString, xms,
403                                         XmNwidth, 200,
404                                         XmNheight, 200,
405                                         NULL);
406         XmStringFree(xms);
407
408         XtAddCallback(
409                 pJob->nextpageButton,
410                 XmNactivateCallback,
411                 _pjPrintOnePageCB,
412                 (XtPointer) pJob);
413
414         XtManageChild(pJob->nextpageShell);
415         XtRealizeWidget(pJob->nextpageShell);
416     }
417 #else
418
419     /*
420      * Create an XmPrintShell widget on the print display.  
421      */ 
422     psd = pJob->printData;
423     if (psd != NULL)
424       pJob->pShell = XmPrintSetup(
425                 pJob->parentShell,
426                 XpGetScreenOfContext(psd->print_display, psd->print_context),
427                 "Print",
428                 NULL, 0);
429
430     XtAddCallback(
431                 pJob->pShell,
432                 XmNpageSetupCallback,
433                 _pjPrintOnePageCB,
434                 (XtPointer) pJob);
435     XtAddCallback(
436                 pJob->pShell,
437                 XmNpdmNotificationCallback,
438                 _pjPdmNotificationCB,
439                 (XtPointer) pJob);
440 #endif
441
442     if (pJob->pShell == NULL) return;
443 }
444
445
446
447 /************************************************************************
448  * _pjCreateOutputWidgets
449  *      Actually run the specified PrintJob.
450  *      Creates the PrintOutput object to be used for printing.
451  *      Initializes the mailbox to iterate through the messages.
452  *      Calls spoolOne to send a print job to the Xp server.
453  ************************************************************************/
454 static void
455 _pjCreateOutputWidgets(PrintJob *pJob)
456 {
457     DtEditorErrorCode   errorCode;
458     Boolean             parseError;
459     DtPrintSetupData    *psd = NULL;
460     int                 save_data;
461
462     /*
463      * Notify the user that we're printing
464      */
465     /* TBD:  Is there a status bar on pPad? */
466
467     if (pJob->pShell == NULL)
468     {
469         {/* TBD error dialog */}
470         PrintJobDestroy(pJob);
471         return;
472     }
473
474     pJob->pOutput = PrintOutputCreate(pJob->pShell);
475     PrintOutputSetWordWrap(pJob->pOutput, PrintSetupUseWordWrap(pJob->pSetup));
476     PrintOutputSetPageMargins(
477         pJob->pOutput,
478         PrintSetupGetMarginSpec(pJob->pSetup, DTPRINT_OPTION_MARGIN_TOP),
479         PrintSetupGetMarginSpec(pJob->pSetup, DTPRINT_OPTION_MARGIN_RIGHT),
480         PrintSetupGetMarginSpec(pJob->pSetup, DTPRINT_OPTION_MARGIN_BOTTOM),
481         PrintSetupGetMarginSpec(pJob->pSetup, DTPRINT_OPTION_MARGIN_LEFT),
482         &parseError
483         );
484     if (parseError)
485     {
486         /*
487          * Display an error dialog.
488         DtMailGenDialog *genDialog = new DtMailGenDialog(
489                                                         "Dialog",
490                                                         _parent->baseWidget());
491          */
492         char    *i18nMsg;
493         char    *errMsg;
494
495         i18nMsg = GETMESSAGE(
496                         14, 1,
497                         "One of the following margin specifiers \n has incorrect syntax: \n %s \n %s \n %s \n %s \nContinue using default margins?"
498                         );
499
500         errMsg = (char *) XtMalloc(1024);
501         sprintf(
502             errMsg,
503             i18nMsg,
504             PrintSetupGetMarginSpec(pJob->pSetup, DTPRINT_OPTION_MARGIN_TOP),
505             PrintSetupGetMarginSpec(pJob->pSetup, DTPRINT_OPTION_MARGIN_RIGHT),
506             PrintSetupGetMarginSpec(pJob->pSetup, DTPRINT_OPTION_MARGIN_BOTTOM),
507             PrintSetupGetMarginSpec(pJob->pSetup, DTPRINT_OPTION_MARGIN_LEFT)
508             );
509
510         Warning(pJob->pPad, (char *) errMsg, XmDIALOG_WARNING);
511         XtFree(errMsg);
512     }
513
514     /*
515      * Load the file
516      */
517     errorCode = PrintOutputLoadFile(pJob->pOutput, pJob->tempFileName);
518     switch (errorCode)
519     {
520         case DtEDITOR_NO_ERRORS:
521         case DtEDITOR_READ_ONLY_FILE:
522             break;
523         case DtEDITOR_NONEXISTENT_FILE:
524             Warning(
525                 pJob->pPad,
526                 (char *) GETMESSAGE(14, 2, "File does not exist."),
527                 XmDIALOG_WARNING);
528             break;
529         case DtEDITOR_DIRECTORY:
530             Warning(
531                 pJob->pPad,
532                 (char *) GETMESSAGE(14, 3, "Specified file is a directory."),
533                 XmDIALOG_WARNING);
534             break;
535         case DtEDITOR_CHAR_SPECIAL_FILE:
536         case DtEDITOR_BLOCK_MODE_FILE:
537             Warning(
538                 pJob->pPad,
539                 (char *) GETMESSAGE(14, 4, "File type error."),
540                 XmDIALOG_WARNING);
541             break;
542         case DtEDITOR_NULLS_REMOVED:
543             Warning(
544                 pJob->pPad,
545                 (char *) GETMESSAGE(14, 5, "File contains NULL characters."),
546                 XmDIALOG_WARNING);
547             break;
548         case DtEDITOR_INSUFFICIENT_MEMORY:
549             Warning(
550                 pJob->pPad,
551                 (char*)
552                 GETMESSAGE(14, 6, "Unable to load file (insufficient memory)."),
553                 XmDIALOG_ERROR);
554                 break;
555         case DtEDITOR_NO_FILE_ACCESS:
556         case DtEDITOR_UNREADABLE_FILE:
557         default:
558             Warning(
559                 pJob->pPad,
560                 (char *)
561                 GETMESSAGE(14, 7, "File does not have read permissions"),
562                 XmDIALOG_WARNING);
563             break;
564     }
565
566     XtRealizeWidget( pJob->pShell );
567
568     PrintOutputFirstPage(pJob->pOutput);
569     pJob->npagesTotal = PrintOutputGetNumLines(pJob->pOutput) +
570                         PrintOutputGetLinesPerPage(pJob->pOutput) - 1;
571     pJob->npagesTotal /= PrintOutputGetLinesPerPage(pJob->pOutput);
572     pJob->npagesDone = 0;
573 }
574
575
576
577
578 /************************************************************************
579  * _pjDoPrint
580  *      Actually run the specified PrintJob.
581  *      Creates the PrintOutput object to be used for printing.
582  *      Initializes the mailbox to iterate through the messages.
583  *      Calls spoolOne to send a print job to the Xp server.
584  ************************************************************************/
585 static void
586 _pjDoPrint(PrintJob *pJob)
587 {
588     static char         buf[1024];
589     static char         *format;
590     DtPrintSetupData    *psd = NULL;
591     int                 dest = XPSpool;
592
593     /*
594      * Notify the user that we're printing
595      */
596     if (pJob->pPad != NULL) {
597         pJob->pPad->numPendingTasks++;
598         format = GETMESSAGE(14, 21, "Printing %s ...");
599         sprintf(buf, format, pJob->documentName);
600         SetStatusMessage(pJob->pPad, buf);
601         XtSetSensitive(pJob->pPad->fileStuff.fileWidgets.printBtn, False);
602     }
603
604 #ifndef PRINT_TO_VIDEO
605     psd = pJob->printData;
606
607     if (psd->destination == DtPRINT_TO_FILE)
608       dest = XPGetData;
609
610     _pjRegisterActivePrintDisplay(XtDisplay(pJob->pShell));
611     XpStartJob(XtDisplay(pJob->pShell), dest);
612     XFlush(XtDisplay(pJob->pShell));
613
614     if (psd->destination == DtPRINT_TO_FILE)
615     {
616         if (FALSE == XmPrintToFile(
617                                 XtDisplay(pJob->pShell),
618                                 psd->dest_info,
619                                 _pjFinishedPrintToFile,
620                                 (XPointer) pJob))
621         {
622             char        *fmt = "%s\n%s:  %s";
623             char        *message;
624             char        *appmessage = NULL;
625             char        *sysmessage = strerror(errno);
626
627             appmessage = (char *) GETMESSAGE(
628                             14, 14,
629                             "'Print to File' was unsuccessful.");
630             
631             if (NULL == sysmessage)
632             {
633                 message = XtMalloc(strlen(appmessage) + 1);
634                 sprintf(message, "%s", appmessage);
635             }
636             else
637             {
638                 message = XtMalloc(
639                                 strlen(appmessage) +
640                                 strlen(sysmessage) +
641                                 strlen(psd->dest_info) +
642                                 strlen(fmt) + 1);
643                 sprintf(message, fmt, appmessage, psd->dest_info, sysmessage);
644             }
645             
646             Warning(pJob->pPad, message, XmDIALOG_WARNING);
647             XtFree(message);
648             
649             XpCancelJob(XtDisplay(pJob->pShell), False);
650             PrintJobDestroy(pJob);
651         }
652     }
653 #endif
654 }
655
656 /************************************************************************
657  * _pjUpdatePageHeaders
658  *      Configures the header and footer string in the PrintOutput. 
659  ************************************************************************/
660 static void
661 _pjUpdatePageHeaders(
662                 PrintJob                *pJob,
663                 PrintStringTypeEnum     hl_type,
664                 PrintStringTypeEnum     hr_type,
665                 PrintStringTypeEnum     fl_type,
666                 PrintStringTypeEnum     fr_type
667                 )
668 {
669     char *hl_string,
670          *hr_string,
671          *fl_string,
672          *fr_string;
673
674     if (pJob == (PrintJob *) NULL) return;
675
676     hl_string = _pjGetPageHeaderString(pJob, hl_type);
677     hr_string = _pjGetPageHeaderString(pJob, hr_type);
678     fl_string = _pjGetPageHeaderString(pJob, fl_type);
679     fr_string = _pjGetPageHeaderString(pJob, fr_type);
680
681     if (PRINT_NONE_STRING_TYPE_ENUM == hl_type &&
682         PRINT_NONE_STRING_TYPE_ENUM == hr_type)
683       PrintOutputHideHeaders(pJob->pOutput);
684     else
685       PrintOutputShowHeaders(pJob->pOutput);
686
687     if (PRINT_NONE_STRING_TYPE_ENUM == fl_type &&
688         PRINT_NONE_STRING_TYPE_ENUM == fr_type)
689       PrintOutputHideFooters(pJob->pOutput);
690     else
691       PrintOutputShowFooters(pJob->pOutput);
692
693
694     PrintOutputSetHdrFtrStrings(
695                                 pJob->pOutput,
696                                 hl_string,
697                                 hr_string,
698                                 fl_string,
699                                 fr_string
700                                 );
701     free(hl_string);
702     free(hr_string);
703     free(fl_string);
704     free(fr_string);
705 }
706
707 /************************************************************************
708  * _pjGetPageHeaderString
709  *      Returns a header and footer string of the specified type.
710  ************************************************************************/
711 static char *
712 _pjGetPageHeaderString(PrintJob *pJob, PrintStringTypeEnum type)
713 {
714     char *format,
715          *buf = (char *) NULL;
716
717     switch (type)
718     {
719         case PRINT_NONE_STRING_TYPE_ENUM:
720             buf = strdup(" ");
721             break;
722         case PRINT_DATE_STRING_TYPE_ENUM:
723             {
724                 time_t  clock;
725                 char    *date;
726
727                 clock = time((time_t*) NULL);
728                 date = ctime(&clock);
729                 /* Strip off the trailing newline. */
730                 date[strlen(date)-1] = '\0';
731                 format = GETMESSAGE(14, 8, "Date:  %s");
732                 buf = (char *) malloc(strlen(format) + strlen(date) + 1);
733                 if (buf != (char *) NULL)
734                   sprintf(buf, format, date);
735             }
736             break;
737         case PRINT_DOCNAME_STRING_TYPE_ENUM:
738             {
739                 unsigned        buflen;
740
741                 format = GETMESSAGE(14, 9, "Document:  %s");
742                 buflen = strlen(format) + strlen(pJob->documentName) + 1;
743                 buf = (char *) malloc(buflen);
744                 if (buf != (char *) NULL)
745                   sprintf(buf, format, pJob->documentName);
746             }
747             break;
748         case PRINT_PAGE_NUMBER_STRING_TYPE_ENUM:
749             /*
750              * Allocate space for the format and the translated page number.
751              */
752             {
753                 format = GETMESSAGE(14, 10, "Page %d of %d");
754                 buf = (char *) malloc(strlen(format) + 16);
755                 if (buf != (char *) NULL)
756                   sprintf(buf, format, pJob->npagesDone, pJob->npagesTotal);
757             }
758             break;
759         case PRINT_USER_NAME_STRING_TYPE_ENUM:
760             /*
761              * Allocate space for the format and the username.
762              */
763             {
764                 struct passwd   *pw;
765
766                 format = GETMESSAGE(14, 11, "Document For:  %s");
767                 pw = getpwuid(getuid());
768                 buf = (char *) malloc(strlen(format) + strlen(pw->pw_name) + 1);
769                 if (buf != (char *) NULL)
770                   sprintf(buf, format, pw->pw_name);
771             }
772             break;
773         default:
774             buf = strdup("DEFAULT not impld");
775             break;
776     }
777     return buf;
778 }
779
780
781 /*
782  *
783  * Name: _pjFinishedPrintToFile
784  *
785  * Description:
786  *
787  *     App-specific print data holder allocate function.
788  *
789  */
790 static void _pjFinishedPrintToFile(
791                         Display         *display,
792                         XPContext       context,
793                         XPGetDocStatus  status,
794                         XPointer        client_data)
795 {
796     char        *message = NULL;
797     PrintJob    *pJob = (PrintJob *) client_data;
798     Editor      *pPad = pJob->pPad;
799
800     if (status != XPGetDocFinished)
801     {
802
803         message = (char *) GETMESSAGE(
804                                 14, 14,
805                                 "'Print to File' was unsuccessful.");
806         Warning(pPad, message, XmDIALOG_WARNING);
807     }
808     else if (display != PrintJobGetErrorPrintDisplay())
809     {
810
811         message = (char *) GETMESSAGE(
812                                 14, 15,
813                                 "'Print to File' completed successfully.");
814         Warning(pPad, message, XmDIALOG_INFORMATION);
815     }
816     PrintJobDestroy(pJob);
817 }
818
819
820 /*
821  * Name: _pjCancelCB
822  * Description:
823  *      An XtCallbackProc which can be added to the callback list of
824  *      a widget to cancel the print job passed back as client_data.
825  */
826 static void
827 _pjCancelCB (Widget widget, XtPointer client_data, XtPointer call_data)
828 {
829     PrintJob *pJob = (PrintJob *) client_data;
830
831     PrintJobDestroy(pJob);
832 }
833
834 /*
835  * Name: _pjCloseDisplayCB
836  * Description:
837  *      An XtCallbackProc which can be added to the callback list of
838  *      a widget to cancel the print job passed back as client_data.
839  */
840 static void
841 _pjCloseDisplayCB (Widget widget, XtPointer client_data, XtPointer call_data)
842 {
843     PrintJob *pJob = (PrintJob *) client_data;
844     DtPrintSetupCallbackStruct *pbs = (DtPrintSetupCallbackStruct *) call_data;
845
846     if (pJob->pShell != NULL)
847     {
848         XtDestroyWidget(pJob->pShell);
849         pJob->pShell = NULL;
850     }
851     DtPrintFreeSetupData(pJob->printData);
852 }
853
854 /*
855  * Name: _pjPrintCB
856  * Description:
857  *      An XtCallbackProc which can be added to the callback list of
858  *      a widget to execute the print job passed back as client_data.
859  */
860 static void
861 _pjPrintCB (Widget widget, XtPointer client_data, XtPointer call_data)
862 {
863     PrintJob *pJob = (PrintJob *) client_data;
864     DtPrintSetupCallbackStruct *pbs = (DtPrintSetupCallbackStruct *) call_data;
865
866     DtPrintCopySetupData(pJob->printData, pbs->print_data);
867     _pjCreatePrintShell(pJob);
868     _pjDoPrint(pJob);
869 }
870
871
872 /*
873  * Name: _pjPdmSetupCB
874  * Description:
875  *      An XtCallbackProc which can be added to the callback list of
876  *      a widget to popup the PDM for the print job.
877  */
878 static void
879 _pjPdmSetupCB(Widget print_setup, XtPointer client_data, XtPointer call_data)
880 {
881     char        *pname = "_pjPdmSetupCB";
882     PrintJob    *pJob = (PrintJob *) client_data;
883     DtPrintSetupCallbackStruct
884                 *pbs = (DtPrintSetupCallbackStruct *) call_data;
885
886     DtPrintCopySetupData(pJob->printData, pbs->print_data);
887     _pjCreatePrintShell(pJob);
888
889     /* Pop up the PDM */
890     if (pJob->pShell)
891     {
892         Widget  shell = print_setup;
893
894         while (! (shell == NULL || XtIsShell(shell)) )
895           shell = XtParent(shell);
896
897         if (shell)
898           XmPrintPopupPDM(pJob->pShell, shell);
899         else
900           fprintf(stderr, "Internal Error %s:  Missing XmPrintShell.", pname);
901     }
902 }
903
904
905 /************************************************************************
906  * _pjPdmNotificationCB
907  *      XmNpdmNotificationCallback for the XmPrintShell
908  ************************************************************************/
909 static void
910 _pjPdmNotificationCB (Widget widget, XtPointer client_data, XtPointer call_data)
911 {
912     PrintJob                    *pJob = (PrintJob*) client_data;
913     XmPrintShellCallbackStruct  *pscbs = (XmPrintShellCallbackStruct*)call_data;
914     char                        *message = NULL;
915
916     switch (pscbs->reason)
917     {
918     
919         case XmCR_PDM_NONE:
920         case XmCR_PDM_START_ERROR:
921         case XmCR_PDM_START_VXAUTH:
922         case XmCR_PDM_START_PXAUTH:
923             message = (char *) GETMESSAGE(
924                         14, 25,
925                         "Print Dialog Manager error - setup failed.");
926             break;
927         default:
928             message = NULL;
929             break;
930     }
931
932     if (message != NULL)
933       Warning( pJob->pPad, message, XmDIALOG_WARNING);
934 }
935
936
937
938 /************************************************************************
939  * _pjPrintOnePageCB
940  *      XmNpageSetupCallback for the XmPrintShell
941  ************************************************************************/
942 static void
943 _pjPrintOnePageCB(
944                 Widget widget,
945                 XtPointer client_data,
946                 XtPointer call_data
947                 )
948 {
949     PrintJob    *pJob = (PrintJob *) client_data;
950
951     XmPrintShellCallbackStruct  *pscbs = (XmPrintShellCallbackStruct*)call_data;
952     int                         top = 0;
953
954     if (pJob->pOutput == NULL)
955     {
956         Dimension       width, height;
957
958         width = 0; height=0;
959         XtVaGetValues(
960                 pJob->pShell,
961                 XmNwidth, &width,
962                 XmNheight, &height,
963                 NULL);
964
965 #if defined(PRINT_TO_VIDEO)
966         printf("PrintShell in _pjPrintOnePageCB: <W %d - H %d>\n",width,height);
967 #endif
968
969         if (width < 100 || height < 100)
970         {
971             width = 2550; height=3250;
972             XtVaSetValues(
973                 pJob->pShell,
974                 XmNwidth, width,
975                 XmNheight, height,
976                 NULL);
977             width = 0; height=0;
978             XtVaGetValues(
979                 pJob->pShell,
980                 XmNwidth, &width,
981                 XmNheight, &height,
982                 NULL);
983 #if defined(PRINT_TO_VIDEO)
984             printf(
985               "PrintShell in _pjPrintOnePageCB: <W %d - H %d>\n",width,height);
986 #endif
987         }
988         _pjCreateOutputWidgets(pJob);
989     }
990
991 #ifdef PRINT_TO_VIDEO
992     if (pJob->npagesDone > 0 && pJob->npagesDone == pJob->npagesTotal)
993 #else
994     if (pscbs->last_page)
995 #endif
996     {
997         DtPrintSetupData    *psd = pJob->printData;
998
999         /*
1000          * This spool job is done.  Clean up.
1001          * If this is a print to file job,
1002          * clean up in the job finished callback.
1003          */
1004         if (psd->destination != DtPRINT_TO_FILE)
1005           PrintJobDestroy(pJob);
1006         return;
1007     }
1008
1009     if (pJob->npagesDone > 0 && PrintOutputPageDown(pJob->pOutput) == FALSE)
1010     {
1011 #ifndef PRINT_TO_VIDEO
1012         pscbs->last_page = TRUE;
1013 #endif
1014         return;
1015     }
1016
1017     /*
1018      * Update header and footer strings.
1019      */
1020     pJob->npagesDone++;
1021     _pjUpdatePageHeaders(
1022         pJob,
1023         PrintSetupGetHdrFtrSpec(pJob->pSetup, DTPRINT_OPTION_HEADER_LEFT),
1024         PrintSetupGetHdrFtrSpec(pJob->pSetup, DTPRINT_OPTION_HEADER_RIGHT),
1025         PrintSetupGetHdrFtrSpec(pJob->pSetup, DTPRINT_OPTION_FOOTER_LEFT),
1026         PrintSetupGetHdrFtrSpec(pJob->pSetup, DTPRINT_OPTION_FOOTER_RIGHT)
1027         );
1028
1029     /*
1030      * Notify the user that we're printing
1031      */
1032     if (pJob->pPad != NULL)
1033     {
1034         static char     buf[1024];
1035         char            *format;
1036
1037         format = GETMESSAGE(14, 22, "Printing %s: page %d of %d ...");
1038         sprintf(buf, format,
1039                 pJob->documentName,
1040                 pJob->npagesDone,
1041                 pJob->npagesTotal);
1042         SetStatusMessage(pJob->pPad, buf);
1043     }
1044
1045 #ifndef PRINT_TO_VIDEO
1046     if (pJob->npagesDone >= pJob->npagesTotal)
1047       pscbs->last_page = TRUE;
1048 #endif
1049 }