Link with C++ linker
[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 == NULL);
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     int total = 0;
573     int saveTop;
574
575 #ifdef USE_DTEDITOR
576     saveTop = pOutput->currentLine;
577     PrintOutputFirstPage(pOutput);
578     while (PrintOutputPageDown(pOutput))
579       total += pOutput->linesPerPage;
580
581     DtEditorGoToLine(pOutput->editor, saveTop);
582     pOutput->currentLine = saveTop;
583 #else
584     XtVaGetValues(pOutput->editor, XmNtotalLines, &total, NULL);
585 #endif
586     return(total);
587 }
588
589 /************************************************************************
590  * PrintOutputPageUp
591  ************************************************************************/
592 Boolean
593 PrintOutputPageUp(PrintOutput *pOutput)
594 {
595     XmTextPosition      top_before, top_after;
596     Boolean             retval;
597
598 #ifdef USE_DTEDITOR
599     DtEditorGoToLine(
600                 pOutput->editor,
601                 pOutput->currentLine - pOutput->linesPerPage
602                 );
603     pOutput->currentLine -= pOutput->linesPerPage;
604     if (pOutput->currentLine < 1)
605     {
606         pOutput->currentLine = 1;
607         retval = FALSE;
608     }
609 #else
610     top_before = (XmTextPosition) _poGetTopPosition(pOutput);
611     XmTextScroll(pOutput->editor, -1 * pOutput->linesPerPage);
612     top_after = (XmTextPosition) _poGetTopPosition(pOutput);
613     retval = (top_before > top_after) ? TRUE : FALSE;
614 #endif
615
616     return retval;
617 }
618
619 /************************************************************************
620  * PrintOutputPageDown
621  ************************************************************************/
622 Boolean
623 PrintOutputPageDown(PrintOutput *pOutput)
624 {
625     XmTextPosition      top_before, top_after;
626
627     top_before = (XmTextPosition) _poGetTopPosition(pOutput);
628
629 #ifdef USE_DTEDITOR
630     DtEditorGoToLine(
631                 pOutput->editor,
632                 pOutput->currentLine + pOutput->linesPerPage
633                 );
634     pOutput->currentLine += pOutput->linesPerPage;
635 #else
636     XmTextScroll(pOutput->editor, pOutput->linesPerPage);
637 #endif
638
639     top_after = (XmTextPosition) _poGetTopPosition(pOutput);
640     return (top_before < top_after) ? TRUE : FALSE;
641 }
642
643 /************************************************************************
644  * PrintOutputFirstPage
645  ************************************************************************/
646 void
647 PrintOutputFirstPage(PrintOutput *pOutput)
648 {
649 #ifdef USE_DTEDITOR
650     XtVaSetValues(pOutput->editor, DtNtopCharacter, (XmTextPosition) 0, NULL);
651     pOutput->currentLine = 1;
652 #else
653     XmTextSetTopCharacter(pOutput->editor, (XmTextPosition) 0);
654 #endif
655 }
656
657 /************************************************************************
658  * PrintOutputLoadFile
659  ************************************************************************/
660 DtEditorErrorCode
661 PrintOutputLoadFile( PrintOutput *pOutput, char *file)
662 {
663     char                *contents = NULL;
664     DtEditorErrorCode   errorCode;
665
666 #ifdef USE_DTEDITOR
667     errorCode = DtEditorSetContentsFromFile(pOutput->editor, file);
668 #else
669     errorCode = _poGetFileContents(&contents, file);
670     if (contents != NULL)
671     {
672         XmTextSetString(pOutput->editor, contents);
673         free(contents);
674     }
675 #endif
676
677     return errorCode;
678 }
679
680 /************************************************************************
681  ************************************************************************
682  *
683  * Private class methods
684  *
685  *     _poDoGetLinesPerPage     - Returns number of rows in the editor.
686  *     _poSetInnerPageDimensions- Sets the XmN x,y,width,height of InnerPage.
687  *     _poGetTopPosition        - Returns the position of the 1st visible char.
688  *     _poGetFileContents       - Returns the contents of the specified file.
689  *     _poStripEmbeddedNulls    - Removes any embedded NULLs (\0) in a
690  *                                string of length 'length'.  The removal
691  *                                occurs in place, with 'length' set to the
692  *                                new, stripped length.  The resulting string
693  *                                is terminated with a trailing NULL.  
694  * 
695  ************************************************************************
696  ************************************************************************/
697
698 static int
699 _poDoGetLinesPerPage(PrintOutput *pOutput)
700 {
701     Dimension   lpp;
702
703     XtVaGetValues(pOutput->editor, XmNrows, &lpp, NULL);
704     return ((int) lpp);
705 }
706
707
708 static void
709 _poSetInnerPageDimensions(
710                         PrintOutput *pOutput,
711                         Dimension top,
712                         Dimension right,
713                         Dimension bottom,
714                         Dimension left
715                         )
716 {
717     Dimension   inner_height, inner_width, inner_x, inner_y,
718                 outer_height, outer_width,
719                 editor_height, footer_height, header_height;
720
721     XtVaGetValues(pOutput->page,
722                   XmNheight, &outer_height,
723                   XmNwidth, &outer_width,
724                   NULL);
725
726     XtVaGetValues(pOutput->headerLeft,
727                   XmNheight, &header_height,
728                   NULL);
729
730     XtVaGetValues(pOutput->footerLeft,
731                   XmNheight, &footer_height,
732                   NULL);
733
734     inner_x = left;
735     inner_y = top;
736     inner_height = (outer_height > (Dimension) (top + bottom)) ?
737                         (outer_height - (top +  bottom)) :
738                         outer_height;
739     inner_width = (outer_width > (Dimension) (left + right)) ?
740                         (outer_width - (left + right)) :
741                         outer_width;
742     editor_height =
743                 (inner_height > (Dimension) (header_height + footer_height)) ?
744                         (inner_height - (header_height + footer_height)) :
745                         inner_height;
746     
747     XtVaSetValues(pOutput->editor, XmNheight, editor_height, NULL);
748
749     XtVaSetValues(pOutput->innerPage,
750                 XmNleftAttachment, XmATTACH_NONE,
751                 XmNtopAttachment, XmATTACH_NONE,
752                 XmNx, inner_x,
753                 XmNy, inner_y,
754                 XmNheight, inner_height,
755                 XmNwidth, inner_width,
756                 NULL);
757
758     pOutput->linesPerPage = _poDoGetLinesPerPage(pOutput);
759 }
760
761 /*
762  * _poGetTopPosition
763  */
764 static int
765 _poGetTopPosition(PrintOutput *pOutput)
766 {
767     XmTextPosition top = (XmTextPosition) 0;
768
769 #ifdef USE_DTEDITOR
770     XtVaGetValues(pOutput->editor, DtNtopCharacter, &top, NULL);
771 #else
772     top = XmTextGetTopCharacter(pOutput->editor);
773 #endif
774     return (int) top;
775 }
776
777 static DtEditorErrorCode
778 _poGetFileContents(char **contents, char *file)
779 {
780     DtEditorErrorCode   error = DtEDITOR_NO_ERRORS;
781     struct stat         statbuf;
782     char                *buf;
783     int                 nbytes;
784     FILE                *fp = NULL;
785
786     if (file == NULL || *file == NULL) return
787
788     /*
789      * Open the file for reading.
790      */
791     error = _poEditorValidateFileAccess(file, READ_ACCESS);
792     if (error != DtEDITOR_NO_ERRORS) return error;
793
794     if( (fp = fopen(file, "r")) == NULL )
795       return DtEDITOR_UNREADABLE_FILE;
796
797     stat(file, &statbuf);
798     nbytes = statbuf.st_size;
799
800     /* 
801      * Read the file contents (with room for null) & convert to a
802      * string.  We want to use a string because the 
803      * DtEditorSetContents/Append/Insert/... functions create another 
804      * copy of the data before actually putting it into the widget.
805      */
806     buf = (char *) malloc(nbytes + 1);
807     if (buf == NULL)
808       return DtEDITOR_INSUFFICIENT_MEMORY;
809
810     nbytes = fread(buf, sizeof(char), nbytes, fp);
811     buf[nbytes] = '\0';
812
813     /* 
814      * Strip out any embedded NULLs because the text widget will only 
815      * accept data up to the first NULL.
816      */
817     error = _poStripEmbeddedNulls(buf, &nbytes);
818
819     /* Close the file */
820     fclose(fp);
821
822     *contents = buf;
823     return error;
824 } /* end LoadFile */
825
826 static DtEditorErrorCode 
827 _poStripEmbeddedNulls(char *strbuf, int *len)
828 {
829     DtEditorErrorCode retval = DtEDITOR_NO_ERRORS;
830
831     if (strlen(strbuf) != *len)
832     {
833        int firstNull;
834
835        retval = DtEDITOR_NULLS_REMOVED;
836
837        /*
838         * The file contains NULL characters, so we strip them out and
839         * report that we have done so.
840         */
841        while((firstNull = strlen(strbuf)) != *len)
842        {
843           int lastNull = firstNull;
844
845           while((lastNull+1) < *len && strbuf[lastNull+1] == (char)'\0')
846             lastNull++;
847
848           memcpy(&strbuf[firstNull], &strbuf[lastNull+1], *len-lastNull);
849           *len -= 1 + lastNull - firstNull;
850        }
851     }
852
853     return retval;
854 }
855
856 extern DtEditorErrorCode
857 _poEditorValidateFileAccess( char *file, int accessType )
858 {
859    struct stat statbuf;
860    unsigned short tmpMode;
861
862    if (file && *file ) return DtEDITOR_INVALID_FILENAME;
863
864    if (access(file, F_OK) != 0) return DtEDITOR_NONEXISTENT_FILE; 
865
866    if( stat(file, &statbuf) != 0 ) return DtEDITOR_NO_FILE_ACCESS;
867
868    if( (statbuf.st_mode & S_IFMT) == S_IFDIR ) return DtEDITOR_DIRECTORY;
869
870    if( (statbuf.st_mode & S_IFMT) == S_IFCHR ) return DtEDITOR_CHAR_SPECIAL_FILE;
871
872    if((statbuf.st_mode & S_IFMT) == S_IFBLK) return DtEDITOR_BLOCK_MODE_FILE;
873
874    switch( accessType )
875    {
876       case READ_ACCESS:
877         if (access(file, R_OK) != 0) return DtEDITOR_UNREADABLE_FILE;
878         break;
879       case WRITE_ACCESS:
880         if (access(file, W_OK) != 0) return DtEDITOR_UNWRITABLE_FILE;
881         break;
882       default:
883         break;
884    } /* end stat suceeded */
885
886    return DtEDITOR_NO_ERRORS;
887 }