Initial import of the CDE 2.1.30 sources from the Open Group.
[oweals/cde.git] / cde / programs / dtmail / dtmail / DmxPrintOutput.C
1 /* $TOG: DmxPrintOutput.C /main/6 1997/07/07 13:57:21 mgreess $ */
2
3 /*
4  *+SNOTICE
5  *
6  *      $:$
7  *
8  *      RESTRICTED CONFIDENTIAL INFORMATION:
9  *      
10  *      The information in this document is subject to special
11  *      restrictions in a confidential disclosure agreement between
12  *      HP, IBM, Sun, USL, SCO and Univel.  Do not distribute this
13  *      document outside HP, IBM, Sun, USL, SCO, or Univel without
14  *      Sun's specific written approval.  This document and all copies
15  *      and derivative works thereof must be returned or destroyed at
16  *      Sun's request.
17  *
18  *      Copyright 1994 Sun Microsystems, Inc.  All rights reserved.
19  *
20  *+ENOTICE
21  */
22 /*
23  *                   Common Desktop Environment
24  *
25  *   (c) Copyright 1993, 1994, 1995 Hewlett-Packard Company
26  *   (c) Copyright 1993, 1994, 1995 International Business Machines Corp.
27  *   (c) Copyright 1993, 1994, 1995 Sun Microsystems, Inc.
28  *   (c) Copyright 1993, 1994, 1995 Novell, Inc.
29  *   (c) Copyright 1995 Digital Equipment Corp.
30  *   (c) Copyright 1995 Fujitsu Limited
31  *   (c) Copyright 1995 Hitachi, Ltd.
32  *                                                                   
33  *
34  *                     RESTRICTED RIGHTS LEGEND                              
35  *
36  *Use, duplication, or disclosure by the U.S. Government is subject to
37  *restrictions as set forth in subparagraph (c)(1)(ii) of the Rights in
38  *Technical Data and Computer Software clause in DFARS 252.227-7013.  Rights
39  *for non-DOD U.S. Government Departments and Agencies are as set forth in
40  *FAR 52.227-19(c)(1,2).
41
42  *Hewlett-Packard Company, 3000 Hanover Street, Palo Alto, CA 94304 U.S.A.
43  *International Business Machines Corp., Route 100, Somers, NY 10589 U.S.A. 
44  *Sun Microsystems, Inc., 2550 Garcia Avenue, Mountain View, CA 94043 U.S.A.
45  *Novell, Inc., 190 River Road, Summit, NJ 07901 U.S.A.
46  *Digital Equipment Corp., 111 Powdermill Road, Maynard, MA 01754, U.S.A.
47  *Fujitsu Limited, 1015, Kamikodanaka Nakahara-Ku, Kawasaki 211, Japan
48  *Hitachi, Ltd., 6, Kanda Surugadai 4-Chome, Chiyoda-ku, Tokyo 101, Japan
49  */
50
51
52 #include <stdio.h>
53 #include <X11/Intrinsic.h>
54 #include <Xm/Xm.h>
55 #include <Xm/DialogS.h>
56 #include <Xm/Form.h>
57 #include <Xm/Label.h>
58 #include <Xm/Print.h>
59 #include <Xm/Text.h>
60 #include <Dt/Editor.h>
61
62 #include "Dmx.h"
63 #include "DmxPrintOutput.h"
64 #include "RoamMenuWindow.h"
65
66 //
67 // Used to initialize the top, right, bottom, and left margins
68 // between the outside edge of the page (_form) and the inner
69 // page that is written on.
70 //
71 const char *const DmxPrintOutput::_default_margin = ".5in";
72
73 DmxPrintOutput::DmxPrintOutput (
74                                 Widget pshell
75                                 ) : UIComponent( "PrintOutput" )
76 {
77     Widget              w;
78     DtMailBoolean       parse_error;
79
80     _w = NULL;
81     _pshell = pshell;
82
83     w = XtVaCreateWidget("Page",
84                         xmFormWidgetClass,
85                         _pshell,
86                         XmNresizePolicy, XmRESIZE_NONE,
87                         NULL);
88     _form = w;
89     _w = _form;
90                  
91     w = XtVaCreateWidget("InnerPage",
92                         xmFormWidgetClass,
93                         _form,
94                         XmNresizePolicy, XmRESIZE_NONE,
95                         NULL);
96     _inner_form = w;
97                  
98     w = XtVaCreateManagedWidget("HeaderLeft",
99                                   xmLabelWidgetClass,
100                                   _inner_form,
101                                   XmNalignment, XmALIGNMENT_BEGINNING,
102                                   XmNleftAttachment, XmATTACH_FORM,
103                                   XmNtopAttachment, XmATTACH_FORM,
104                                   NULL);
105     _header_left = w;
106
107     w = XtVaCreateManagedWidget("HeaderRight",
108                                   xmLabelWidgetClass,
109                                   _inner_form,
110                                   XmNalignment, XmALIGNMENT_END,
111                                   XmNrightAttachment, XmATTACH_FORM,
112                                   XmNleftAttachment, XmATTACH_WIDGET,
113                                   XmNleftWidget, _header_left,
114                                   XmNtopAttachment, XmATTACH_FORM,
115                                   NULL);
116     _header_right = w;
117                  
118     w = XtVaCreateManagedWidget("Editor",
119 #ifdef USE_DTEDITOR
120                                   dtEditorWidgetClass,
121 #else
122                                   xmTextWidgetClass,
123 #endif
124                                   _inner_form,
125                                   DtNscrollVertical, FALSE,
126                                   DtNscrollHorizontal, FALSE,
127                                   DtNshowStatusLine, FALSE,
128                                   DtNwordWrap, TRUE,
129                                   XmNeditMode, XmMULTI_LINE_EDIT,
130                                   XmNleftAttachment, XmATTACH_FORM,
131                                   XmNrightAttachment, XmATTACH_FORM,
132                                   XmNtopAttachment, XmATTACH_WIDGET,
133                                   XmNtopWidget, _header_left,
134                                   NULL);
135     _editor = w;
136                  
137     w = XtVaCreateManagedWidget("FooterLeft",
138                                   xmLabelWidgetClass,
139                                   _inner_form,
140                                   XmNalignment, XmALIGNMENT_BEGINNING,
141                                   XmNleftAttachment, XmATTACH_FORM,
142                                   XmNbottomAttachment, XmATTACH_FORM,
143                                   NULL);
144     _footer_left = w;
145
146     w = XtVaCreateManagedWidget("FooterRight",
147                                   xmLabelWidgetClass,
148                                   _inner_form,
149                                   XmNalignment, XmALIGNMENT_END,
150                                   XmNleftAttachment, XmATTACH_WIDGET,
151                                   XmNleftWidget, _footer_left,
152                                   XmNrightAttachment, XmATTACH_FORM,
153                                   XmNbottomAttachment, XmATTACH_FORM,
154                                   NULL);
155     _footer_right = w;
156
157     XtVaSetValues(
158                 _editor,
159                 XmNbottomAttachment, XmATTACH_WIDGET,
160                 XmNbottomWidget, _footer_left,
161                 NULL);
162
163     installDestroyHandler();
164     XtManageChild(_inner_form);
165     XtManageChild(_form);
166
167     setPageMargins(
168                 _default_margin,
169                 _default_margin,
170                 _default_margin,
171                 _default_margin,
172                 &parse_error );
173     assert(!parse_error);
174 }
175
176 DmxPrintOutput::~DmxPrintOutput (void)
177 {
178     //
179     //  Don't destroy anything here.
180     //  The BasicComponent class takes care of destroying
181     //  the _form widget.
182     //
183 }
184
185 void DmxPrintOutput::hideFooters (void)
186 {
187     XtUnmanageChild(_footer_left);
188     XtUnmanageChild(_footer_right);
189     XtVaSetValues(_editor, XmNbottomAttachment, XmATTACH_FORM, NULL);
190 }
191
192 void DmxPrintOutput::showFooters (void)
193 {
194     XtManageChild(_footer_left);
195     XtManageChild(_footer_right);
196     XtVaSetValues(
197                 _editor,
198                 XmNbottomAttachment, XmATTACH_WIDGET,
199                 XmNbottomWidget, _footer_left,
200                 NULL);
201 }
202
203 void DmxPrintOutput::hideHeaders (void)
204 {
205     XtUnmanageChild(_header_left);
206     XtUnmanageChild(_header_right);
207     XtVaSetValues(_editor, XmNtopAttachment, XmATTACH_FORM, NULL);
208 }
209
210 void DmxPrintOutput::showHeaders (void)
211 {
212     XtManageChild(_header_left);
213     XtManageChild(_header_right);
214     XtVaSetValues(
215                 _editor,
216                 XmNtopAttachment, XmATTACH_WIDGET,
217                 XmNtopWidget, _header_left,
218                 NULL);
219 }
220
221
222 void
223 DmxPrintOutput::setHdrFtrString (_DtPrintHdrFtrEnum which, char *label)
224 {
225     Widget      w;
226     XmString    xms;
227
228     if (label == (char *) NULL)
229       return;
230
231     switch (which)
232     {
233         case DTPRINT_OPTION_HEADER_LEFT:
234           w = _header_left;
235           break;
236         case DTPRINT_OPTION_HEADER_RIGHT:
237           w = _header_right;
238           break;
239         case DTPRINT_OPTION_FOOTER_LEFT:
240           w = _footer_left;
241           break;
242         case DTPRINT_OPTION_FOOTER_RIGHT:
243           w = _footer_right;
244           break;
245         default:
246           // TBD:  Need to log an error.
247           return;
248     }
249
250     xms = XmStringCreateLocalized(label);
251     XtVaSetValues(w, XmNlabelString, xms, NULL);
252     XmStringFree(xms);
253 }
254
255 void
256 DmxPrintOutput::setHdrFtrStrings (
257                                 char *hdr_left,
258                                 char *hdr_right,
259                                 char *ftr_left,
260                                 char *ftr_right
261                                    )
262 {
263     XmString    xms;
264
265     if (hdr_left)
266     {
267         xms = XmStringCreateLocalized(hdr_left);
268         XtVaSetValues(_header_left, XmNlabelString, xms, NULL);
269         XmStringFree(xms);
270     }
271
272     if (hdr_right)
273     {
274         xms = XmStringCreateLocalized(hdr_right);
275         XtVaSetValues(_header_right, XmNlabelString, xms, NULL);
276         XmStringFree(xms);
277     }
278
279     if (ftr_left)
280     {
281         xms = XmStringCreateLocalized(ftr_left);
282         XtVaSetValues(_footer_left, XmNlabelString, xms, NULL);
283         XmStringFree(xms);
284     }
285
286     if (ftr_right)
287     {
288         xms = XmStringCreateLocalized(ftr_right);
289         XtVaSetValues(_footer_right, XmNlabelString, xms, NULL);
290         XmStringFree(xms);
291     }
292 }
293
294 void
295 DmxPrintOutput::setPageMargin (
296                                 _DtPrintMarginEnum which,
297                                 const char *margin,
298                                 DtMailBoolean *parse_error
299                                 )
300 {
301     int         pixels = 0;
302     XtEnum      xt_parse_error = FALSE;
303     char        *marginstring = strdup(margin);
304
305     if (parse_error)
306       *parse_error = DTM_FALSE;
307
308     switch (which)
309     {
310         case DTPRINT_OPTION_MARGIN_TOP:
311           pixels = XmConvertStringToUnits(
312                                         XtScreenOfObject(_pshell),
313                                         marginstring,
314                                         XmVERTICAL,
315                                         XmPIXELS,
316                                         &xt_parse_error);
317           if (!xt_parse_error && pixels > 0)
318             _margin_top = pixels;
319           break;
320         case DTPRINT_OPTION_MARGIN_RIGHT:
321           pixels = XmConvertStringToUnits(
322                                         XtScreenOfObject(_pshell),
323                                         marginstring,
324                                         XmHORIZONTAL,
325                                         XmPIXELS,
326                                         &xt_parse_error);
327           if (!xt_parse_error && pixels > 0)
328             _margin_right = pixels;
329           break;
330         case DTPRINT_OPTION_MARGIN_BOTTOM:
331           _margin_bottom = pixels;
332           pixels = XmConvertStringToUnits(
333                                         XtScreenOfObject(_pshell),
334                                         marginstring,
335                                         XmVERTICAL,
336                                         XmPIXELS,
337                                         &xt_parse_error);
338           if (!xt_parse_error && pixels > 0)
339             _margin_bottom = pixels;
340           break;
341         case DTPRINT_OPTION_MARGIN_LEFT:
342           pixels = XmConvertStringToUnits(
343                                         XtScreenOfObject(_pshell),
344                                         marginstring,
345                                         XmHORIZONTAL,
346                                         XmPIXELS,
347                                         &xt_parse_error);
348           if (!xt_parse_error && pixels > 0)
349             _margin_left = pixels;
350           break;
351         default:
352           // TBD:  Need to log an error.
353           return;
354     }
355
356     if (!xt_parse_error)
357       setInnerPageDimensions(
358                         _margin_top,
359                         _margin_right,
360                         _margin_bottom,
361                         _margin_left);
362     else
363       *parse_error = DTM_TRUE;
364
365     free(marginstring);
366 }
367
368 void
369 DmxPrintOutput::setPageMargin (_DtPrintMarginEnum which, int margin)
370 {
371     Dimension   pixels = (Dimension) margin;
372
373     switch (which)
374     {
375         case DTPRINT_OPTION_MARGIN_TOP:
376           _margin_top = pixels;
377           break;
378         case DTPRINT_OPTION_MARGIN_RIGHT:
379           _margin_right = pixels;
380           break;
381         case DTPRINT_OPTION_MARGIN_BOTTOM:
382           _margin_bottom = pixels;
383           break;
384         case DTPRINT_OPTION_MARGIN_LEFT:
385           _margin_left = pixels;
386           break;
387         default:
388           // TBD:  Need to log an error.
389           return;
390     }
391
392     setInnerPageDimensions(
393                         _margin_top,
394                         _margin_right,
395                         _margin_bottom,
396                         _margin_left);
397 }
398
399 void
400 DmxPrintOutput::setPageMargins (
401                                 const char *top,
402                                 const char *right,
403                                 const char *bottom,
404                                 const char *left,
405                                 DtMailBoolean *parse_error
406                                  )
407 {
408     int         pixels = 0;
409     XtEnum      xt_parse_error = FALSE;
410     char        *margin;
411
412     *parse_error = DTM_FALSE;
413
414     margin = strdup(top);
415     pixels = XmConvertStringToUnits(
416                                 XtScreenOfObject(_pshell),
417                                 margin,
418                                 XmVERTICAL,
419                                 XmPIXELS,
420                                 &xt_parse_error);
421     free(margin);
422     if (!xt_parse_error && pixels > 0)
423     {
424         _margin_top = pixels;
425     }
426     else
427     {    
428         *parse_error = DTM_TRUE;
429         return;
430     }
431
432     margin = strdup(right);
433     pixels = XmConvertStringToUnits(
434                                 XtScreenOfObject(_pshell),
435                                 margin,
436                                 XmHORIZONTAL,
437                                 XmPIXELS,
438                                 &xt_parse_error);
439     free(margin);
440     if (!xt_parse_error && pixels > 0)
441     {
442         _margin_right = pixels;
443     }
444     else
445     {    
446         *parse_error = DTM_TRUE;
447         return;
448     }
449
450     margin = strdup(bottom);
451     pixels = XmConvertStringToUnits(
452                                 XtScreenOfObject(_pshell),
453                                 margin,
454                                 XmVERTICAL,
455                                 XmPIXELS,
456                                 &xt_parse_error);
457     free(margin);
458     if (!xt_parse_error && pixels > 0)
459     {
460         _margin_bottom = pixels;
461     }
462     else
463     {    
464         *parse_error = DTM_TRUE;
465         return;
466     }
467
468     margin = strdup(left);
469     pixels = XmConvertStringToUnits(
470                                 XtScreenOfObject(_pshell),
471                                 margin,
472                                 XmHORIZONTAL,
473                                 XmPIXELS,
474                                 &xt_parse_error);
475     free(margin);
476     if (!xt_parse_error && pixels > 0)
477     {
478         _margin_left = pixels;
479     }
480     else
481     {    
482         *parse_error = DTM_TRUE;
483         return;
484     }
485
486     setInnerPageDimensions(
487                         _margin_top,
488                         _margin_right,
489                         _margin_bottom,
490                         _margin_left);
491 }
492
493 void
494 DmxPrintOutput::setPageMargins (
495                                 int top,
496                                 int right,
497                                 int bottom,
498                                 int left
499                                  )
500 {
501     _margin_top = (top > 0) ? (Dimension) top : _margin_top;
502     _margin_right = (right > 0) ? (Dimension) right : _margin_right;
503     _margin_bottom = (bottom > 0) ? (Dimension) bottom : _margin_bottom;
504     _margin_left = (left > 0) ? (Dimension) left : _margin_left;
505
506     setInnerPageDimensions(
507                         _margin_top,
508                         _margin_right,
509                         _margin_bottom,
510                         _margin_left);
511 }
512
513 void
514 DmxPrintOutput::setWrapToFit (DtMailBoolean onoff)
515 {
516 #ifdef USE_DTEDITOR
517     XtVaSetValues(_editor, DtNwordWrap, onoff, NULL);
518 #else
519     XtVaSetValues(_editor, XmNwordWrap, onoff, NULL);
520 #endif
521 }
522
523
524
525 int DmxPrintOutput::getCharactersPerLine ()
526 {
527     short       columns = 0;
528
529 #ifdef USE_DTEDITOR
530     XtVaGetValues(_editor, DtNcolumns, &columns, NULL);
531 #else
532     XtVaGetValues(_editor, XmNcolumns, &columns, NULL);
533 #endif
534     return((int) columns);
535 }
536
537
538
539 int DmxPrintOutput::getNumLines ()
540 {
541     int total = 0;
542
543 #ifdef USE_DTEDITOR
544 #else
545     XtVaGetValues(_editor, XmNtotalLines, &total, NULL);
546     //
547     // Correct for off by one error.
548     //
549     total -= 1;
550 #endif
551     return(total);
552 }
553
554
555 int DmxPrintOutput::getLastPosition ()
556 {
557     XmTextPosition last;
558
559 #ifdef USE_DTEDITOR
560     last = DtEditorGetLastPosition(_editor);
561 #else
562     last = XmTextGetLastPosition(_editor);
563 #endif
564     return((int) last);
565 }
566
567 int DmxPrintOutput::getTopPosition ()
568 {
569     XmTextPosition top;
570
571 #ifdef USE_DTEDITOR
572     XtVaGetValues(_editor, DtNtopCharacter, &top, NULL);
573 #else
574     top = XmTextGetTopCharacter(_editor);
575 #endif
576     return((int) top);
577 }
578
579 DtMailBoolean DmxPrintOutput::pageUp ()
580 {
581     XmTextPosition top_before, top_after;
582
583 #ifdef USE_DTEDITOR
584     return DTM_FALSE;
585 #else
586     top_before = XmTextGetTopCharacter(_editor);
587     XmTextScroll(_editor, -1 * _lines_per_page);
588     top_after = XmTextGetTopCharacter(_editor);
589
590     return (top_before > top_after) ? DTM_TRUE : DTM_FALSE;
591 #endif
592 }
593
594 DtMailBoolean DmxPrintOutput::pageDown ()
595 {
596     XmTextPosition top_before, top_after;
597
598 #ifdef USE_DTEDITOR
599     return DTM_FALSE;
600 #else
601     top_before = XmTextGetTopCharacter(_editor);
602     XmTextScroll(_editor, _lines_per_page);
603     top_after = XmTextGetTopCharacter(_editor);
604
605     return (top_before < top_after) ? DTM_TRUE : DTM_FALSE;
606 #endif
607 }
608
609 void DmxPrintOutput::setTopPosition ( int pos )
610 {
611     XmTextPosition top = (XmTextPosition) pos;
612
613 #ifdef USE_DTEDITOR
614     XtVaSetValues(_editor, DtNtopCharacter, top, NULL);
615 #else
616     XmTextSetTopCharacter(_editor, top);
617 #endif
618 }
619
620 void DmxPrintOutput::appendContents (void* stream, char *contents)
621 {
622     DmxPrintOutput      *thisOutput = (DmxPrintOutput *) stream;
623
624 #ifdef USE_DTEDITOR
625     DtEditorContentRec  rec;
626
627     rec.type = DtEDITOR_TEXT;
628     rec.value.string = contents;
629     DtEditorInsert(thisOutput->_editor, &rec);
630 #else
631     XmTextPosition pos;
632
633     pos = XmTextGetLastPosition(thisOutput->_editor);
634     XmTextInsert(thisOutput->_editor, pos, contents);
635 #endif
636 }
637
638 void DmxPrintOutput::appendNewLine ()
639 {
640 #ifdef PRINT_TO_VIDEO 
641     char        *contents = "=========== NewLine ==========\n";
642 #else
643     char        *contents = "\n";
644 #endif
645     appendContents((XtPointer) this, contents);
646 }
647
648 void DmxPrintOutput::appendPageBreak ()
649 {
650     char *      buf;
651     char        *contents = "\n";
652     int         nlines, missing;
653
654     nlines = getNumLines();
655     missing = ((nlines % _lines_per_page) > 0) ?
656                 (_lines_per_page - (nlines % _lines_per_page)) :
657                 0;
658
659     if (! missing)
660       return;
661     
662 #ifdef PRINT_TO_VIDEO 
663     for (int i=0; i<missing; i++)
664     {
665         char    buffer[128];
666
667         sprintf(buffer, "Page Break Line:  %d\n", i);
668         appendContents((XtPointer) this, buffer);
669     }
670     fprintf(
671         stdout,
672         "Total Lines:  %d;  Lines Per Page:  %d;  Missing Lines:  %d\n",
673         nlines,
674         _lines_per_page,
675         missing);
676 #else
677     buf = (char *) malloc((missing * 2) + 1);
678     for (int i=0; i<missing; i++)
679       strcat(buf, contents);
680
681     appendContents(this, contents);
682
683     free(buf);
684 #endif
685 }
686
687 void DmxPrintOutput::clearContents (void)
688 {
689 #ifdef USE_DTEDITOR
690     DtEditorContentRec  content;
691
692     content.type = DtEDITOR_TEXT;
693     rec.value.string = NULL;
694     status = DtEditorSetContents(my_text, &content);
695 #else
696     XmTextSetString(_editor, "");
697 #endif
698 }
699
700
701 /*
702  * Private class methods
703  */
704 int
705 DmxPrintOutput::doGetLinesPerPage ()
706 {
707     Dimension   lpp;
708
709     XtVaGetValues(_editor, XmNrows, &lpp, NULL);
710     return ((int) lpp);
711 }
712
713
714 void
715 DmxPrintOutput::setInnerPageDimensions (
716                                         Dimension top,
717                                         Dimension right,
718                                         Dimension bottom,
719                                         Dimension left
720                                            )
721 {
722     Dimension   inner_height, inner_width, inner_x, inner_y,
723                 outer_height, outer_width,
724                 editor_height, footer_height, header_height;
725
726     XtVaGetValues(_form,
727                   XmNheight, &outer_height,
728                   XmNwidth, &outer_width,
729                   NULL);
730
731     XtVaGetValues(_header_left,
732                   XmNheight, &header_height,
733                   NULL);
734
735     XtVaGetValues(_footer_left,
736                   XmNheight, &footer_height,
737                   NULL);
738
739     inner_x = left;
740     inner_y = top;
741     inner_height = ((int) outer_height > (top + bottom)) ?
742                         (outer_height - (top +  bottom)) :
743                         outer_height;
744     inner_width = ((int) outer_width > (left + right)) ?
745                         (outer_width - (left + right)) :
746                         outer_width;
747     editor_height = ((int) inner_height > (header_height + footer_height)) ?
748                         (inner_height - (header_height + footer_height)) :
749                         inner_height;
750     
751     XtVaSetValues(_editor, XmNheight, editor_height, NULL);
752
753     XtVaSetValues(_inner_form,
754                 XmNleftAttachment, XmATTACH_NONE,
755                 XmNtopAttachment, XmATTACH_NONE,
756                 XmNx, inner_x,
757                 XmNy, inner_y,
758                 XmNheight, inner_height,
759                 XmNwidth, inner_width,
760                 NULL);
761
762     _lines_per_page = doGetLinesPerPage();
763 }