dtcm: make it build
[oweals/cde.git] / cde / lib / DtHelp / FormatMan.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: FormatMan.c /main/14 1999/10/14 15:06:59 mgreess $ */
24 /************************************<+>*************************************
25  ****************************************************************************
26  **
27  **   File:     FormatMan.c
28  **
29  **   Project:     Text Graphic Display Library
30  **
31  **   Description: This body of formats the input into a form understood by
32  **             a Display Area.
33  **
34  **
35  **  (c) Copyright 1987, 1988, 1989, 1990, 1991, 1992 Hewlett-Packard Company
36  **
37  **  (c) Copyright 1993, 1994 Hewlett-Packard Company
38  **  (c) Copyright 1993, 1994 International Business Machines Corp.
39  **  (c) Copyright 1993, 1994 Sun Microsystems, Inc.
40  **  (c) Copyright 1993, 1994 Novell, Inc.
41  **
42  **
43  **
44  ****************************************************************************
45  ************************************<+>*************************************/
46
47 /*
48  * system includes
49  */
50 #include <errno.h>
51 #if defined(sun)
52 #include <sys/utsname.h>
53 #endif
54 #include <limits.h>
55 #include <locale.h>
56 #include <nl_types.h>
57 #include <string.h>
58 #include <unistd.h>
59 #include <stdio.h>
60 #include <stdlib.h>
61
62 #include <Xm/Xm.h>
63
64 /*
65  * Canvas Engine
66  */
67 #include "CanvasP.h"
68 #include "CanvasSegP.h"
69
70 /*
71  * private includes
72  */
73 #include "bufioI.h"
74 #include "DisplayAreaP.h"
75 #include "Access.h"
76 #include "CleanUpI.h"
77 #include "FontAttrI.h"
78 #include "FormatUtilI.h"
79 #include "FormatCCDFI.h"
80 #include "FormatManI.h"
81 #include "HelpXlate.h"
82 #include "XInterfaceI.h"
83
84 #ifdef NLS16
85 #endif
86
87 /******************************************************************************
88  *
89  * Private variables and defines.
90  *
91  *****************************************************************************/
92 enum    State   {
93         Char,
94         Bold,
95         BoldDone,
96         Italic,
97         BoldItalic,
98         BoldItalicDone};
99
100 #define STDOUT_FD (1)   /* File descriptor for std. output. */
101 #define STDERR_FD (1)   /* File descriptor for std. error. */
102
103 #define PIPE_OUT  (0)   /* The output end of a pipe. */
104 #define PIPE_IN   (1)   /* The input end of a pipe. */
105
106 static  char    *ScanString  = "<\n\\ ";
107 static  char    *EndToken    = "</>";
108 static  char    *BoldToken   = "<weight bold>";
109 static  char    *ItalicToken = "<angle italic>";
110
111 static  int     EndTokenSize    = 3;
112 static  int     BoldTokenSize   = 13;
113 static  int     ItalicTokenSize = 14;
114
115 /********    Private Function Declarations    ********/
116 static  int     FormatManPage(
117                         VarHandle         my_vars,
118                         BufFilePtr        in_file,
119                         char             *in_buf,
120                         int               in_size,
121                         _DtHelpFontHints        *font_attr,
122                         char            **out_buf,
123                         int              *out_size,
124                         int              *out_max );
125 /********    End Public Function Declarations    ********/
126
127 #define FileStream(f)   ((FILE *)(f)->hidden)
128
129 /******************************************************************************
130  *
131  * Private Functions
132  *
133  *****************************************************************************/
134 /*********************************************************************
135  * Procedure: GetNextState (char c, wchar_t wide_c, int length, char *str,
136  *                      wchar_t ret_wc, int ret_wc_len, char ret_str_ptr,
137  *                      Boolean ret_flag)
138  *
139  * Parameters:  wide_c          Specifies the wide char value of the
140  *                              previous character.
141  *              length          Specifies the length in bytes of the
142  *                              previous character.
143  *              str             Specifies the pointer to the string of
144  *                              bytes to be processed next.
145  *              ret_wc          Returns the wide character that is to be
146  *                              italicized iff the state returned is Italic.
147  *              ret_wc_len      Returns the length in bytes of ret_wc.
148  *              ret_str_ptr     Returns the pointer to the next character
149  *                              after the bold or italic character.
150  *              ret_flag        Returns whether we have encountered a
151  *                              + followed by a _, to convert to +/-
152  *
153  * Returns:     Bold, Italic, Char
154  *
155  * Purpose:     To determine if the sequence of characters represent
156  *              a bold or italic character.
157  *
158  *********************************************************************/
159 static  enum State
160 GetNextState (
161     char         c,
162     wchar_t      wide_c,
163     int          len,
164     char        *str,
165     char        *ret_c,
166     wchar_t     *ret_wc,
167     int         *ret_wc_len,
168     char        **ret_str_ptr,
169     Boolean      *ret_flag )
170 {
171     int i = len;
172
173     /* check to see if we have the pattern of a bold + followed by a bold _
174        purpose is to eventually convert this to +/-
175        This is a hack because the nroff output produced for the sequence
176        of a + with an _ UNDER it, as in indicating statistical significance,
177        looks like a bold +, backspace, and then a bold _.
178        However, the nroff output indicates <c>bs_ as an italic, so
179        this sequence has to be treated as a special case. */
180        
181     if (*str == '+')
182       {
183         if (str[7] == '\010' && str[8] == '_' &&
184             str[9] == '\010' && str[10] == '_' &&
185             str[11] == '\010' && str[12] == '_' &&
186             str[13] == '\010' && str[14] == '_' )
187           {
188             *ret_flag = TRUE;
189           } 
190       }
191
192     /* We need to eat the bold '_' -- continuation of aforementioned hack */
193     if (TRUE == *ret_flag)
194       {
195         if (c == '+' &&
196             str[0] == '\010' && str[1] == '_' &&
197             str[2] == '\010' && str[3] == '_' &&
198             str[4] == '\010' && str[5] == '_' &&
199             str[6] == '\010' && str[7] == '_' )
200           {
201             *ret_flag = FALSE;
202             *ret_str_ptr = str + 8;
203             return Bold;
204           }
205       }
206     
207     /*
208      * check for multi-byte italic which is '_ _bsbs<c>'
209      */
210     if (len == 1 && c == '_' && mblen (str, MB_CUR_MAX) == 1 && *str == '_')
211       {
212         str++;
213         i++;
214       }
215
216     /*
217      * check for backspaces equal to the number of bytes making up wide_c.
218      */
219     while (i)
220       {
221         if (mblen (str, MB_CUR_MAX) != 1 || *str != '\010')
222             return Char;
223         i--;
224         str++;
225       }
226
227     /*
228      * convert the next character
229      */
230     *ret_wc_len = mbtowc(ret_wc, str, MB_CUR_MAX);
231
232     /*
233      * check for validity
234      */
235     if ((*ret_wc_len) < 1)
236         return Char;
237
238     /*
239      * check to make sure the next character is equal to the first character
240      * if so, the sequence was <c>bs<c> indicating a bold character.
241      */
242     if (*ret_wc_len == len && *ret_wc == wide_c)
243       {
244         /*
245          * Do not set the return string ptr prior to this return.
246          * If the user specifies the same variable for both the str and
247          * ret_str_ptr, then we will overwrite it improperly if the
248          * sequence is not an italic or bold.
249          */
250         *ret_str_ptr = str + *ret_wc_len;
251         return Bold;
252       }
253
254     /*
255      * Check to see if the sequence is _bs<c> for italics.
256      * If so, take the next character for the ret_c (even if it
257      * is a multi-byte character). ret_wc, and ret_wc_len are
258      * already set from the mbtowc call. Move the ptr to after
259      * the processed character.
260      */
261     if (len == 1 && c == '_')
262       {
263         *ret_c       = *str;
264         *ret_str_ptr = str + *ret_wc_len;
265         return Italic;
266       }
267
268     /*
269      * Check to see if the sequence is <c>bs_ for italics.
270      * If so, return the given c for the ret_c (even if it
271      * is a multi-byte character). Set ret_wc and ret_wc_len
272      * to the passed in wide character and wide character len.
273      * Move the ptr to after the underscore.
274      */
275     if (*ret_wc_len == 1 && *str == '_')
276       {
277         *ret_c       = c;
278         *ret_str_ptr = str + *ret_wc_len;
279         *ret_wc      = wide_c;
280         *ret_wc_len  = len;
281         return Italic;
282       }
283     
284     /*
285      * failed all the tests.
286      * It could be a character followed by backspaces
287      * followed by another character (which would cause over-
288      * striking), but we don't know how to deal with this.
289      */
290     return Char;
291 }
292
293 /******************************************************************************
294  *
295  *  Formatting a man page is done based on the current input and the
296  *  current state of the processing. 
297  *
298  * Note:
299  *      Bold multi-byte characters have one backspace per byte. Therefore,
300  *              a two-byte character would be be followed by two backspaces
301  *              and the same two-bytes to indicate that the character is to
302  *              be a bold character.
303  *      Italic characters can either be preceded by a backspace/underline
304  *              or followed by a backspace/underline. I.E. _bsAB<bs_
305  *              would be an italic capitol A, a regular capital B and
306  *              an italic less than sign.
307  *      All backslashes and less than signs are output with a backslash
308  *              preceding them.
309  *
310  * The following characters have special meaning in the state table:
311  *      <c>     indicates a character.
312  *      <?>     indicates the next character in the sequence.
313  *      <_>     indicates an underscore character.
314  *      bs      indicates a backspace character.
315  *      nl      indicates a new-line character.
316  *
317  *  Cur State           Cur Sequence            Action          New State
318  * ------------------------------------------------------------------------
319  *  Char                <c>bs<c><?>             Bold -> buf     Bold
320  *                                              <c>  -> buf
321  *                                              lastChar = <c>
322  *                                              incr to <?>
323  *
324  *                      <_>bs<c><?>             Italic -> buf   Italic
325  *                                              <c>  -> buf
326  *                                              incr to <?>
327  *
328  *                      <c>bs<_><?>             Italic -> buf   Italic
329  *                                              <c>  -> buf
330  *                                              incr to <?>
331  *
332  *                      nl<?>                   dump buf        Char
333  *                                              incr to <?>
334  *
335  *                      <c><?>                  <c>  -> buf     Char
336  *                                              incr to <b>
337  *
338  *  Bold                bs<c><?>
339  *                      <c> = lastChar          skip to <?>     Bold
340  *
341  *                      nl<?>                   <\> -> buf      Char
342  *                                              dump buf
343  *                                              incr to <?>
344  *
345  *                      <c><?>                  <\> -> buf      BoldDone
346  *
347  *  BoldDone            <c>bs<c><?>             erase <\>       Bold
348  *                                              <c> -> buf
349  *                                              lastChar = <c>
350  *                                              incr to <?>
351  *
352  *                      <_>bs<c><?>             Italic -> buf   Italic
353  *                                              <c>  -> buf
354  *                                              incr to <?>
355  *
356  *                      <c>bs<_><?>             Italic -> buf   Italic
357  *                                              <c>  -> buf
358  *                                              incr to <?>
359  *
360  *                      nl<?>                   dump buf        Char
361  *                                              incr to <?>
362  *
363  *                      <c><?>                  <c> -> buf      Char
364  *                                              incr to <?>
365  *
366  *  Italic              <c>bs<c><?>             <\> -> buf      Char
367  *
368  *                      <_>bs<c><?>             <c> -> buf      Italic
369  *                                              incr to <?>
370  *
371  *                      <c>bs<_><?>             <c>  -> buf     Italic
372  *                                              incr to <?>
373  *
374  *                      bs<c><?>                erase lastChar  BoldItalic
375  *                                              Bold -> buf
376  *                                              <c>  -> buf
377  *                                              lastChar = <c>
378  *                                              incr to <?>
379  *
380  *                      nl<?>                   <\> -> buf      Char
381  *                                              dump buf
382  *                                              incr to <?>
383  *
384  *                      <c><?>                  </> -> buf      Char
385  *
386  *  BoldItalic          bs<c><?>                skip to <?>     BoldItalic
387  *
388  *                      <c><?>                  <\> -> buf      BoldItalicDone
389  *
390  *  BoldItalicDone      _bs<c>bs<c><?>  erase <\>       ItalicBold
391  *                                      <c> -> buf
392  *                                      lastChar = <c>
393  *                                      inc to <?>
394  *
395  *                      _bs<c><?>       <c> -> buf      Italic
396  *                                      lastChar = <c>
397  *                                      inc to <?>
398  *                                      
399  *                      <c><?>          <\> ->buf       Char
400  *                                      <c> -> buf
401  *                                      lastChar = <c>
402  *                                      inc to <?>
403  *
404  ******************************************************************************/
405 /******************************************************************************
406  * Function: RemoveToken
407  ******************************************************************************/
408 static  void
409 RemoveToken(
410     int           size,
411     char        **out_buf,
412     int          *out_size)
413 {
414     *out_size = *out_size - size;
415
416     if (size == 1 &&
417                 ((*out_buf)[*out_size] == '\\' || (*out_buf)[*out_size] == '<'))
418         *out_size = *out_size - 1;
419
420     (*out_buf)[*out_size] = '\0';
421 }
422
423 /*********************************************************************
424  * Function: WriteToken
425  *********************************************************************/
426 static  int
427 WriteToken(
428     char         *token,
429     int           size,
430     char        **out_buf,
431     int          *out_size,
432     int          *out_max )
433 {
434     char        *ptr = token;
435
436     return (_DtHelpCeAddStrToBuf(&ptr, out_buf, out_size, out_max, size, 128));
437 }
438
439 /*********************************************************************
440  * Function: WriteOutChar
441  *********************************************************************/
442 static  int
443 WriteOutChar(
444     int           last_len,
445     wchar_t       last_wc,
446     char          c,
447     char        **out_buf,
448     int          *out_size,
449     int          *out_max,
450     Boolean       flag)
451 {
452     char  *ptr;
453     char   temp[10];
454
455     if (last_len == 1 && c == '<')
456         ptr = "\\<";
457     else if (last_len == 1 && c == '\\')
458         ptr = "\\\\";
459     else
460       {
461         (void) wctomb (temp, last_wc);
462         temp[last_len] = '\0';
463         ptr            = temp;
464       }
465
466     /*  here is the conversion for the bold '+' followed by bold '_'
467         part of a hack to treat this special character sequence */
468     if (flag && c == '+')
469       ptr = "+/-";
470
471     return (_DtHelpCeAddStrToBuf(&ptr, out_buf, out_size, out_max,
472                                                         strlen(ptr), 128));
473 }
474
475 /*********************************************************************
476  * Function: FormatManPage
477  *
478  *    FormatManPage is the top entry point for formating man pages
479  *      into a form understood by a display area.
480  *
481  *********************************************************************/
482 static  int
483 FormatManPage(
484         VarHandle         my_vars,
485         BufFilePtr        in_file,
486         char             *in_buf,
487         int               in_size,
488         _DtHelpFontHints        *font_attr,
489         char            **out_buf,
490         int              *out_size,
491         int              *out_max )
492 {
493     int          italicCnt = 0;
494     int          result = 0;
495     int          cread;
496     int          lastLen;
497     int          checkLen;
498     int          retWCLen;
499     wchar_t      lastWC;
500     wchar_t      retWC;
501     char        *rloc = in_buf;
502     char        *retStrPtr;
503     char         c;
504     char         retC;
505     Boolean      flag = False;
506     enum State   newState;
507     enum State   state = Char;
508
509     cread = strlen (rloc);
510
511     do
512       {
513         /*
514          * while I can read information process; loop.
515          */
516         while (result != -1 && cread > 0)
517           {
518             /**
519              * check for the size of the character
520              **/
521             checkLen = mblen(rloc, MB_CUR_MAX);
522
523             /*
524              * if we hit a null character before we've run out of characters,
525              * we've got corrupt data.
526              */
527             if (checkLen == 0)
528                 return -1;
529
530             if (checkLen > 0)
531               {
532                 /*
533                  * check for end of line
534                  */
535                 if (checkLen == 1 && *rloc == '\n')
536                   {
537                     cread--;
538                     if (state == Bold || state == Italic)
539                         result = WriteToken(EndToken, EndTokenSize,
540                                                 out_buf, out_size, out_max);
541
542                     if (result != -1)
543                         result = _DtHelpCeAddCharToBuf (&rloc, out_buf,
544                                                 out_size, out_max, 128);
545                     if (result != -1)
546                       {
547                         result = __DtHelpCeProcessString(
548                                         my_vars, NULL,
549                                         _DtCvLITERAL,
550                                         ScanString,
551                                         *out_buf,
552                                         *out_size,
553                                         0,
554                                         False,
555                                         font_attr);
556                         *out_size = 0;
557                         (*out_buf)[0] = '\0';
558                         state = Char;
559                       }
560                   }
561                 else
562                   {
563                     switch (state)
564                       {
565                         case Char:
566                         case BoldDone:
567                         case BoldItalicDone:
568                                 /*
569                                  * get the character and wide character
570                                  * representation of the next character.
571                                  */
572                                 c        = *rloc;
573                                 lastLen  = mbtowc (&lastWC, rloc, MB_CUR_MAX);
574
575                                 /*
576                                  * skip past this character.
577                                  */
578                                 rloc     = rloc  + lastLen;
579                                 cread    = cread - lastLen;
580
581                                 /*
582                                  * Check ahead for bold or italic sequences
583                                  */
584                                 newState = GetNextState (c, lastWC, lastLen,
585                                                 rloc,
586                                                 &retC, &retWC, &retWCLen,
587                                                 &retStrPtr, &flag);
588
589                                 if (newState == Bold)
590                                   {
591                                     if (state == BoldDone)
592                                         RemoveToken(EndTokenSize, out_buf, out_size);
593                                     else
594                                         result = WriteToken(BoldToken,
595                                                         BoldTokenSize,
596                                                         out_buf, out_size,
597                                                         out_max);
598
599                                     /*
600                                      * skip the backspaces and the extra
601                                      * copy of the character.
602                                      */
603                                     cread = cread - (retStrPtr - rloc);
604                                     rloc  = retStrPtr;
605                                   }
606                                 else if (newState == Italic)
607                                   {
608                                     if (state != BoldItalicDone)
609                                         result = WriteToken(ItalicToken,
610                                                         ItalicTokenSize,
611                                                         out_buf, out_size,
612                                                         out_max);
613
614                                     /*
615                                      * skip the blanks after the current
616                                      * character plus the character after
617                                      * that. The returned wide character
618                                      * is the character that is to be
619                                      * italicized.
620                                      */
621                                     cread   = cread - (retStrPtr - rloc);
622                                     rloc    = retStrPtr;
623                                     c       = retC;
624                                     lastWC  = retWC;
625                                     lastLen = retWCLen;
626                                     italicCnt = 1;
627
628                                     if (state == BoldItalicDone &&
629                                         GetNextState (c, lastWC, lastLen, rloc,
630                                                 &retC, &retWC, &retWCLen,
631                                                 &retStrPtr, &flag) == Bold)
632                                       {
633                                         RemoveToken(EndTokenSize, out_buf, out_size);
634                                         newState = BoldItalic;
635                                       }
636                                   }
637                                 else if (state == BoldItalicDone)
638                                     result = WriteToken(EndToken, EndTokenSize,
639                                                         out_buf, out_size,
640                                                         out_max);
641
642                                 state = newState;
643
644
645                                 result = WriteOutChar(lastLen, lastWC, c,
646                                                 out_buf, out_size, out_max, flag);
647                                 break;
648
649                         case BoldItalic:
650                         case Bold:
651                                 if (GetNextState (c, lastWC, lastLen, rloc,
652                                                 &retC, &retWC, &retWCLen,
653                                                 &retStrPtr, &flag) == Bold)
654                                   {
655                                   /* skip backspaces and copy characters */
656                                     cread = cread - (retStrPtr - rloc);
657                                     rloc  = retStrPtr;
658                                   }
659                                 else
660                                   {
661                                     result = WriteToken(EndToken, EndTokenSize,
662                                                 out_buf, out_size, out_max);
663                                     if (state == BoldItalic)
664                                         state = BoldItalicDone;
665                                     else
666                                         state = BoldDone;
667                                   }
668                                 break;
669
670                         case Italic:
671                                 c = *rloc;
672                                 newState = GetNextState (c, lastWC, lastLen,
673                                                 rloc,
674                                                 &retC, &retWC, &retWCLen,
675                                                 &retStrPtr, &flag);
676
677                                 if (newState == Italic)
678                                   {
679                                     italicCnt++;
680                                     cread   = cread - (retStrPtr - rloc);
681                                     rloc    = retStrPtr;
682                                     c       = retC;
683                                     lastWC  = retWC;
684                                     lastLen = retWCLen;
685
686                                     result = WriteOutChar(lastLen, lastWC, c,
687                                                 out_buf, out_size, out_max, flag);
688                                   }
689                                 else if (italicCnt == 1 && lastWC == retWC
690                                                 && newState == Bold)
691                                   {
692                                     RemoveToken(lastLen, out_buf, out_size);
693
694                                     result  = WriteToken(BoldToken,
695                                                         BoldTokenSize,
696                                                         out_buf, out_size,
697                                                         out_max);
698
699                                     cread   = cread - (retStrPtr - rloc);
700                                     rloc    = retStrPtr;
701                                     c       = retC;
702                                     lastWC  = retWC;
703                                     lastLen = retWCLen;
704
705                                     result = WriteOutChar(lastLen, lastWC, c,
706                                                 out_buf, out_size, out_max, flag);
707
708                                     state = BoldItalic;
709                                   }
710                                 else
711                                   {
712                                     result    = WriteToken(EndToken,
713                                                         EndTokenSize,
714                                                         out_buf, out_size,
715                                                         out_max);
716                                     state     = Char;
717                                     italicCnt = 0;
718                                   }
719
720                                 break;
721                       }
722                   }
723
724                 if (cread < (3 * ((int) MB_CUR_MAX)) &&
725                                                 !feof (FileStream(in_file)))
726                     cread = 0;
727               }
728             else
729               {
730                 /**
731                  * if it is an invalid character - skip.
732                  * But be careful.
733                  * If this is the start of a multi-byte character,
734                  * I must save it and try again on the next read.
735                  **/
736                 if (cread < ((int) MB_CUR_MAX))
737                     cread = 0;
738                 else
739                   {
740                     /*
741                      * otherwise we've got corrupt data.
742                      */
743                     return -1;
744                   }
745               }
746           }
747         if (result != -1 && !feof(FileStream(in_file)))
748           {
749             if (_DtHelpCeGetNxtBuf (in_file, in_buf, &rloc, in_size) == -1)
750                 result = -1;
751
752             if (result != -1)
753                 cread = strlen (rloc);
754           }
755       } while (result != -1 && cread > 0);
756
757     return(result);
758
759 } /* End FormatManPage */
760
761 /******************************************************************************
762  *
763  * Public Functions
764  *
765  *****************************************************************************/
766 /*********************************************************************
767  * Function: _DtHelpFormatManPage
768  *
769  *    _DtHelpFormatManPage formats a man page
770  *      into a form understood by a display area.
771  *
772  *********************************************************************/
773 int
774 _DtHelpFormatManPage(
775         XtPointer        client_data,
776         char            *man_spec,
777         XtPointer       *ret_handle)
778 {
779     int      result = -1;
780     FILE    *myFile;
781     int      writeBufSize = 0;
782     int      writeBufMax  = 0;
783     char    *ptr;
784     char    *writeBuf = NULL;
785     char     readBuf[BUFSIZ];
786     _DtHelpFontHints    fontAttr;
787     VarHandle  myVars;
788     _DtCvTopicInfo *topicStruct;
789     BufFilePtr myBufFile;
790     static char manString[]     = "man ";
791     static char devNullString[] = " 2>/dev/null";
792     _DtCvTopicPtr topic = NULL;
793     DtHelpDispAreaStruct *pDAS     = (DtHelpDispAreaStruct *) client_data;
794     _FrmtUiInfo           myUiInfo = { NULL, NULL, NULL, NULL, NULL, NULL, 0, 0, 0, 1, False };
795
796     /*
797      * fill out the ui information
798      */
799     myUiInfo.load_font    = _DtHelpDAResolveFont;
800     myUiInfo.client_data  = (_DtCvPointer) pDAS;
801     myUiInfo.avg_char     = (int)(pDAS->charWidth / 10 +
802                                         ((pDAS->charWidth % 10) ? 1 : 0));
803     myUiInfo.nl_to_space  = pDAS->nl_to_space;
804
805     /*
806      * pre-append the man command to man specification
807      */
808     ptr = (char *) malloc(sizeof(manString) + strlen(man_spec) +
809                                                    sizeof(devNullString) - 1);
810     if (!ptr)
811         return -1;
812     strcpy (ptr, manString);
813     strcat (ptr, man_spec);
814     strcat (ptr, devNullString);
815
816     myFile = popen(ptr, "r");
817
818     /*
819      * free the man command
820      */
821     free (ptr);
822
823     /*
824      * check for problems
825      */
826     if (!myFile) /* couldn't create man(1) process */
827         return -1;
828
829     /*
830      * make sure we don't try to read compressed.
831      */
832     myBufFile = _DtHelpCeCreatePipeBufFile(myFile);
833     if (myBufFile == NULL)
834       {
835         (void) pclose(myFile); /* don't check for error, it was popen'd */
836         return -1;
837       }
838
839     /*
840      * get the font quark list - but force to mono-space
841      */
842     _DtHelpCeCopyDefFontAttrList (&fontAttr);
843     fontAttr.spacing  = _DtHelpFontSpacingMono;
844     _DtHelpCeXlateOpToStdLocale(DtLCX_OPER_SETLOCALE,setlocale(LC_CTYPE,NULL),
845                         NULL, &(fontAttr.language), &(fontAttr.char_set));
846
847     myVars = __DtHelpCeSetUpVars(fontAttr.language, fontAttr.char_set, &myUiInfo);
848     if (myVars == NULL)
849       {
850         free(fontAttr.language);
851         free(fontAttr.char_set);
852         _DtHelpCeBufFileClose (myBufFile, True);
853         return -1;
854       }
855
856     readBuf[0] = '\0';
857     ptr        = readBuf;
858
859     result = _DtHelpCeGetNxtBuf (myBufFile, readBuf, &ptr, BUFSIZ);
860     if (result > 0)
861          result = FormatManPage (myVars, myBufFile,
862                                      readBuf,
863                                      BUFSIZ,
864                                      &fontAttr,
865                                      &writeBuf,
866                                      &writeBufSize,
867                                      &writeBufMax );
868
869     if ((result != -1) && writeBufSize)
870         result = __DtHelpCeProcessString(myVars, NULL, _DtCvLITERAL,
871                         ScanString, writeBuf, writeBufSize,
872                         0, False, &fontAttr);
873
874     /*
875      * free the buffer
876      */
877     if (writeBuf)
878         free (writeBuf);
879
880     /*
881      * close the pipe
882      */
883     _DtHelpCeBufFileClose (myBufFile, True);
884
885     /*
886      * clean up the last segment.
887      */
888     if (result != -1)
889         __DtHelpCeGetParagraphList (myVars, True, _DtCvLITERAL, &topic);
890
891     topicStruct = (_DtCvTopicInfo *) (topic);
892
893    /*
894     * did we have any paragraphs to format?
895     */
896    if ((topic != NULL && NULL == topicStruct->seg_list)
897                 || NULL == _DtCvContainerListOfSeg(topicStruct->seg_list))
898       {
899         _DtHelpFreeSegments(topicStruct->seg_list, _DtCvFALSE,
900                                                 NULL, (_DtCvPointer) pDAS);
901         free ((char *) topicStruct);
902         topic = NULL;
903         errno = ENOENT; /* we'll just assume no man page existed */
904         result = -1;
905       }
906
907     free(fontAttr.language);
908     free(fontAttr.char_set);
909     free(myVars);
910
911     *ret_handle = (_DtCvPointer) topic;
912
913     return (result);
914
915 }  /* End _DtHelpFormatManPage */