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