dthelp: Change to ANSI function definitions
[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 libraries 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                 free((void*) separator_string);
634                 
635                 break;
636             }
637           case DMX_SEPARATOR_PAGE_BREAK:
638           case DMX_SEPARATOR_NEW_JOB:
639             _print_output->appendPageBreak();
640             break;
641           case DMX_SEPARATOR_NEW_LINE:
642           default:
643             _print_output->appendNewLine();
644             break;
645         }
646
647         assert(_spool_nmsgs_total < _mailbox->numMessages());
648         _spool_msg_info[_spool_nmsgs_total].msg = _next_msg;
649         _spool_msg_info[_spool_nmsgs_total].end_position =
650             _print_output->getLastPosition();
651
652         _spool_nmsgs_total++;
653
654     } while ( (  (_next_msg = _mailbox->nextMessage()) != (DmxMsg *) NULL  ) &&
655               (  (! _print_setup->printSeparately()) ||
656                  (_print_data->destination == DtPRINT_TO_FILE )  )
657             );
658
659
660     _print_output->setTopPosition(0);
661     _spool_npages_total = _print_output->getNumLines() +
662                         _print_output->getLinesPerPage() - 1;
663     _spool_npages_total /= _print_output->getLinesPerPage();
664
665     return TRUE;
666 }
667
668 void
669 DmxPrintJob::printOnePageCB(
670                         Widget,
671                         XtPointer client_data,
672                         XtPointer call_data)
673 {
674 #if 0 && defined(PRINTING_SUPPORTED)
675     DmxPrintJob         *thisJob = (DmxPrintJob *) client_data;
676
677     XmPrintShellCallbackStruct  *pscbs = (XmPrintShellCallbackStruct*)call_data;
678     DmxMsg                      *currmsg;
679     int                         top = 0;
680
681     if (thisJob->_print_output == NULL)
682     {
683         
684         XtArgVal /* Dimension */        width, height;
685
686         width = 0; height=0;
687         XtVaGetValues(
688                 thisJob->_pshell,
689                 XmNwidth, &width,
690                 XmNheight, &height,
691                 NULL);
692 #if PRINT_TO_VIDEO
693         printf("PrintShell in PrintOnePageCB: <W %d - H %d>\n", width, height);
694 #endif
695
696         if (width < 100 || height < 100)
697         {
698             width = 2550; height=3250;
699             XtVaSetValues(
700                     thisJob->_pshell,
701                     XmNwidth, width,
702                     XmNheight, height,
703                     NULL);
704             width = 0; height=0;
705             XtVaGetValues(
706                     thisJob->_pshell,
707                     XmNwidth, &width,
708                     XmNheight, &height,
709                     NULL);
710
711 #if PRINT_TO_VIDEO
712             printf("PrintShell in PrintOnePageCB: <W %d - H %d>\n",
713                    width,height);
714 #endif
715         }
716
717         thisJob->createOutputWidgets();
718         if (! thisJob->loadOutputWidgets())
719         {
720             thisJob->cancel();
721             return;
722         }
723     }
724
725 #ifndef PRINT_TO_VIDEO 
726     if (pscbs->last_page)
727 #else
728     if (thisJob->_spool_npages_done == thisJob->_spool_npages_total)
729 #endif
730     {
731         int     dest = XPSpool;
732
733         //
734         // This spool job is done.
735         // Try spooling the next one.
736         //
737         if (! thisJob->loadOutputWidgets())
738         {
739             if (thisJob->_print_data->destination != DtPRINT_TO_FILE)
740               thisJob->cancel();
741             return;
742         }
743
744         //
745         // Register a work proc to print one page at a time
746         //
747 #ifndef PRINT_TO_VIDEO 
748         if (thisJob->_print_data->destination == DtPRINT_TO_FILE)
749           dest = XPGetData;
750
751         XpStartJob(XtDisplay(thisJob->_pshell), dest);
752         XFlush(XtDisplay(thisJob->_pshell));
753
754         if (thisJob->_print_data->destination == DtPRINT_TO_FILE)
755           XmPrintToFile(
756                 XtDisplay(thisJob->_pshell),
757                 thisJob->_print_data->dest_info,
758                 (XPFinishProc) &DmxPrintJob::finishedPrintToFile,
759                 (XPointer) thisJob);
760 #endif
761
762         return;
763     }
764
765     if (thisJob->_spool_npages_done == 0)
766     {
767         thisJob->_print_output->setTopPosition(0);
768     }
769     else if (! thisJob->_print_output->pageDown())
770     {
771 #ifndef PRINT_TO_VIDEO 
772         pscbs->last_page = TRUE;
773 #endif
774         return;
775     }
776     else
777     {
778         int top = thisJob->_print_output->getTopPosition();
779         int currmsg_i = thisJob->_spool_nmsgs_done;
780
781         //
782         // Find the index into the ._spool_msg_info array of the
783         // message which will begin the next page.  This message
784         // will be used to set the header and footer strings.
785         //
786         while (top > thisJob->_spool_msg_info[currmsg_i].end_position &&
787                currmsg_i < thisJob->_spool_nmsgs_total)
788           currmsg_i++;
789
790         assert(top <= thisJob->_spool_msg_info[currmsg_i].end_position);
791         thisJob->_spool_nmsgs_done = currmsg_i;
792     }
793
794     currmsg = thisJob->_spool_msg_info[thisJob->_spool_nmsgs_done].msg;
795     assert(currmsg != (DmxMsg *) NULL);
796     if (currmsg == (DmxMsg *) NULL)
797     {
798 #ifndef PRINT_TO_VIDEO 
799         pscbs->last_page = TRUE;
800 #endif
801         return;
802     }
803
804     //
805     // Update header and footer strings.
806     //
807     thisJob->_spool_npages_done++;
808     thisJob->updatePageHeaders(
809                 currmsg,
810                 DmxPrintOptions::getHdrFtrSpec(DTPRINT_OPTION_HEADER_LEFT),
811                 DmxPrintOptions::getHdrFtrSpec(DTPRINT_OPTION_HEADER_RIGHT),
812                 DmxPrintOptions::getHdrFtrSpec(DTPRINT_OPTION_FOOTER_LEFT),
813                 DmxPrintOptions::getHdrFtrSpec(DTPRINT_OPTION_FOOTER_RIGHT)
814                 );
815
816 #ifndef PRINT_TO_VIDEO 
817     if (thisJob->_spool_npages_done >= thisJob->_spool_npages_total)
818       pscbs->last_page = TRUE;
819 #endif
820 #endif  /* PRINTING_SUPPORTED */
821 }
822
823
824 void
825 DmxPrintJob::updatePageHeaders(
826                                 DmxMsg                  *msg,
827                                 DmxStringTypeEnum       hl_type,
828                                 DmxStringTypeEnum       hr_type,
829                                 DmxStringTypeEnum       fl_type,
830                                 DmxStringTypeEnum       fr_type
831                                 )
832 {
833     char *hl_string,
834          *hr_string,
835          *fl_string,
836          *fr_string;
837
838     if (msg == (DmxMsg *) NULL)
839       return;
840
841     hl_string = getPageHeaderString(msg, hl_type);
842     hr_string = getPageHeaderString(msg, hr_type);
843     fl_string = getPageHeaderString(msg, fl_type);
844     fr_string = getPageHeaderString(msg, fr_type);
845     
846     _print_output->setHdrFtrStrings(
847                                 hl_string,
848                                 hr_string,
849                                 fl_string,
850                                 fr_string);
851     
852     if (DMX_NONE_STRING == hl_type && DMX_NONE_STRING == hr_type)
853       _print_output->hideHeaders();
854     else
855       _print_output->showHeaders();
856
857     if (DMX_NONE_STRING == fl_type && DMX_NONE_STRING == fr_type)
858       _print_output->hideFooters();
859     else
860       _print_output->showFooters();
861
862     free(hl_string);
863     free(hr_string);
864     free(fl_string);
865     free(fr_string);
866 }
867
868 char *
869 DmxPrintJob::getPageHeaderString(
870                                 DmxMsg                  *msg,
871                                 DmxStringTypeEnum       type
872                                    )
873 {
874     char *format,
875          *buf = (char *) NULL;
876
877
878     if (msg == (DmxMsg *) NULL)
879       return NULL;
880
881     switch (type)
882     {
883         case DMX_NONE_STRING:
884             buf = strdup(" ");
885             break;
886         case DMX_CC_HEADER_STRING:
887             {
888                 char    *hdrstr = msg->getMessageHeader(DMXCC);
889
890                 format = GETMSG(DT_catd, 21, 5, "Cc:  %s");
891                 buf = (char *) malloc(strlen(format) + strlen(hdrstr) + 1); 
892                 if (buf != (char *) NULL)
893                   sprintf(buf, format, hdrstr);
894                 
895                 free(hdrstr);
896             }
897             break;
898         case DMX_DATE_HEADER_STRING:
899             {
900                 char    *hdrstr = msg->getMessageHeader(DMXDATE);
901
902                 format = GETMSG(DT_catd, 21, 6, "Date:  %s");
903                 buf = (char *) malloc(strlen(format) + strlen(hdrstr) + 1); 
904                 if (buf != (char *) NULL)
905                   sprintf(buf, format, hdrstr);
906                 
907                 free(hdrstr);
908             }
909             break;
910         case DMX_FROM_HEADER_STRING:
911             {
912                 char    *hdrstr = msg->getMessageHeader(DMXFROM);
913
914                 format = GETMSG(DT_catd, 21, 7, "From:  %s");
915                 buf = (char *) malloc(strlen(format) + strlen(hdrstr) + 1); 
916                 if (buf != (char *) NULL)
917                   sprintf(buf, format, hdrstr);
918                 
919                 free(hdrstr);
920             }
921             break;
922         case DMX_SUBJECT_HEADER_STRING:
923             {
924                 char    *hdrstr = msg->getMessageHeader(DMXSUBJ);
925
926                 format = GETMSG(DT_catd, 21, 8, "Subject:  %s");
927                 buf = (char *) malloc(strlen(format) + strlen(hdrstr) + 1); 
928                 if (buf != (char *) NULL)
929                   sprintf(buf, format, hdrstr);
930                 
931                 free(hdrstr);
932             }
933             break;
934         case DMX_TO_HEADER_STRING:
935             {
936                 char    *hdrstr = msg->getMessageHeader(DMXTO);
937
938                 format = GETMSG(DT_catd, 21, 9, "To:  %s");
939                 buf = (char *) malloc(strlen(format) + strlen(hdrstr) + 1); 
940                 if (buf != (char *) NULL)
941                   sprintf(buf, format, hdrstr);
942                 
943                 free(hdrstr);
944             }
945             break;
946         case DMX_PAGE_NUMBER_STRING:
947             // 
948             // Allocate space for the format and the translated page number.
949             //
950             {
951                 format = GETMSG(DT_catd, 21, 10, "Page %d of %d");
952                 buf = (char *) malloc(strlen(format) + 16); 
953                 if (buf != (char *) NULL)
954                   sprintf(buf, format, _spool_npages_done, _spool_npages_total);
955             }
956             break;
957         case DMX_USER_NAME_STRING:
958             // 
959             // Allocate space for the format and the username.
960             //
961             {
962                 struct passwd   *pw;
963                 
964                 format = GETMSG(DT_catd, 21, 11, "Mail For:  %s");
965                 pw = getpwuid(getuid());
966                 buf = (char *) malloc(strlen(format) + strlen(pw->pw_name) + 1);
967                 if (buf != (char *) NULL)
968                   sprintf(buf, format, pw->pw_name);
969             }
970             break;
971         default:
972             buf = strdup("DEFAULT not impld");
973             break;
974     }
975     return buf;
976 }
977
978 /*
979  * Name: DmxPrintJob::finishedPrintToFile
980  * Description:
981  */
982 #if 0 && defined(PRINTING_SUPPORTED)
983 void
984 DmxPrintJob::finishedPrintToFile(
985                         Display         *display,
986                         XPContext,
987                         XPGetDocStatus  status,
988                         XPointer        client_data)
989
990 {
991     DmxPrintJob *thisJob = (DmxPrintJob*) client_data;
992     Widget      w = (Widget) thisJob->_parent->baseWidget();
993     char        *message = NULL;
994
995     if (status != XPGetDocFinished)
996     {
997         DtMailGenDialog *genDialog = new DtMailGenDialog("Dialog", w);
998
999         message = (char *) GETMSG(
1000                                 DT_catd, 21, 14,
1001                                 "'Print to File'  was unsuccessful.");
1002         genDialog->setToErrorDialog(
1003                             GETMSG(DT_catd, 21, 3, "Mailer"),
1004                             message);
1005         genDialog->post_and_return(
1006                             GETMSG(DT_catd, 21, 4, "OK"),
1007                             NULL);
1008         delete genDialog;
1009     }
1010     else if (display != theRoamApp.getErrorPrintDisplay())
1011     {
1012         DtMailGenDialog *genDialog = new DtMailGenDialog("Dialog", w);
1013
1014         message = (char *) GETMSG(
1015                                 DT_catd, 21, 15,
1016                                 "'Print to File' completed successfully");
1017
1018         genDialog->setToWarningDialog(
1019                             GETMSG(DT_catd, 21, 3, "Mailer"),
1020                             message);
1021         genDialog->post_and_return(
1022                             GETMSG(DT_catd, 21, 4, "OK"),
1023                             NULL);
1024         delete genDialog;
1025     }
1026     thisJob->cancel();
1027 }
1028 #endif /* PRINTING_SUPPORTED */
1029
1030 /*
1031  * Name: DmxPrintJob::cancelCB
1032  * Description:
1033  *      An XtCallbackProc which can be added to the callback list of
1034  *      a widget to cancel the print job passed back as client_data.
1035  */
1036 void
1037 DmxPrintJob::cancelCB (Widget, XtPointer client_data, XtPointer)
1038 {
1039     DmxPrintJob *thisJob = (DmxPrintJob *) client_data;
1040
1041     thisJob->cancel();
1042 }
1043
1044 /*
1045  * Name: DmxPrintJob::closeDisplayCB
1046  * Description:
1047  *      An XtCallbackProc which can be added to the callback list of
1048  *      a widget to react to the print setup closing the display.
1049  */
1050 void
1051 DmxPrintJob::closeDisplayCB (Widget, XtPointer client_data, XtPointer call_data)
1052 {
1053     DmxPrintJob *thisJob = (DmxPrintJob *) client_data;
1054     DtPrintSetupCallbackStruct *pbs = (DtPrintSetupCallbackStruct *) call_data;
1055
1056     if (thisJob->_pshell != NULL)
1057     {
1058         XtDestroyWidget(thisJob->_pshell);
1059         thisJob->_pshell = NULL;
1060     }
1061     DtPrintFreeSetupData(thisJob->_print_data);
1062 }
1063
1064 /*
1065  * Name: DmxPrintJob::pdmNotificationCB
1066  * Description:
1067  *       XmNpdmNotificationCallback for the XmPrintShell
1068  */
1069 void
1070 DmxPrintJob::pdmNotificationCB(
1071                         Widget,
1072                         XtPointer client_data,
1073                         XtPointer call_data)
1074 {
1075 #if 0 && defined(PRINTING_SUPPORTED)
1076     DmxPrintJob                 *thisJob = (DmxPrintJob *) client_data;
1077     XmPrintShellCallbackStruct  *pscbs = (XmPrintShellCallbackStruct*)call_data;
1078     char                        *message = NULL;
1079
1080     switch (pscbs->reason)
1081     {
1082     
1083         case XmCR_PDM_NONE:
1084         case XmCR_PDM_START_ERROR:
1085         case XmCR_PDM_START_VXAUTH:
1086         case XmCR_PDM_START_PXAUTH:
1087             message = (char *) GETMSG(
1088                         DT_catd, 21, 24,
1089                         "Print Dialog Manager error - setup failed.");
1090             break;
1091         default:
1092             message = NULL;
1093             break;
1094     }
1095
1096     if (message != NULL)
1097     {
1098         DtMailGenDialog *genDialog = new DtMailGenDialog(
1099                                                 "Dialog",
1100                                                 thisJob->_parent->baseWidget());
1101         genDialog->setToErrorDialog(
1102                             GETMSG(DT_catd, 21, 3, "Mailer"),
1103                             message);
1104         genDialog->post_and_return(
1105                             GETMSG(DT_catd, 21, 25, "Continue"),
1106                             NULL);
1107         delete genDialog;
1108     }
1109 #endif  /* PRINTING_SUPPORTED */
1110 }
1111
1112 /*
1113  * Name: DmxPrintJob::pdmSetupCB
1114  * Description:
1115  *      An XtCallbackProc which can be added to the callback list of
1116  *      a widget to execute the print job passed back as client_data.
1117  */
1118 void
1119 DmxPrintJob::pdmSetupCB(
1120                 Widget print_setup,
1121                 XtPointer client_data,
1122                 XtPointer call_data)
1123 {
1124 #if 0 && defined(PRINTING_SUPPORTED)
1125     DmxPrintJob *thisJob = (DmxPrintJob *) client_data;
1126     DtPrintSetupCallbackStruct *pbs = (DtPrintSetupCallbackStruct *) call_data;
1127
1128     DtPrintCopySetupData(thisJob->_print_data, pbs->print_data);
1129     thisJob->createPrintShell();
1130
1131     if (thisJob->_pshell)
1132     {
1133         Widget  shell = print_setup;
1134
1135         while (! (shell == NULL || XtIsShell(shell)) )
1136           shell = XtParent(shell);
1137
1138         if (shell)
1139           XmPrintPopupPDM(thisJob->_pshell, shell);
1140         else
1141           fprintf(stderr, "Internal Error:  Missing XmPrintShell\n");
1142     }
1143 #endif  /* PRINTING_SUPPORTED */
1144 }
1145
1146 /*
1147  * Name: DmxPrintJob::printCB
1148  * Description:
1149  *      An XtCallbackProc which can be added to the callback list of
1150  *      a widget to execute the print job passed back as client_data.
1151  */
1152 void
1153 DmxPrintJob::printCB (Widget, XtPointer client_data, XtPointer call_data)
1154 {
1155     DmxPrintJob *thisJob = (DmxPrintJob *) client_data;
1156     DtPrintSetupCallbackStruct *pbs = (DtPrintSetupCallbackStruct *) call_data;
1157
1158     /* TBD: Save options??? */
1159
1160     DtPrintCopySetupData(thisJob->_print_data, pbs->print_data);
1161     thisJob->createPrintShell();
1162     thisJob->doPrint();
1163 }