dtcm: Resolve CID 87713
[oweals/cde.git] / cde / programs / dtpad / printOutput.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: printOutput.c /main/6 1997/07/07 15:06:25 mgreess $ */
24 /**********************************<+>*************************************
25 ***************************************************************************
26 **
27 **  File:        printOption.c
28 **
29 **  Project:     HP DT dtpad, a memo maker type editor based on the
30 **               Dt Editor widget.
31 **
32 **  Description:  Routines which manipulate the print setup dialog
33 **
34 **************************************************************************
35 **********************************<+>*************************************/
36 /*
37  *                   Common Desktop Environment
38  *
39  *   (c) Copyright 1993, 1994, 1995 Hewlett-Packard Company
40  *   (c) Copyright 1993, 1994, 1995 International Business Machines Corp.
41  *   (c) Copyright 1993, 1994, 1995 Sun Microsystems, Inc.
42  *   (c) Copyright 1993, 1994, 1995 Novell, Inc.
43  *   (c) Copyright 1995 Digital Equipment Corp.
44  *   (c) Copyright 1995 Fujitsu Limited
45  *   (c) Copyright 1995 Hitachi, Ltd.
46  *
47  *
48  *                     RESTRICTED RIGHTS LEGEND
49  *
50  *Use, duplication, or disclosure by the U.S. Government is subject to
51  *restrictions as set forth in subparagraph (c)(1)(ii) of the Rights in
52  *Technical Data and Computer Software clause in DFARS 252.227-7013.  Rights
53  *for non-DOD U.S. Government Departments and Agencies are as set forth in
54  *FAR 52.227-19(c)(1,2).
55
56  *Hewlett-Packard Company, 3000 Hanover Street, Palo Alto, CA 94304 U.S.A.
57  *International Business Machines Corp., Route 100, Somers, NY 10589 U.S.A.
58  *Sun Microsystems, Inc., 2550 Garcia Avenue, Mountain View, CA 94043 U.S.A.
59  *Novell, Inc., 190 River Road, Summit, NJ 07901 U.S.A.
60  *Digital Equipment Corp., 111 Powdermill Road, Maynard, MA 01754, U.S.A.
61  *Fujitsu Limited, 1015, Kamikodanaka Nakahara-Ku, Kawasaki 211, Japan
62  *Hitachi, Ltd., 6, Kanda Surugadai 4-Chome, Chiyoda-ku, Tokyo 101, Japan
63  */
64
65
66 #include <stdio.h>
67 #include <string.h>
68 #include <assert.h>
69
70 #include <X11/Intrinsic.h>
71 #include <Xm/Xm.h>
72 #include <Xm/DialogS.h>
73 #include <Xm/Form.h>
74 #include <Xm/Label.h>
75 #include <Xm/Print.h>
76 #include <Xm/Text.h>
77 #include <Dt/Editor.h>
78
79 #include "dtpad.h"
80
81 #define READ_ACCESS     1
82 #define WRITE_ACCESS    2
83
84 static void     _poSetInnerPageDimensions(
85                                 PrintOutput*,
86                                 Dimension,
87                                 Dimension,
88                                 Dimension,
89                                 Dimension
90                                 );
91 static int      _poDoGetLinesPerPage(PrintOutput*);
92 static int      _poGetTopPosition(PrintOutput *pOutput);
93 static DtEditorErrorCode
94                 _poGetFileContents(char **contents, char *file);
95 static DtEditorErrorCode 
96                 _poStripEmbeddedNulls(char *strbuf, int *len);
97 extern DtEditorErrorCode
98                 _poEditorValidateFileAccess(char *file, int accessType);
99
100 /*
101  * Used to initialize the top, right, bottom, and left margins
102  * between the outside edge of the page (_form) and the inner
103  * page that is written on.
104  */
105 const char *const _poDefaultMargin = ".5in";
106
107 /************************************************************************
108  * PrintOutputCreate
109  *      Creates and initialiazes a new PrintOutput output including the
110  *      widget hierarchy.
111  ************************************************************************/
112 PrintOutput*
113 PrintOutputCreate(Widget shell)
114 {
115     Widget              w;
116     Boolean             parseError;
117     PrintOutput         *pOutput;
118
119     pOutput = (PrintOutput *) XtMalloc(sizeof(PrintOutput));
120     pOutput->pShell = shell;
121
122     pOutput->currentLine = 0;
123     pOutput->linesPerPage = 0;
124
125     w = XtVaCreateWidget("Page",
126                           xmFormWidgetClass,
127                           pOutput->pShell,
128                           XmNresizePolicy, XmRESIZE_NONE,
129                           NULL);
130     pOutput->page = w;
131                  
132     w = XtVaCreateWidget("InnerPage",
133                           xmFormWidgetClass,
134                           pOutput->page,
135                           XmNresizePolicy, XmRESIZE_NONE,
136                           NULL);
137     pOutput->innerPage = w;
138                  
139     w = XtVaCreateManagedWidget("HeaderLeft",
140                                   xmLabelWidgetClass,
141                                   pOutput->innerPage,
142                                   XmNalignment, XmALIGNMENT_BEGINNING,
143                                   XmNleftAttachment, XmATTACH_FORM,
144                                   XmNtopAttachment, XmATTACH_FORM,
145                                   NULL);
146     pOutput->headerLeft = w;
147
148     w = XtVaCreateManagedWidget("HeaderRight",
149                                   xmLabelWidgetClass,
150                                   pOutput->innerPage,
151                                   XmNalignment, XmALIGNMENT_END,
152                                   XmNrightAttachment, XmATTACH_FORM,
153                                   XmNleftAttachment, XmATTACH_WIDGET,
154                                   XmNleftWidget, pOutput->headerLeft,
155                                   XmNtopAttachment, XmATTACH_FORM,
156                                   NULL);
157     pOutput->headerRight = w;
158                  
159     w = XtVaCreateManagedWidget("Editor",
160 #ifdef USE_DTEDITOR
161                                   dtEditorWidgetClass,
162 #else
163                                   xmTextWidgetClass,
164 #endif
165                                   pOutput->innerPage,
166                                   DtNscrollVertical, FALSE,
167                                   DtNscrollHorizontal, FALSE,
168                                   DtNshowStatusLine, FALSE,
169                                   DtNwordWrap, TRUE,
170                                   XmNeditMode, XmMULTI_LINE_EDIT,
171                                   XmNleftAttachment, XmATTACH_FORM,
172                                   XmNrightAttachment, XmATTACH_FORM,
173                                   XmNtopAttachment, XmATTACH_WIDGET,
174                                   XmNtopWidget, pOutput->headerLeft,
175                                   NULL);
176     pOutput->editor = w;
177                  
178     w = XtVaCreateManagedWidget("FooterLeft",
179                                   xmLabelWidgetClass,
180                                   pOutput->innerPage,
181                                   XmNalignment, XmALIGNMENT_BEGINNING,
182                                   XmNleftAttachment, XmATTACH_FORM,
183                                   XmNbottomAttachment, XmATTACH_FORM,
184                                   NULL);
185     pOutput->footerLeft = w;
186
187     w = XtVaCreateManagedWidget("FooterRight",
188                                   xmLabelWidgetClass,
189                                   pOutput->innerPage,
190                                   XmNalignment, XmALIGNMENT_END,
191                                   XmNleftAttachment, XmATTACH_WIDGET,
192                                   XmNleftWidget, pOutput->footerLeft,
193                                   XmNrightAttachment, XmATTACH_FORM,
194                                   XmNbottomAttachment, XmATTACH_FORM,
195                                   NULL);
196     pOutput->footerRight = w;
197
198     XtVaSetValues(
199                 pOutput->editor,
200                 XmNbottomAttachment, XmATTACH_WIDGET,
201                 XmNbottomWidget, pOutput->footerLeft,
202                 NULL);
203
204     XtManageChild(pOutput->innerPage);
205     XtManageChild(pOutput->page);
206
207     PrintOutputSetPageMargins(
208                 pOutput,
209                 _poDefaultMargin,
210                 _poDefaultMargin,
211                 _poDefaultMargin,
212                 _poDefaultMargin,
213                 &parseError );
214     assert(parseError == 0);
215
216     return pOutput;
217 }
218
219 /************************************************************************
220  * PrintOutputCreate
221  *      Class destructor.
222  ************************************************************************/
223 void
224 PrintOutputDestroy(PrintOutput *pOutput)
225 {
226     if (pOutput == NULL) return;
227     XtDestroyWidget(pOutput->page);
228     XtFree((char*) pOutput);
229 }
230
231 /************************************************************************
232  * PrintOutputHideFooter
233  * PrintOutputShowFooter
234  * PrintOutputHideHeader
235  * PrintOutputShowHeader
236  *      Unmanages/Manages the footer/header widgets
237  ************************************************************************/
238 void
239 PrintOutputHideFooters(PrintOutput *pOutput)
240 {
241     XtUnmanageChild(pOutput->footerLeft);
242     XtUnmanageChild(pOutput->footerRight);
243     XtVaSetValues(pOutput->editor, XmNbottomAttachment, XmATTACH_FORM, NULL);
244 }
245
246 void
247 PrintOutputShowFooters(PrintOutput *pOutput)
248 {
249     XtManageChild(pOutput->footerLeft);
250     XtManageChild(pOutput->footerRight);
251     XtVaSetValues(
252                 pOutput->editor,
253                 XmNbottomAttachment, XmATTACH_WIDGET,
254                 XmNbottomWidget, pOutput->footerLeft,
255                 NULL);
256 }
257
258 void
259 PrintOutputHideHeaders(PrintOutput *pOutput)
260 {
261     XtUnmanageChild(pOutput->headerLeft);
262     XtUnmanageChild(pOutput->headerRight);
263     XtVaSetValues(pOutput->editor, XmNtopAttachment, XmATTACH_FORM, NULL);
264 }
265
266 void
267 PrintOutputShowHeaders(PrintOutput *pOutput)
268 {
269     XtManageChild(pOutput->headerLeft);
270     XtManageChild(pOutput->headerRight);
271     XtVaSetValues(
272                 pOutput->editor,
273                 XmNtopAttachment, XmATTACH_WIDGET,
274                 XmNtopWidget, pOutput->headerLeft,
275                 NULL);
276 }
277
278 /************************************************************************
279  * PrintOutputSetHdrFtrString
280  *      Set the contents of the specifies header/footer
281  ************************************************************************/
282 void
283 PrintOutputSetHdrFtrString(
284                         PrintOutput *pOutput,
285                         _DtPrintHdrFtrEnum which,
286                         char *contents
287                         )
288 {
289     Widget      w;
290     XmString    xms;
291
292     if (contents == (char *) NULL)
293       return;
294
295     switch (which)
296     {
297         case DTPRINT_OPTION_HEADER_LEFT:
298           w = pOutput->headerLeft;
299           break;
300         case DTPRINT_OPTION_HEADER_RIGHT:
301           w = pOutput->headerRight;
302           break;
303         case DTPRINT_OPTION_FOOTER_LEFT:
304           w = pOutput->footerLeft;
305           break;
306         case DTPRINT_OPTION_FOOTER_RIGHT:
307           w = pOutput->footerRight;
308           break;
309         default:
310           return;
311     }
312
313     xms = XmStringCreateLocalized(contents);
314     XtVaSetValues(w, XmNlabelString, xms, NULL);
315     XmStringFree(xms);
316 }
317
318 /************************************************************************
319  * PrintOutputSetHdrFtrStrings
320  *      Set the contents of all the header/footers
321  ************************************************************************/
322 void
323 PrintOutputSetHdrFtrStrings(
324                         PrintOutput *pOutput,
325                         char *hdrLeft,
326                         char *hdrRight,
327                         char *ftrLeft,
328                         char *ftrRight
329                         )
330 {
331     XmString    xms;
332
333     if (hdrLeft)
334     {
335         xms = XmStringCreateLocalized(hdrLeft);
336         XtVaSetValues(pOutput->headerLeft, XmNlabelString, xms, NULL);
337         XmStringFree(xms);
338     }
339
340     if (hdrRight)
341     {
342         xms = XmStringCreateLocalized(hdrRight);
343         XtVaSetValues(pOutput->headerRight, XmNlabelString, xms, NULL);
344         XmStringFree(xms);
345     }
346
347     if (ftrLeft)
348     {
349         xms = XmStringCreateLocalized(ftrLeft);
350         XtVaSetValues(pOutput->footerLeft, XmNlabelString, xms, NULL);
351         XmStringFree(xms);
352     }
353
354     if (ftrRight)
355     {
356         xms = XmStringCreateLocalized(ftrRight);
357         XtVaSetValues(pOutput->footerRight, XmNlabelString, xms, NULL);
358         XmStringFree(xms);
359     }
360 }
361
362 /************************************************************************
363  * PrintOutputSetPageMargin
364  *      Set the contents of the specified page margin
365  ************************************************************************/
366 void
367 PrintOutputSetPageMargin(
368                         PrintOutput *pOutput,
369                         _DtPrintMarginEnum which,
370                         const char *margin,
371                         Boolean *parseError
372                         )
373 {
374     int         pixels = 0;
375     XtEnum      xtParseError = FALSE;
376     char        *marginString = XtNewString(margin);
377
378     if (parseError)
379       *parseError = FALSE;
380
381     switch (which)
382     {
383         case DTPRINT_OPTION_MARGIN_TOP:
384           pixels = XmConvertStringToUnits(
385                                         XtScreenOfObject(pOutput->pShell),
386                                         marginString,
387                                         XmVERTICAL,
388                                         XmPIXELS,
389                                         &xtParseError);
390           if (!xtParseError && pixels > 0)
391             pOutput->marginTop = pixels;
392           break;
393         case DTPRINT_OPTION_MARGIN_RIGHT:
394           pixels = XmConvertStringToUnits(
395                                         XtScreenOfObject(pOutput->pShell),
396                                         marginString,
397                                         XmHORIZONTAL,
398                                         XmPIXELS,
399                                         &xtParseError);
400           if (!xtParseError && pixels > 0)
401             pOutput->marginRight = pixels;
402           break;
403         case DTPRINT_OPTION_MARGIN_BOTTOM:
404           pixels = XmConvertStringToUnits(
405                                         XtScreenOfObject(pOutput->pShell),
406                                         marginString,
407                                         XmVERTICAL,
408                                         XmPIXELS,
409                                         &xtParseError);
410           if (!xtParseError && pixels > 0)
411             pOutput->marginBottom = pixels;
412           break;
413         case DTPRINT_OPTION_MARGIN_LEFT:
414           pixels = XmConvertStringToUnits(
415                                         XtScreenOfObject(pOutput->pShell),
416                                         marginString,
417                                         XmHORIZONTAL,
418                                         XmPIXELS,
419                                         &xtParseError);
420           if (!xtParseError && pixels > 0)
421             pOutput->marginLeft = pixels;
422           break;
423         default:
424           return;
425     }
426
427     if (!xtParseError)
428       _poSetInnerPageDimensions(
429                         pOutput,
430                         pOutput->marginTop,
431                         pOutput->marginRight,
432                         pOutput->marginBottom,
433                         pOutput->marginLeft);
434     else
435       *parseError = TRUE;
436
437     XtFree(marginString);
438 }
439
440 /************************************************************************
441  * PrintOutputSetPageMargins
442  *      Set the contents of all the page margins
443  ************************************************************************/
444 void
445 PrintOutputSetPageMargins(
446                         PrintOutput *pOutput,
447                         const char *top,
448                         const char *right,
449                         const char *bottom,
450                         const char *left,
451                         Boolean *parseError
452                         )
453 {
454     int         pixels = 0;
455     XtEnum      xtParseError = FALSE;
456     char        *margin;
457
458     *parseError = FALSE;
459
460     margin = XtNewString(top);
461     pixels = XmConvertStringToUnits(
462                                 XtScreenOfObject(pOutput->pShell),
463                                 margin,
464                                 XmVERTICAL,
465                                 XmPIXELS,
466                                 &xtParseError);
467     XtFree(margin);
468     if (!xtParseError && pixels > 0)
469     {
470         pOutput->marginTop = pixels;
471     }
472     else
473     {    
474         *parseError = TRUE;
475         return;
476     }
477
478     margin = XtNewString(right);
479     pixels = XmConvertStringToUnits(
480                                 XtScreenOfObject(pOutput->pShell),
481                                 margin,
482                                 XmHORIZONTAL,
483                                 XmPIXELS,
484                                 &xtParseError);
485     XtFree(margin);
486     if (!xtParseError && pixels > 0)
487     {
488         pOutput->marginRight = pixels;
489     }
490     else
491     {    
492         *parseError = TRUE;
493         return;
494     }
495
496     margin = XtNewString(bottom);
497     pixels = XmConvertStringToUnits(
498                                 XtScreenOfObject(pOutput->pShell),
499                                 margin,
500                                 XmVERTICAL,
501                                 XmPIXELS,
502                                 &xtParseError);
503     XtFree(margin);
504     if (!xtParseError && pixels > 0)
505     {
506         pOutput->marginBottom = pixels;
507     }
508     else
509     {    
510         *parseError = TRUE;
511         return;
512     }
513
514     margin = XtNewString(left);
515     pixels = XmConvertStringToUnits(
516                                 XtScreenOfObject(pOutput->pShell),
517                                 margin,
518                                 XmHORIZONTAL,
519                                 XmPIXELS,
520                                 &xtParseError);
521     XtFree(margin);
522     if (!xtParseError && pixels > 0)
523     {
524         pOutput->marginLeft = pixels;
525     }
526     else
527     {    
528         *parseError = TRUE;
529         return;
530     }
531
532     _poSetInnerPageDimensions(
533                         pOutput,
534                         pOutput->marginTop,
535                         pOutput->marginRight,
536                         pOutput->marginBottom,
537                         pOutput->marginLeft);
538 }
539
540
541 /************************************************************************
542  * PrintOutputSetWordWrap
543  *      Set the wrap to fit value in the editor
544  ************************************************************************/
545 void
546 PrintOutputSetWordWrap(PrintOutput *pOutput, Boolean onoff)
547 {
548 #ifdef USE_DTEDITOR
549     XtVaSetValues(pOutput->editor, DtNwordWrap, onoff, NULL);
550 #else
551     XtVaSetValues(pOutput->editor, XmNwordWrap, onoff, NULL);
552 #endif
553 }
554
555 /************************************************************************
556  * PrintOutputGetLinesPerPage
557  *      Returns the number of lines per page.
558  ************************************************************************/
559 int
560 PrintOutputGetLinesPerPage(PrintOutput *pOutput)
561 {
562     return ((int) pOutput->linesPerPage);
563 }
564
565 /************************************************************************
566  * PrintOutputGetNumLines
567  *      Returns the number of lines of test in the editor.
568  ************************************************************************/
569 int
570 PrintOutputGetNumLines(PrintOutput *pOutput)
571 {
572     XtArgVal p;
573     int total = 0;
574     int saveTop;
575
576 #ifdef USE_DTEDITOR
577     saveTop = pOutput->currentLine;
578     PrintOutputFirstPage(pOutput);
579     while (PrintOutputPageDown(pOutput))
580       total += pOutput->linesPerPage;
581
582     DtEditorGoToLine(pOutput->editor, saveTop);
583     pOutput->currentLine = saveTop;
584 #else
585     XtVaGetValues(pOutput->editor, XmNtotalLines, &p, NULL);
586     total = (int)p;
587 #endif
588     return(total);
589 }
590
591 /************************************************************************
592  * PrintOutputPageUp
593  ************************************************************************/
594 Boolean
595 PrintOutputPageUp(PrintOutput *pOutput)
596 {
597     XmTextPosition      top_before, top_after;
598     Boolean             retval;
599
600 #ifdef USE_DTEDITOR
601     DtEditorGoToLine(
602                 pOutput->editor,
603                 pOutput->currentLine - pOutput->linesPerPage
604                 );
605     pOutput->currentLine -= pOutput->linesPerPage;
606     if (pOutput->currentLine < 1)
607     {
608         pOutput->currentLine = 1;
609         retval = FALSE;
610     }
611 #else
612     top_before = (XmTextPosition) _poGetTopPosition(pOutput);
613     XmTextScroll(pOutput->editor, -1 * pOutput->linesPerPage);
614     top_after = (XmTextPosition) _poGetTopPosition(pOutput);
615     retval = (top_before > top_after) ? TRUE : FALSE;
616 #endif
617
618     return retval;
619 }
620
621 /************************************************************************
622  * PrintOutputPageDown
623  ************************************************************************/
624 Boolean
625 PrintOutputPageDown(PrintOutput *pOutput)
626 {
627     XmTextPosition      top_before, top_after;
628
629     top_before = (XmTextPosition) _poGetTopPosition(pOutput);
630
631 #ifdef USE_DTEDITOR
632     DtEditorGoToLine(
633                 pOutput->editor,
634                 pOutput->currentLine + pOutput->linesPerPage
635                 );
636     pOutput->currentLine += pOutput->linesPerPage;
637 #else
638     XmTextScroll(pOutput->editor, pOutput->linesPerPage);
639 #endif
640
641     top_after = (XmTextPosition) _poGetTopPosition(pOutput);
642     return (top_before < top_after) ? TRUE : FALSE;
643 }
644
645 /************************************************************************
646  * PrintOutputFirstPage
647  ************************************************************************/
648 void
649 PrintOutputFirstPage(PrintOutput *pOutput)
650 {
651 #ifdef USE_DTEDITOR
652     XtVaSetValues(pOutput->editor, DtNtopCharacter, (XmTextPosition) 0, NULL);
653     pOutput->currentLine = 1;
654 #else
655     XmTextSetTopCharacter(pOutput->editor, (XmTextPosition) 0);
656 #endif
657 }
658
659 /************************************************************************
660  * PrintOutputLoadFile
661  ************************************************************************/
662 DtEditorErrorCode
663 PrintOutputLoadFile( PrintOutput *pOutput, char *file)
664 {
665     char                *contents = NULL;
666     DtEditorErrorCode   errorCode;
667
668 #ifdef USE_DTEDITOR
669     errorCode = DtEditorSetContentsFromFile(pOutput->editor, file);
670 #else
671     errorCode = _poGetFileContents(&contents, file);
672     if (contents != NULL)
673     {
674         XmTextSetString(pOutput->editor, contents);
675         free(contents);
676     }
677 #endif
678
679     return errorCode;
680 }
681
682 /************************************************************************
683  ************************************************************************
684  *
685  * Private class methods
686  *
687  *     _poDoGetLinesPerPage     - Returns number of rows in the editor.
688  *     _poSetInnerPageDimensions- Sets the XmN x,y,width,height of InnerPage.
689  *     _poGetTopPosition        - Returns the position of the 1st visible char.
690  *     _poGetFileContents       - Returns the contents of the specified file.
691  *     _poStripEmbeddedNulls    - Removes any embedded NULLs (\0) in a
692  *                                string of length 'length'.  The removal
693  *                                occurs in place, with 'length' set to the
694  *                                new, stripped length.  The resulting string
695  *                                is terminated with a trailing NULL.  
696  * 
697  ************************************************************************
698  ************************************************************************/
699
700 static int
701 _poDoGetLinesPerPage(PrintOutput *pOutput)
702 {
703     XtArgVal   lpp;
704
705     XtVaGetValues(pOutput->editor, XmNrows, &lpp, NULL);
706     return ((int) lpp);
707 }
708
709
710 static void
711 _poSetInnerPageDimensions(
712                         PrintOutput *pOutput,
713                         Dimension top,
714                         Dimension right,
715                         Dimension bottom,
716                         Dimension left
717                         )
718 {
719     XtArgVal    outer_height0, outer_width0, footer_height0, header_height0;
720     Dimension   inner_height, inner_width, inner_x, inner_y,
721                 outer_height, outer_width,
722                 editor_height, footer_height, header_height;
723
724     XtVaGetValues(pOutput->page,
725                   XmNheight, &outer_height0,
726                   XmNwidth, &outer_width0,
727                   NULL);
728
729     XtVaGetValues(pOutput->headerLeft,
730                   XmNheight, &header_height0,
731                   NULL);
732
733     XtVaGetValues(pOutput->footerLeft,
734                   XmNheight, &footer_height0,
735                   NULL);
736
737     outer_height = (Dimension)outer_height0;
738     outer_width = (Dimension)outer_width0;
739     header_height = (Dimension)header_height0;
740     footer_height = (Dimension)footer_height0;
741
742     inner_x = left;
743     inner_y = top;
744     inner_height = (outer_height > (Dimension) (top + bottom)) ?
745                         (outer_height - (top +  bottom)) :
746                         outer_height;
747     inner_width = (outer_width > (Dimension) (left + right)) ?
748                         (outer_width - (left + right)) :
749                         outer_width;
750     editor_height =
751                 (inner_height > (Dimension) (header_height + footer_height)) ?
752                         (inner_height - (header_height + footer_height)) :
753                         inner_height;
754     
755     XtVaSetValues(pOutput->editor, XmNheight, editor_height, NULL);
756
757     XtVaSetValues(pOutput->innerPage,
758                 XmNleftAttachment, XmATTACH_NONE,
759                 XmNtopAttachment, XmATTACH_NONE,
760                 XmNx, inner_x,
761                 XmNy, inner_y,
762                 XmNheight, inner_height,
763                 XmNwidth, inner_width,
764                 NULL);
765
766     pOutput->linesPerPage = _poDoGetLinesPerPage(pOutput);
767 }
768
769 /*
770  * _poGetTopPosition
771  */
772 static int
773 _poGetTopPosition(PrintOutput *pOutput)
774 {
775     XmTextPosition top = (XmTextPosition) 0;
776
777 #ifdef USE_DTEDITOR
778     XtVaGetValues(pOutput->editor, DtNtopCharacter, &top, NULL);
779 #else
780     top = XmTextGetTopCharacter(pOutput->editor);
781 #endif
782     return (int) top;
783 }
784
785 static DtEditorErrorCode
786 _poGetFileContents(char **contents, char *file)
787 {
788     DtEditorErrorCode   error = DtEDITOR_NO_ERRORS;
789     struct stat         statbuf;
790     char                *buf;
791     int                 nbytes;
792     FILE                *fp = NULL;
793
794     if (file == NULL || *file == '\0') return
795
796     /*
797      * Open the file for reading.
798      */
799     error = _poEditorValidateFileAccess(file, READ_ACCESS);
800     if (error != DtEDITOR_NO_ERRORS) return error;
801
802     if( (fp = fopen(file, "r")) == NULL )
803       return DtEDITOR_UNREADABLE_FILE;
804
805     stat(file, &statbuf);
806     nbytes = statbuf.st_size;
807
808     /* 
809      * Read the file contents (with room for null) & convert to a
810      * string.  We want to use a string because the 
811      * DtEditorSetContents/Append/Insert/... functions create another 
812      * copy of the data before actually putting it into the widget.
813      */
814     buf = (char *) malloc(nbytes + 1);
815     if (buf == NULL)
816       return DtEDITOR_INSUFFICIENT_MEMORY;
817
818     nbytes = fread(buf, sizeof(char), nbytes, fp);
819     buf[nbytes] = '\0';
820
821     /* 
822      * Strip out any embedded NULLs because the text widget will only 
823      * accept data up to the first NULL.
824      */
825     error = _poStripEmbeddedNulls(buf, &nbytes);
826
827     /* Close the file */
828     fclose(fp);
829
830     *contents = buf;
831     return error;
832 } /* end LoadFile */
833
834 static DtEditorErrorCode 
835 _poStripEmbeddedNulls(char *strbuf, int *len)
836 {
837     DtEditorErrorCode retval = DtEDITOR_NO_ERRORS;
838
839     if (strlen(strbuf) != *len)
840     {
841        int firstNull;
842
843        retval = DtEDITOR_NULLS_REMOVED;
844
845        /*
846         * The file contains NULL characters, so we strip them out and
847         * report that we have done so.
848         */
849        while((firstNull = strlen(strbuf)) != *len)
850        {
851           int lastNull = firstNull;
852
853           while((lastNull+1) < *len && strbuf[lastNull+1] == (char)'\0')
854             lastNull++;
855
856           memcpy(&strbuf[firstNull], &strbuf[lastNull+1], *len-lastNull);
857           *len -= 1 + lastNull - firstNull;
858        }
859     }
860
861     return retval;
862 }
863
864 extern DtEditorErrorCode
865 _poEditorValidateFileAccess( char *file, int accessType )
866 {
867    struct stat statbuf;
868    unsigned short tmpMode;
869
870    if (file && *file ) return DtEDITOR_INVALID_FILENAME;
871
872    if (access(file, F_OK) != 0) return DtEDITOR_NONEXISTENT_FILE; 
873
874    if( stat(file, &statbuf) != 0 ) return DtEDITOR_NO_FILE_ACCESS;
875
876    if( (statbuf.st_mode & S_IFMT) == S_IFDIR ) return DtEDITOR_DIRECTORY;
877
878    if( (statbuf.st_mode & S_IFMT) == S_IFCHR ) return DtEDITOR_CHAR_SPECIAL_FILE;
879
880    if((statbuf.st_mode & S_IFMT) == S_IFBLK) return DtEDITOR_BLOCK_MODE_FILE;
881
882    switch( accessType )
883    {
884       case READ_ACCESS:
885         if (access(file, R_OK) != 0) return DtEDITOR_UNREADABLE_FILE;
886         break;
887       case WRITE_ACCESS:
888         if (access(file, W_OK) != 0) return DtEDITOR_UNWRITABLE_FILE;
889         break;
890       default:
891         break;
892    } /* end stat suceeded */
893
894    return DtEDITOR_NO_ERRORS;
895 }