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