Disable all code related to libXp
[oweals/cde.git] / cde / programs / dtmail / dtmail / DmxPrintJob.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: DmxPrintJob.C /main/30 1998/07/23 18:11:50 mgreess $ */
24
25 /*
26  *+SNOTICE
27  *
28  *      $:$
29  *
30  *      RESTRICTED CONFIDENTIAL INFORMATION:
31  *      
32  *      The information in this document is subject to special
33  *      restrictions in a confidential disclosure agreement between
34  *      HP, IBM, Sun, USL, SCO and Univel.  Do not distribute this
35  *      document outside HP, IBM, Sun, USL, SCO, or Univel without
36  *      Sun's specific written approval.  This document and all copies
37  *      and derivative works thereof must be returned or destroyed at
38  *      Sun's request.
39  *
40  *      Copyright 1994 Sun Microsystems, Inc.  All rights reserved.
41  *
42  *+ENOTICE
43  */
44 /*
45  *                   Common Desktop Environment
46  *
47  *   (c) Copyright 1993, 1994, 1995 Hewlett-Packard Company
48  *   (c) Copyright 1993, 1994, 1995 International Business Machines Corp.
49  *   (c) Copyright 1993, 1994, 1995 Sun Microsystems, Inc.
50  *   (c) Copyright 1993, 1994, 1995 Novell, Inc.
51  *   (c) Copyright 1995 Digital Equipment Corp.
52  *   (c) Copyright 1995 Fujitsu Limited
53  *   (c) Copyright 1995 Hitachi, Ltd.
54  *                                                                   
55  *
56  *                     RESTRICTED RIGHTS LEGEND                              
57  *
58  *Use, duplication, or disclosure by the U.S. Government is subject to
59  *restrictions as set forth in subparagraph (c)(1)(ii) of the Rights in
60  *Technical Data and Computer Software clause in DFARS 252.227-7013.  Rights
61  *for non-DOD U.S. Government Departments and Agencies are as set forth in
62  *FAR 52.227-19(c)(1,2).
63
64  *Hewlett-Packard Company, 3000 Hanover Street, Palo Alto, CA 94304 U.S.A.
65  *International Business Machines Corp., Route 100, Somers, NY 10589 U.S.A. 
66  *Sun Microsystems, Inc., 2550 Garcia Avenue, Mountain View, CA 94043 U.S.A.
67  *Novell, Inc., 190 River Road, Summit, NJ 07901 U.S.A.
68  *Digital Equipment Corp., 111 Powdermill Road, Maynard, MA 01754, U.S.A.
69  *Fujitsu Limited, 1015, Kamikodanaka Nakahara-Ku, Kawasaki 211, Japan
70  *Hitachi, Ltd., 6, Kanda Surugadai 4-Chome, Chiyoda-ku, Tokyo 101, Japan
71  */
72
73
74 #include <errno.h>
75 #include <pwd.h>
76 #include <stdio.h>
77 #include <stdlib.h>
78 #include <string.h>
79 #include <unistd.h>
80 #include <sys/param.h>
81 #include <X11/Intrinsic.h>
82 #include <X11/Shell.h>
83 #include <Xm/Xm.h>
84 #include <Xm/PushB.h>
85 #if 0 && defined(PRINTING_SUPPORTED)
86 #include <Xm/Print.h>
87 #endif /* PRINTING_SUPPORTED */
88 #include "Dmx.h"
89 #include "DmxPrintJob.h"
90 #include "DmxPrintOptions.h"
91 #include "DmxPrintOutput.h"
92 #include "DmxPrintSetup.h"
93 #include "DtMailGenDialog.hh"
94 #include "DtMailDialogCallbackData.hh"
95 #include "MailMsg.h"
96 #include "OptCmd.h"
97 #include "RoamApp.h"
98
99
100 //
101 // Public class methods
102 //
103
104 DmxPrintJob::DmxPrintJob(
105                         char            *filename,
106                         DtMailBoolean   silent,
107                         MainWindow      *window
108                          ) : UIComponent( "PrintJob" )
109 {
110     _next_msg = (DmxMsg *) NULL;
111     _filename = strdup(filename);
112     _mailbox = (DmxMailbox *) NULL;
113     _parent = window;
114     _print_output = (DmxPrintOutput *) NULL;
115     _print_setup = (DmxPrintSetup *) NULL;
116     _print_data = (DtPrintSetupData *) XtMalloc(sizeof(DtPrintSetupData));
117     memset((void*) _print_data, 0, sizeof(DtPrintSetupData));
118     _pshell = (Widget) NULL;
119     _silent = silent;
120
121     _spool_msg_info = (DmxMsgInfo *) NULL;
122     _spool_nmsgs_done = 0;
123     _spool_nmsgs_total = 0;
124     _spool_npages_done = 0;
125     _spool_npages_total = 0;
126     _w = XtCreateWidget(_name, coreWidgetClass, _parent->baseWidget(), NULL, 0);
127     installDestroyHandler();
128
129     _nextpage_shell = NULL;
130     _nextpage_button = NULL;
131 }
132
133 DmxPrintJob::~DmxPrintJob (void)
134 {
135     //
136     // Unregister the fact that we have a print job running so
137     // dtmail can terminate.
138     //
139     if (_parent != NULL)
140       _parent->unregisterPendingTask();
141
142     if (_filename)
143     {
144         free(_filename);
145         _filename = NULL;
146     }
147     if (_mailbox)
148     {
149         delete _mailbox;
150         _mailbox = NULL;
151     }
152     if (_spool_msg_info)
153     {
154         XtFree((char*) _spool_msg_info);
155         _spool_msg_info = NULL;
156     }
157     if (_print_output)
158     {
159         delete _print_output;
160         _print_output = NULL;
161     }
162     if (_print_setup)
163     {
164         delete _print_setup;
165         _print_setup = NULL;
166     }
167     if (_pshell)
168     {
169         XtDestroyWidget(_pshell);
170         _pshell = NULL;
171     }
172     if (_print_data)
173     {
174         DtPrintFreeSetupData(_print_data);
175         XtFree((char *) _print_data);
176         _print_data = NULL;
177     }
178     if (_nextpage_shell)
179     {
180         XtDestroyWidget(_nextpage_shell);
181         _nextpage_shell = NULL;
182     }
183     if (_w)
184     {
185         //
186         //  Do not destroy this widget.
187         //  BasicComponent takes care of this for us.
188         //
189     }
190 }
191
192 /*
193  * Name: DmxPrintJob::cancel
194  * Description:
195  *      Public method used to cancel the print job.
196  */
197 void
198 DmxPrintJob::cancel(void)
199 {
200
201     _parent->clearStatus();
202
203     if (NULL != _pshell)
204     {
205         Display *display = XtDisplay(_pshell);
206
207         theRoamApp.unregisterActivePrintDisplay(display);
208         if (display == theRoamApp.getErrorPrintDisplay())
209         {
210             //
211             // Need to display an error dialog;
212             //
213             DtMailGenDialog *genDialog = new DtMailGenDialog(
214                                                         "Dialog",
215                                                         _parent->baseWidget());
216             char *errMsg =
217               GETMSG(
218                 DT_catd, 21, 23,
219                 "The X Print Server is temporarily out of resources.");
220
221             genDialog->setToErrorDialog(GETMSG(DT_catd, 1, 6, "Mailer"),
222                                         errMsg);
223             genDialog->post_and_return(GETMSG(DT_catd, 3, 9, "OK"), NULL);
224             delete genDialog;
225
226             theRoamApp.setErrorPrintDisplay(NULL);
227         }
228     }
229     delete this;
230 }
231
232 /*
233  * Name: DmxPrintJob::execute
234  * Description:
235  *      Public method used to execute the print job.
236  */
237 void
238 DmxPrintJob::execute (void)
239 {
240     theRoamApp.busyAllWindows();
241     _print_setup = new DmxPrintSetup(
242                                 _parent->baseWidget(),
243                                 &DmxPrintJob::printCB, (XtPointer) this,
244                                 &DmxPrintJob::cancelCB, (XtPointer) this,
245                                 &DmxPrintJob::closeDisplayCB, (XtPointer) this,
246                                 &DmxPrintJob::pdmSetupCB, (XtPointer) this);
247
248     //
249     // load in the messages
250     //
251     _mailbox = new DmxMailbox(_filename);
252     _mailbox->loadMessages();
253     _next_msg = _mailbox->firstMessage();
254
255     if (_mailbox->numMessages() == 1)
256     {
257         int     i,j,last_space;
258         char    *orig_subject = _next_msg->getMessageHeader(DMXSUBJ);
259         int     orig_len = strlen(orig_subject);
260         char    *subject = (char*) malloc(orig_len+1);
261         char    *filename = (char*) malloc(MAXPATHLEN+1);
262
263         
264         for (i=0,j=0,last_space=0; i<orig_len; i++)
265         {
266             if (isspace(orig_subject[i]))
267             {
268                 if (last_space < i-1)
269                   subject[j++] = ' ';
270                 last_space = i;
271             }
272             else if (orig_subject[i] == '/')
273               subject[j++] = '\\';
274             else
275               subject[j++] = orig_subject[i];
276         }
277         subject[j] = '\0';
278         sprintf(filename, "%s/%s.ps", getenv("HOME"), subject);
279
280         _print_setup->setPrintToFileName(filename);
281         free(orig_subject);
282         free(subject);
283         free(filename);
284     }
285     theRoamApp.unbusyAllWindows();
286
287     if (_silent) {
288         if (DTM_TRUE != _print_setup->getDefaultPrintData(_print_data))
289           //
290           // DtPrintSetupDialog is popped up automatically.
291           //
292           return;
293
294         createPrintShell();
295         doPrint();
296     } else {
297         _print_setup->display();
298     }
299 }
300
301
302
303 //
304 // Private class methods
305 //
306
307 /*
308  * Name: DmxPrintJob::createPrintShell
309  * Description:
310  *      Creates the XmPrint Shell widget.
311  */
312 void
313 DmxPrintJob::createPrintShell (void)
314 {
315 #if 0 && defined(PRINTING_SUPPORTED)
316     DtMailEnv           dmxenv;
317     DtMail::Session     *d_session = theRoamApp.session()->session();
318
319     if (_pshell != NULL) return;
320
321     //
322     // Create the print shell and
323     // the print output widgets
324     //
325 #ifdef PRINT_TO_VIDEO 
326     XmString    xms;
327
328     /*
329      * Create a dialog shell widget on the video display.
330      */
331     _pshell = XmCreateDialogShell(_parent->baseWidget(), "PrintVideo", NULL, 0);
332
333     _nextpage_shell = XtVaCreateWidget(
334                         "PrintNextPage",
335                          topLevelShellWidgetClass,
336                          _parent->baseWidget(),
337                          XmNx, 0,
338                          XmNy, 0,
339                          NULL);
340
341     xms = XmStringCreateLocalized("Push for Next Page");
342     _nextpage_button = XtVaCreateManagedWidget(
343                                 "NextPageButton",
344                                 xmPushButtonWidgetClass,
345                                 _nextpage_shell,
346                                 XmNlabelString, xms,
347                                 XmNwidth, 300,
348                                 XmNheight, 300,
349                                 NULL);
350     XmStringFree(xms);
351
352     XtAddCallback(
353                 _nextpage_button,
354                 XmNactivateCallback, 
355                 &DmxPrintJob::printOnePageCB,
356                 (XtPointer) this);
357
358     XtRealizeWidget(_nextpage_shell);
359     XtManageChild(_nextpage_shell);
360 #else
361     /*
362      * Create an XmPrintShell widget on the video display.
363      */
364     _pshell = XmPrintSetup(
365                 _parent->baseWidget(),
366                 XpGetScreenOfContext(
367                                 _print_data->print_display,
368                                 _print_data->print_context),
369                 "Print",
370                 NULL, 0);
371
372     XtAddCallback(
373                 _pshell,
374                 XmNpageSetupCallback,
375                 &DmxPrintJob::printOnePageCB,
376                 (XtPointer) this);
377     XtAddCallback(
378                 _pshell,
379                 XmNpdmNotificationCallback,
380                 &DmxPrintJob::pdmNotificationCB,
381                 (XtPointer) this);
382 #endif
383
384 #endif  /* PRINTING_SUPPORTED */
385 }
386
387
388 /*
389  * Name: DmxPrintJob::createOutputWidgets
390  * Description:
391  *      Creates the DmxPrintOutput object to be used for printing.
392  */
393 void
394 DmxPrintJob::createOutputWidgets (void)
395 {
396     DtMailEnv           dmxenv;
397     DtMail::Session     *d_session = theRoamApp.session()->session();
398     DtMailBoolean       parse_error = DTM_FALSE;
399     const char          *top;
400     const char          *right;
401     const char          *bottom;
402     const char          *left;
403
404     _print_output = new DmxPrintOutput( _pshell );
405     _print_output->setWrapToFit(_print_setup->useWordWrap());
406     top         = DmxPrintOptions::getMarginSpec(DTPRINT_OPTION_MARGIN_TOP);
407     right       = DmxPrintOptions::getMarginSpec(DTPRINT_OPTION_MARGIN_RIGHT);
408     bottom      = DmxPrintOptions::getMarginSpec(DTPRINT_OPTION_MARGIN_BOTTOM);
409     left        = DmxPrintOptions::getMarginSpec(DTPRINT_OPTION_MARGIN_LEFT);
410     _print_output->setPageMargins(top, right, bottom, left, &parse_error);
411     if (parse_error)
412     {
413         DtMailGenDialog *genDialog = new DtMailGenDialog(
414                                                         "Dialog",
415                                                         _parent->baseWidget());
416         char            *errMsg = (char *) XtMalloc(1024);
417         char            *i18nMsg;
418
419         i18nMsg = GETMSG(
420                         DT_catd, 21, 2,
421                         "One of the following margin specifiers \n has incorrect syntax: \n %s \n %s \n %s \n %s \nContinue using default margins?"
422                         );
423
424         sprintf(errMsg, i18nMsg, top, right, bottom, left);
425         genDialog->setToErrorDialog(
426                             GETMSG(DT_catd, 21, 3, "Mailer"),
427                             errMsg);
428         XtFree(errMsg);
429
430         genDialog->post_and_return(
431                             GETMSG(DT_catd, 21, 4, "OK"),
432                             NULL);
433         delete genDialog;
434     }
435
436     XtRealizeWidget( _pshell );
437
438     if (NULL != top)
439       free((void*) top);
440     if (NULL != right)
441       free((void*) right);
442     if (NULL != bottom)
443       free((void*) bottom);
444     if (NULL != left)
445       free((void*) left);
446 }
447
448 void
449 ok_cb(DtMailGenDialog *genDialog)
450 {
451     delete genDialog;
452 }
453
454 /*
455  * Name: DmxPrintJob::doPrint
456  * Description:
457  *      Creates a DmxMailbox and loads the contents of the message file.
458  *      Initializes the mailbox to iterate through the messages.
459  *      Calls XmPrintToFile or XpStartJob to initiate printing.
460  */
461 void
462 DmxPrintJob::doPrint (void)
463 {
464 #if 0 && defined(PRINTING_SUPPORTED)
465     DtMailEnv           dmxenv;
466     DtMail::Session     *d_session = theRoamApp.session()->session();
467     XPSaveData          dest = XPSpool;
468
469     //
470     // Notify the user that we're printing
471     //
472     if (_parent != NULL) {
473         char *buf = new char[1024];
474         char *msg = GETMSG(DT_catd, 21, 1, "Printing %s ...");
475         sprintf(buf, msg, _filename);
476         _parent->setStatus(buf);
477
478         //
479         // Register the fact that we have a print job running so
480         // dtmail will not terminate in the middle.
481         //
482         _parent->registerPendingTask();
483         delete [] buf;
484     }
485
486     //
487     // load in the messages
488     //
489     // Moved to DmxPrintJob::execute
490     //
491     //_mailbox = new DmxMailbox(_filename);
492     //_mailbox->loadMessages();
493     //_next_msg = _mailbox->firstMessage();
494
495     if (_next_msg)
496       _spool_msg_info = (DmxMsgInfo *) XtCalloc(
497                                         _mailbox->numMessages(),
498                                         sizeof(DmxMsgInfo));
499
500 #ifndef PRINT_TO_VIDEO
501     if (_print_data == NULL) return;
502
503     if (_print_data->destination == DtPRINT_TO_FILE)
504       dest = XPGetData;
505
506     theRoamApp.registerActivePrintDisplay(XtDisplay(_pshell));
507     XpStartJob(XtDisplay(_pshell), dest);
508     XFlush(XtDisplay(_pshell));
509
510     if (_print_data->destination == DtPRINT_TO_FILE)
511     {
512         if (FALSE == XmPrintToFile(
513                         XtDisplay(_pshell),
514                         _print_data->dest_info,
515                         (XPFinishProc) &DmxPrintJob::finishedPrintToFile,
516                         (XPointer) this))
517         {
518             char                *fmt = "%s\n%s:  %s";
519             DtMailGenDialog     *genDialog;
520             char                *appmessage = NULL;
521             char                *message = NULL;
522             char                *sysmessage = strerror(errno);
523             Widget              w = (Widget) this->_parent->baseWidget();
524  
525             XpCancelJob(XtDisplay(_pshell), False);
526             XFlush(XtDisplay(_pshell));
527
528             genDialog = new DtMailGenDialog("Dialog", w);
529             appmessage = (char *) GETMSG(
530                                 DT_catd, 21, 14,
531                                 "'Print to File'  was unsuccessful.");
532  
533             if (NULL == sysmessage)
534             {
535                 message = XtMalloc(strlen(appmessage) + 1);
536                 sprintf(message, "%s", appmessage);
537             }
538             else
539             {
540                 message = XtMalloc(
541                                 strlen(appmessage) +
542                                 strlen(sysmessage) +
543                                 strlen(_print_data->dest_info) +
544                                 strlen(fmt) + 1);
545                 sprintf(
546                         message, fmt,
547                         appmessage, _print_data->dest_info, sysmessage);
548             }
549  
550             genDialog->setToErrorDialog(
551                             GETMSG(DT_catd, 21, 3, "Mailer"),
552                             message);
553 #if 0
554             genDialog->post_and_return(
555                             GETMSG(DT_catd, 21, 4, "OK"),
556                             NULL);
557             delete genDialog;
558 #else
559             genDialog->post((void*) genDialog, (DialogCallback) ok_cb);
560 #endif
561             XtFree(message);
562  
563             this->cancel();
564         }
565     }
566 #endif
567 #endif  /* PRINTING_SUPPORTED */
568 }
569
570
571
572 Boolean
573 DmxPrintJob::loadOutputWidgets(void)
574 {
575     if (! _next_msg)
576       return FALSE;
577
578     _print_output->clearContents();
579     _spool_nmsgs_done = 0;
580     _spool_nmsgs_total = 0;
581     _spool_npages_done = 0;
582     _spool_npages_total = 0;
583
584     do
585     {
586 #if 0
587         _next_msg->display(
588                         DmxPrintOptions::getPrintedHeaders(),
589                         (DmxMsg::DmxPrintOutputProc) fprintf,
590                         (XtPointer) stdout);
591 #endif
592         _next_msg->display(
593                         DmxPrintOptions::getPrintedHeaders(),
594                         &DmxPrintOutput::appendContents,
595                         (XtPointer) _print_output);
596
597         switch (DmxPrintOptions::getMessageSeparator())
598         {
599           case DMX_SEPARATOR_BLANK_LINE:
600             _print_output->appendNewLine();
601             _print_output->appendNewLine();
602             break;
603           case DMX_SEPARATOR_CHARACTER_LINE:
604             {
605                 #define DMXPJ_MAX_SEPARATOR_LENGTH 100
606                 char    *buffer;
607                 const char *separator_string;
608                 int     len, nchars;
609
610                 separator_string = DmxPrintOptions::getSeparatorString();
611                 len = strlen(separator_string);
612                 nchars = _print_output->getCharactersPerLine() - 5;
613 #ifdef PRINT_TO_VIDEO
614                 fprintf(stderr, "getCharactersPerLine:  <%d>\n", nchars);
615 #endif
616                 nchars = (nchars < DMXPJ_MAX_SEPARATOR_LENGTH) ?
617                          nchars : DMXPJ_MAX_SEPARATOR_LENGTH;
618                 buffer = XtMalloc(nchars+len+1);
619                 *buffer = '\0';
620                 for (int i=0; i<nchars-1; i+=len)
621                 {
622                     int nbytes = (len < nchars-i) ? len : nchars-i;
623                     strncat(buffer, separator_string, nbytes);
624                 }
625                 buffer[nchars-1] = '\0';
626
627                 _print_output->appendNewLine();
628                 _print_output->appendContents((void*) _print_output, buffer);
629                 _print_output->appendNewLine();
630                 _print_output->appendNewLine();
631
632                 XtFree(buffer);
633                 if (NULL != separator_string)
634                   free((void*) separator_string);
635                 
636                 break;
637             }
638           case DMX_SEPARATOR_PAGE_BREAK:
639           case DMX_SEPARATOR_NEW_JOB:
640             _print_output->appendPageBreak();
641             break;
642           case DMX_SEPARATOR_NEW_LINE:
643           default:
644             _print_output->appendNewLine();
645             break;
646         }
647
648         assert(_spool_nmsgs_total < _mailbox->numMessages());
649         _spool_msg_info[_spool_nmsgs_total].msg = _next_msg;
650         _spool_msg_info[_spool_nmsgs_total].end_position =
651             _print_output->getLastPosition();
652
653         _spool_nmsgs_total++;
654
655     } while ( (  (_next_msg = _mailbox->nextMessage()) != (DmxMsg *) NULL  ) &&
656               (  (! _print_setup->printSeparately()) ||
657                  (_print_data->destination == DtPRINT_TO_FILE )  )
658             );
659
660
661     _print_output->setTopPosition(0);
662     _spool_npages_total = _print_output->getNumLines() +
663                         _print_output->getLinesPerPage() - 1;
664     _spool_npages_total /= _print_output->getLinesPerPage();
665
666     return TRUE;
667 }
668
669 void
670 DmxPrintJob::printOnePageCB(
671                         Widget,
672                         XtPointer client_data,
673                         XtPointer call_data)
674 {
675 #if 0 && defined(PRINTING_SUPPORTED)
676     DmxPrintJob         *thisJob = (DmxPrintJob *) client_data;
677
678     XmPrintShellCallbackStruct  *pscbs = (XmPrintShellCallbackStruct*)call_data;
679     DmxMsg                      *currmsg;
680     int                         top = 0;
681
682     if (thisJob->_print_output == NULL)
683     {
684         
685         XtArgVal /* Dimension */        width, height;
686
687         width = 0; height=0;
688         XtVaGetValues(
689                 thisJob->_pshell,
690                 XmNwidth, &width,
691                 XmNheight, &height,
692                 NULL);
693 #if PRINT_TO_VIDEO
694         printf("PrintShell in PrintOnePageCB: <W %d - H %d>\n", width, height);
695 #endif
696
697         if (width < 100 || height < 100)
698         {
699             width = 2550; height=3250;
700             XtVaSetValues(
701                     thisJob->_pshell,
702                     XmNwidth, width,
703                     XmNheight, height,
704                     NULL);
705             width = 0; height=0;
706             XtVaGetValues(
707                     thisJob->_pshell,
708                     XmNwidth, &width,
709                     XmNheight, &height,
710                     NULL);
711
712 #if PRINT_TO_VIDEO
713             printf("PrintShell in PrintOnePageCB: <W %d - H %d>\n",
714                    width,height);
715 #endif
716         }
717
718         thisJob->createOutputWidgets();
719         if (! thisJob->loadOutputWidgets())
720         {
721             thisJob->cancel();
722             return;
723         }
724     }
725
726 #ifndef PRINT_TO_VIDEO 
727     if (pscbs->last_page)
728 #else
729     if (thisJob->_spool_npages_done == thisJob->_spool_npages_total)
730 #endif
731     {
732         int     dest = XPSpool;
733
734         //
735         // This spool job is done.
736         // Try spooling the next one.
737         //
738         if (! thisJob->loadOutputWidgets())
739         {
740             if (thisJob->_print_data->destination != DtPRINT_TO_FILE)
741               thisJob->cancel();
742             return;
743         }
744
745         //
746         // Register a work proc to print one page at a time
747         //
748 #ifndef PRINT_TO_VIDEO 
749         if (thisJob->_print_data->destination == DtPRINT_TO_FILE)
750           dest = XPGetData;
751
752         XpStartJob(XtDisplay(thisJob->_pshell), dest);
753         XFlush(XtDisplay(thisJob->_pshell));
754
755         if (thisJob->_print_data->destination == DtPRINT_TO_FILE)
756           XmPrintToFile(
757                 XtDisplay(thisJob->_pshell),
758                 thisJob->_print_data->dest_info,
759                 (XPFinishProc) &DmxPrintJob::finishedPrintToFile,
760                 (XPointer) thisJob);
761 #endif
762
763         return;
764     }
765
766     if (thisJob->_spool_npages_done == 0)
767     {
768         thisJob->_print_output->setTopPosition(0);
769     }
770     else if (! thisJob->_print_output->pageDown())
771     {
772 #ifndef PRINT_TO_VIDEO 
773         pscbs->last_page = TRUE;
774 #endif
775         return;
776     }
777     else
778     {
779         int top = thisJob->_print_output->getTopPosition();
780         int currmsg_i = thisJob->_spool_nmsgs_done;
781
782         //
783         // Find the index into the ._spool_msg_info array of the
784         // message which will begin the next page.  This message
785         // will be used to set the header and footer strings.
786         //
787         while (top > thisJob->_spool_msg_info[currmsg_i].end_position &&
788                currmsg_i < thisJob->_spool_nmsgs_total)
789           currmsg_i++;
790
791         assert(top <= thisJob->_spool_msg_info[currmsg_i].end_position);
792         thisJob->_spool_nmsgs_done = currmsg_i;
793     }
794
795     currmsg = thisJob->_spool_msg_info[thisJob->_spool_nmsgs_done].msg;
796     assert(currmsg != (DmxMsg *) NULL);
797     if (currmsg == (DmxMsg *) NULL)
798     {
799 #ifndef PRINT_TO_VIDEO 
800         pscbs->last_page = TRUE;
801 #endif
802         return;
803     }
804
805     //
806     // Update header and footer strings.
807     //
808     thisJob->_spool_npages_done++;
809     thisJob->updatePageHeaders(
810                 currmsg,
811                 DmxPrintOptions::getHdrFtrSpec(DTPRINT_OPTION_HEADER_LEFT),
812                 DmxPrintOptions::getHdrFtrSpec(DTPRINT_OPTION_HEADER_RIGHT),
813                 DmxPrintOptions::getHdrFtrSpec(DTPRINT_OPTION_FOOTER_LEFT),
814                 DmxPrintOptions::getHdrFtrSpec(DTPRINT_OPTION_FOOTER_RIGHT)
815                 );
816
817 #ifndef PRINT_TO_VIDEO 
818     if (thisJob->_spool_npages_done >= thisJob->_spool_npages_total)
819       pscbs->last_page = TRUE;
820 #endif
821 #endif  /* PRINTING_SUPPORTED */
822 }
823
824
825 void
826 DmxPrintJob::updatePageHeaders(
827                                 DmxMsg                  *msg,
828                                 DmxStringTypeEnum       hl_type,
829                                 DmxStringTypeEnum       hr_type,
830                                 DmxStringTypeEnum       fl_type,
831                                 DmxStringTypeEnum       fr_type
832                                 )
833 {
834     char *hl_string,
835          *hr_string,
836          *fl_string,
837          *fr_string;
838
839     if (msg == (DmxMsg *) NULL)
840       return;
841
842     hl_string = getPageHeaderString(msg, hl_type);
843     hr_string = getPageHeaderString(msg, hr_type);
844     fl_string = getPageHeaderString(msg, fl_type);
845     fr_string = getPageHeaderString(msg, fr_type);
846     
847     _print_output->setHdrFtrStrings(
848                                 hl_string,
849                                 hr_string,
850                                 fl_string,
851                                 fr_string);
852     
853     if (DMX_NONE_STRING == hl_type && DMX_NONE_STRING == hr_type)
854       _print_output->hideHeaders();
855     else
856       _print_output->showHeaders();
857
858     if (DMX_NONE_STRING == fl_type && DMX_NONE_STRING == fr_type)
859       _print_output->hideFooters();
860     else
861       _print_output->showFooters();
862
863     free(hl_string);
864     free(hr_string);
865     free(fl_string);
866     free(fr_string);
867 }
868
869 char *
870 DmxPrintJob::getPageHeaderString(
871                                 DmxMsg                  *msg,
872                                 DmxStringTypeEnum       type
873                                    )
874 {
875     char *format,
876          *buf = (char *) NULL;
877
878
879     if (msg == (DmxMsg *) NULL)
880       return NULL;
881
882     switch (type)
883     {
884         case DMX_NONE_STRING:
885             buf = strdup(" ");
886             break;
887         case DMX_CC_HEADER_STRING:
888             {
889                 char    *hdrstr = msg->getMessageHeader(DMXCC);
890
891                 format = GETMSG(DT_catd, 21, 5, "Cc:  %s");
892                 buf = (char *) malloc(strlen(format) + strlen(hdrstr) + 1); 
893                 if (buf != (char *) NULL)
894                   sprintf(buf, format, hdrstr);
895                 
896                 free(hdrstr);
897             }
898             break;
899         case DMX_DATE_HEADER_STRING:
900             {
901                 char    *hdrstr = msg->getMessageHeader(DMXDATE);
902
903                 format = GETMSG(DT_catd, 21, 6, "Date:  %s");
904                 buf = (char *) malloc(strlen(format) + strlen(hdrstr) + 1); 
905                 if (buf != (char *) NULL)
906                   sprintf(buf, format, hdrstr);
907                 
908                 free(hdrstr);
909             }
910             break;
911         case DMX_FROM_HEADER_STRING:
912             {
913                 char    *hdrstr = msg->getMessageHeader(DMXFROM);
914
915                 format = GETMSG(DT_catd, 21, 7, "From:  %s");
916                 buf = (char *) malloc(strlen(format) + strlen(hdrstr) + 1); 
917                 if (buf != (char *) NULL)
918                   sprintf(buf, format, hdrstr);
919                 
920                 free(hdrstr);
921             }
922             break;
923         case DMX_SUBJECT_HEADER_STRING:
924             {
925                 char    *hdrstr = msg->getMessageHeader(DMXSUBJ);
926
927                 format = GETMSG(DT_catd, 21, 8, "Subject:  %s");
928                 buf = (char *) malloc(strlen(format) + strlen(hdrstr) + 1); 
929                 if (buf != (char *) NULL)
930                   sprintf(buf, format, hdrstr);
931                 
932                 free(hdrstr);
933             }
934             break;
935         case DMX_TO_HEADER_STRING:
936             {
937                 char    *hdrstr = msg->getMessageHeader(DMXTO);
938
939                 format = GETMSG(DT_catd, 21, 9, "To:  %s");
940                 buf = (char *) malloc(strlen(format) + strlen(hdrstr) + 1); 
941                 if (buf != (char *) NULL)
942                   sprintf(buf, format, hdrstr);
943                 
944                 free(hdrstr);
945             }
946             break;
947         case DMX_PAGE_NUMBER_STRING:
948             // 
949             // Allocate space for the format and the translated page number.
950             //
951             {
952                 format = GETMSG(DT_catd, 21, 10, "Page %d of %d");
953                 buf = (char *) malloc(strlen(format) + 16); 
954                 if (buf != (char *) NULL)
955                   sprintf(buf, format, _spool_npages_done, _spool_npages_total);
956             }
957             break;
958         case DMX_USER_NAME_STRING:
959             // 
960             // Allocate space for the format and the username.
961             //
962             {
963                 struct passwd   *pw;
964                 
965                 format = GETMSG(DT_catd, 21, 11, "Mail For:  %s");
966                 pw = getpwuid(getuid());
967                 buf = (char *) malloc(strlen(format) + strlen(pw->pw_name) + 1);
968                 if (buf != (char *) NULL)
969                   sprintf(buf, format, pw->pw_name);
970             }
971             break;
972         default:
973             buf = strdup("DEFAULT not impld");
974             break;
975     }
976     return buf;
977 }
978
979 /*
980  * Name: DmxPrintJob::finishedPrintToFile
981  * Description:
982  */
983 #if 0 && defined(PRINTING_SUPPORTED)
984 void
985 DmxPrintJob::finishedPrintToFile(
986                         Display         *display,
987                         XPContext,
988                         XPGetDocStatus  status,
989                         XPointer        client_data)
990
991 {
992     DmxPrintJob *thisJob = (DmxPrintJob*) client_data;
993     Widget      w = (Widget) thisJob->_parent->baseWidget();
994     char        *message = NULL;
995
996     if (status != XPGetDocFinished)
997     {
998         DtMailGenDialog *genDialog = new DtMailGenDialog("Dialog", w);
999
1000         message = (char *) GETMSG(
1001                                 DT_catd, 21, 14,
1002                                 "'Print to File'  was unsuccessful.");
1003         genDialog->setToErrorDialog(
1004                             GETMSG(DT_catd, 21, 3, "Mailer"),
1005                             message);
1006         genDialog->post_and_return(
1007                             GETMSG(DT_catd, 21, 4, "OK"),
1008                             NULL);
1009         delete genDialog;
1010     }
1011     else if (display != theRoamApp.getErrorPrintDisplay())
1012     {
1013         DtMailGenDialog *genDialog = new DtMailGenDialog("Dialog", w);
1014
1015         message = (char *) GETMSG(
1016                                 DT_catd, 21, 15,
1017                                 "'Print to File' completed successfully");
1018
1019         genDialog->setToWarningDialog(
1020                             GETMSG(DT_catd, 21, 3, "Mailer"),
1021                             message);
1022         genDialog->post_and_return(
1023                             GETMSG(DT_catd, 21, 4, "OK"),
1024                             NULL);
1025         delete genDialog;
1026     }
1027     thisJob->cancel();
1028 }
1029 #endif /* PRINTING_SUPPORTED */
1030
1031 /*
1032  * Name: DmxPrintJob::cancelCB
1033  * Description:
1034  *      An XtCallbackProc which can be added to the callback list of
1035  *      a widget to cancel the print job passed back as client_data.
1036  */
1037 void
1038 DmxPrintJob::cancelCB (Widget, XtPointer client_data, XtPointer)
1039 {
1040     DmxPrintJob *thisJob = (DmxPrintJob *) client_data;
1041
1042     thisJob->cancel();
1043 }
1044
1045 /*
1046  * Name: DmxPrintJob::closeDisplayCB
1047  * Description:
1048  *      An XtCallbackProc which can be added to the callback list of
1049  *      a widget to react to the print setup closing the display.
1050  */
1051 void
1052 DmxPrintJob::closeDisplayCB (Widget, XtPointer client_data, XtPointer call_data)
1053 {
1054     DmxPrintJob *thisJob = (DmxPrintJob *) client_data;
1055     DtPrintSetupCallbackStruct *pbs = (DtPrintSetupCallbackStruct *) call_data;
1056
1057     if (thisJob->_pshell != NULL)
1058     {
1059         XtDestroyWidget(thisJob->_pshell);
1060         thisJob->_pshell = NULL;
1061     }
1062     DtPrintFreeSetupData(thisJob->_print_data);
1063 }
1064
1065 /*
1066  * Name: DmxPrintJob::pdmNotificationCB
1067  * Description:
1068  *       XmNpdmNotificationCallback for the XmPrintShell
1069  */
1070 void
1071 DmxPrintJob::pdmNotificationCB(
1072                         Widget,
1073                         XtPointer client_data,
1074                         XtPointer call_data)
1075 {
1076 #if 0 && defined(PRINTING_SUPPORTED)
1077     DmxPrintJob                 *thisJob = (DmxPrintJob *) client_data;
1078     XmPrintShellCallbackStruct  *pscbs = (XmPrintShellCallbackStruct*)call_data;
1079     char                        *message = NULL;
1080
1081     switch (pscbs->reason)
1082     {
1083     
1084         case XmCR_PDM_NONE:
1085         case XmCR_PDM_START_ERROR:
1086         case XmCR_PDM_START_VXAUTH:
1087         case XmCR_PDM_START_PXAUTH:
1088             message = (char *) GETMSG(
1089                         DT_catd, 21, 24,
1090                         "Print Dialog Manager error - setup failed.");
1091             break;
1092         default:
1093             message = NULL;
1094             break;
1095     }
1096
1097     if (message != NULL)
1098     {
1099         DtMailGenDialog *genDialog = new DtMailGenDialog(
1100                                                 "Dialog",
1101                                                 thisJob->_parent->baseWidget());
1102         genDialog->setToErrorDialog(
1103                             GETMSG(DT_catd, 21, 3, "Mailer"),
1104                             message);
1105         genDialog->post_and_return(
1106                             GETMSG(DT_catd, 21, 25, "Continue"),
1107                             NULL);
1108         delete genDialog;
1109     }
1110 #endif  /* PRINTING_SUPPORTED */
1111 }
1112
1113 /*
1114  * Name: DmxPrintJob::pdmSetupCB
1115  * Description:
1116  *      An XtCallbackProc which can be added to the callback list of
1117  *      a widget to execute the print job passed back as client_data.
1118  */
1119 void
1120 DmxPrintJob::pdmSetupCB(
1121                 Widget print_setup,
1122                 XtPointer client_data,
1123                 XtPointer call_data)
1124 {
1125 #if 0 && defined(PRINTING_SUPPORTED)
1126     DmxPrintJob *thisJob = (DmxPrintJob *) client_data;
1127     DtPrintSetupCallbackStruct *pbs = (DtPrintSetupCallbackStruct *) call_data;
1128
1129     DtPrintCopySetupData(thisJob->_print_data, pbs->print_data);
1130     thisJob->createPrintShell();
1131
1132     if (thisJob->_pshell)
1133     {
1134         Widget  shell = print_setup;
1135
1136         while (! (shell == NULL || XtIsShell(shell)) )
1137           shell = XtParent(shell);
1138
1139         if (shell)
1140           XmPrintPopupPDM(thisJob->_pshell, shell);
1141         else
1142           fprintf(stderr, "Internal Error:  Missing XmPrintShell\n");
1143     }
1144 #endif  /* PRINTING_SUPPORTED */
1145 }
1146
1147 /*
1148  * Name: DmxPrintJob::printCB
1149  * Description:
1150  *      An XtCallbackProc which can be added to the callback list of
1151  *      a widget to execute the print job passed back as client_data.
1152  */
1153 void
1154 DmxPrintJob::printCB (Widget, XtPointer client_data, XtPointer call_data)
1155 {
1156     DmxPrintJob *thisJob = (DmxPrintJob *) client_data;
1157     DtPrintSetupCallbackStruct *pbs = (DtPrintSetupCallbackStruct *) call_data;
1158
1159     /* TBD: Save options??? */
1160
1161     DtPrintCopySetupData(thisJob->_print_data, pbs->print_data);
1162     thisJob->createPrintShell();
1163     thisJob->doPrint();
1164 }