groff
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Groff] Groff pipeline plumbing problem


From: Gaius Mulley
Subject: Re: [Groff] Groff pipeline plumbing problem
Date: Sat, 29 Dec 2001 19:42:39 +0000

Hi,

here is the fix (with the previous fixes) to the pipeline problem.
It was related to the groff -Z option (the -Z was omitted).
To reduce the size of the patch I've not included the newfiles
which would go in the doc directory (96k of images). Feel
free to email me, if you want and I'll send them to you direct.
Bernd I've changed the homepage.ms slightly - what do you think?

hope this helps,

Gaius


*** groff-cvs/src/preproc/html/pre-html.cc      Mon Dec 10 22:00:54 2001
--- groff-html/src/preproc/html/pre-html.cc     Sat Dec 29 19:09:53 2001
***************
*** 57,71 ****
  #include "pushback.h"
  #include "html-strings.h"
  
! #define DEFAULT_IMAGE_RES         80   // 80 pixels per inch resolution
! #ifdef PAGEA4
! #  define DEFAULT_VERTICAL_OFFSET  0   // DEFAULT_VERTICAL_OFFSET/72 of an 
inch
! #else
! #  define DEFAULT_VERTICAL_OFFSET 50   // DEFAULT_VERTICAL_OFFSET/72 of an 
inch
! #endif
! #define IMAGE_BOARDER_PIXELS       2
  #define MAX_WIDTH                  8   // inches
  #define INLINE_LEADER_CHAR      '\\'
  
  #define TRANSPARENT  "-background white -transparent white"
  
--- 57,71 ----
  #include "pushback.h"
  #include "html-strings.h"
  
! #define DEFAULT_IMAGE_RES        100   // number of pixels per inch resolution
! #define DEFAULT_VERTICAL_OFFSET    0   // DEFAULT_VERTICAL_OFFSET/72 of an 
inch
! #define IMAGE_BOARDER_PIXELS       0
  #define MAX_WIDTH                  8   // inches
  #define INLINE_LEADER_CHAR      '\\'
+ #define A4_LENGTH             841890   // taken from devps/Makefile.sub
+ #define LETTER_LENGTH         792000   // taken from devps/Makefile.sub
+ #define A4_OFFSET                  0
+ #define LETTER_OFFSET             50   // 50/72 of an inch
  
  #define TRANSPARENT  "-background white -transparent white"
  
***************
*** 100,109 ****
  static char *imagePageStem  = NULL;             // stem of all files 
containing page images
  static char *image_device   = "pnmraw";
  static int   image_res      = DEFAULT_IMAGE_RES;
! static int   vertical_offset= DEFAULT_VERTICAL_OFFSET;
  static char *image_template = NULL;             // image template filename
  static int   troff_arg      = 0;                // troff arg index
  static char *image_dir      = NULL;             // user specified image 
directory
  #if defined(DEBUGGING)
  static int   debug          = FALSE;
  static char *troffFileName  = NULL;             // output of pre-html output 
which is sent to troff -Tps
--- 100,110 ----
  static char *imagePageStem  = NULL;             // stem of all files 
containing page images
  static char *image_device   = "pnmraw";
  static int   image_res      = DEFAULT_IMAGE_RES;
! static int   vertical_offset= 0;
  static char *image_template = NULL;             // image template filename
  static int   troff_arg      = 0;                // troff arg index
  static char *image_dir      = NULL;             // user specified image 
directory
+ static char *gsPaper        = NULL;             // the paper size that gs 
must use
  #if defined(DEBUGGING)
  static int   debug          = FALSE;
  static char *troffFileName  = NULL;             // output of pre-html output 
which is sent to troff -Tps
***************
*** 139,155 ****
   *  get_resolution - returns the postscript resolution from devps/DESC
   */
  
! static int get_resolution (void)
  {
    char *pathp;
    FILE *f;
!   unsigned long int res;
    int n;
    int c;
    f = font_path.open_file("devps/DESC", &pathp);
    if (f == 0) sys_fatal("fopen");
    while (1) {
!     n = fscanf(f, " res %lu", &res);
      if (n < 0) sys_fatal("EOF");
      if (n >= 1) {
        fclose(f);
--- 140,156 ----
   *  get_resolution - returns the postscript resolution from devps/DESC
   */
  
! static unsigned int get_resolution (void)
  {
    char *pathp;
    FILE *f;
!   unsigned int res;
    int n;
    int c;
    f = font_path.open_file("devps/DESC", &pathp);
    if (f == 0) sys_fatal("fopen");
    while (1) {
!     n = fscanf(f, " res %u", &res);
      if (n < 0) sys_fatal("EOF");
      if (n >= 1) {
        fclose(f);
***************
*** 161,166 ****
--- 162,203 ----
  }
  
  /*
+  *  get_papersize - returns an integer determining the paper length from 
devps/DESC
+  */
+ 
+ static int get_papersize (void)
+ {
+   char *pathp;
+   FILE *f;
+   int res;
+   int n;
+   int c;
+   f = font_path.open_file("devps/DESC", &pathp);
+   if (f == 0) sys_fatal("fopen");
+   while (1) {
+     n = fscanf(f, " paperlength %d", &res);
+     if (n < 0) sys_fatal("EOF");
+     if (n >= 1) {
+       fclose(f);
+       return res;
+     }
+     while (( c = getc(f) ) != '\n')
+       if (c == EOF) sys_fatal("EOF");
+   }
+ }
+ 
+ /*
+  *  determine_vertical_offset - works out the default vertical offset from
+  *                              the page length
+  */
+ 
+ static void determine_vertical_offset (void)
+ {
+   vertical_offset = ((A4_LENGTH-get_papersize())*72)/postscriptRes;
+   gsPaper = "-sPAPERSIZE=a4";
+ }
+ 
+ /*
   *  html_system - a wrapper for system()
   */
  
***************
*** 734,742 ****
    }
  
    s = make_message("echo showpage | "
!                  "gs%s -q -dSAFER -sDEVICE=%s -r%d "
                   "-sOutputFile=%s/%%d %s -",
                   EXE_EXT,
                   image_device,
                   image_res,
                   imagePageStem,
--- 771,781 ----
    }
  
    s = make_message("echo showpage | "
!                  "gs%s %s -q -dSAFER -sDEVICE=%s -r%d "
!                  "-dTextAlphaBits=4 -dGraphicsAlphaBits=4 "
                   "-sOutputFile=%s/%%d %s -",
                   EXE_EXT,
+                  gsPaper,
                   image_device,
                   image_res,
                   imagePageStem,
***************
*** 812,819 ****
      int  y1 = max((image_res*vertical_offset/72)+min(i->Y1, 
i->Y2)*image_res/postscriptRes-IMAGE_BOARDER_PIXELS, 0);
      int  x2 = max(i->X1, 
i->X2)*image_res/postscriptRes+1*IMAGE_BOARDER_PIXELS;
      int  y2 = (image_res*vertical_offset/72)+(max(i->Y1, 
i->Y2)*image_res/postscriptRes)+1+IMAGE_BOARDER_PIXELS;
! 
!     s = make_message("pnmcut%s %d %d %d %d < %s/%d | pnmcrop | pnmtopng%s %s 
> %s \n",
                     EXE_EXT,
                     x1, y1, x2-x1+1, y2-y1+1,
                     imagePageStem,
--- 851,857 ----
      int  y1 = max((image_res*vertical_offset/72)+min(i->Y1, 
i->Y2)*image_res/postscriptRes-IMAGE_BOARDER_PIXELS, 0);
      int  x2 = max(i->X1, 
i->X2)*image_res/postscriptRes+1*IMAGE_BOARDER_PIXELS;
      int  y2 = (image_res*vertical_offset/72)+(max(i->Y1, 
i->Y2)*image_res/postscriptRes)+1+IMAGE_BOARDER_PIXELS;
!     s = make_message("pnmcut%s %d %d %d %d < %s/%d | pnmcrop -quiet | 
pnmtopng%s %s > %s \n",
                     EXE_EXT,
                     x1, y1, x2-x1+1, y2-y1+1,
                     imagePageStem,
***************
*** 1022,1028 ****
    if (new_argv == NULL)
      sys_fatal("malloc");
  
!   while (i<troff_arg) {
      new_argv[i] = argv[i];
      i++;
    }
--- 1060,1066 ----
    if (new_argv == NULL)
      sys_fatal("malloc");
  
!   if (argc > 0) {
      new_argv[i] = argv[i];
      i++;
    }
***************
*** 1207,1224 ****
    char *troff_name = new char[strlen(command_prefix) + strlen("troff") + 1];
    strcpy(troff_name, command_prefix);
    strcat(troff_name, "troff");
!   int c;
    static const struct option long_options[] = {
      { "help", no_argument, 0, CHAR_MAX + 1 },
      { "version", no_argument, 0, 'v' },
      { NULL, 0, 0, 0 }
    };
!   while ((c = getopt_long(argc, argv, "+o:i:I:D:F:vdhlrn", long_options, 
NULL))
         != EOF)
      switch(c) {
      case 'v':
        printf("GNU pre-grohtml (groff) version %s\n", Version_string);
        exit(0);
      case 'D':
        image_dir = optarg;
        break;
--- 1245,1265 ----
    char *troff_name = new char[strlen(command_prefix) + strlen("troff") + 1];
    strcpy(troff_name, command_prefix);
    strcat(troff_name, "troff");
!   int c, i;
    static const struct option long_options[] = {
      { "help", no_argument, 0, CHAR_MAX + 1 },
      { "version", no_argument, 0, 'v' },
      { NULL, 0, 0, 0 }
    };
!   while ((c = getopt_long(argc, argv, "+o:i:I:D:F:vbdhlrn", long_options, 
NULL))
         != EOF)
      switch(c) {
      case 'v':
        printf("GNU pre-grohtml (groff) version %s\n", Version_string);
        exit(0);
+     case 'b':
+       // handled by post-grohtml (set background color to white)
+       break;
      case 'D':
        image_dir = optarg;
        break;
***************
*** 1233,1238 ****
--- 1274,1280 ----
        break;
      case 'o':
        vertical_offset = atoi(optarg);
+       gsPaper = "";  // do not specify the paper size now
        break;
      case 'd':
  #if defined(DEBUGGING)
***************
*** 1254,1265 ****
        break;
      }
  
!   while (optind < argc) {
!     if (strcmp(argv[optind], troff_name) == 0)
!       troff_arg = optind;
!     else if (argv[optind][0] != '-')
!       return optind;
!     optind++;
    }
    a_delete troff_name;
  
--- 1296,1308 ----
        break;
      }
  
!   i = optind;
!   while (i < argc) {
!     if (strcmp(argv[i], troff_name) == 0)
!       troff_arg = i;
!     else if (argv[i][0] != '-')
!       return i;
!     i++;
    }
    a_delete troff_name;
  
***************
*** 1322,1329 ****
    int found=0;
    int ok=1;
  
-   i = scanArguments(argc, argv);
    postscriptRes = get_resolution();
    checkImageDir();
    makeFileName();
    while (i < argc) {
--- 1365,1373 ----
    int found=0;
    int ok=1;
  
    postscriptRes = get_resolution();
+   determine_vertical_offset();
+   i = scanArguments(argc, argv);
    checkImageDir();
    makeFileName();
    while (i < argc) {
*** groff-cvs/src/devices/grohtml/post-html.cc  Thu Dec  6 10:03:22 2001
--- groff-html/src/devices/grohtml/post-html.cc Fri Dec 28 15:22:00 2001
***************
*** 74,79 ****
--- 74,80 ----
  static int simple_anchors = FALSE;                   /* default to anchors 
with heading text     */
  static int manufacture_headings = FALSE;             /* default is to use the 
Hn html headings,  */
                                                       /* rather than 
manufacture our own.         */
+ static color *default_background = NULL;             /* has user requested 
initial bg color?     */
  
  
  /*
***************
*** 1075,1086 ****
  
    int     has_been_written;
    int     has_been_found;
    string  text;
  };
  
  
  title_desc::title_desc ()
!   : has_been_written(FALSE), has_been_found(FALSE)
  {
  }
  
--- 1076,1088 ----
  
    int     has_been_written;
    int     has_been_found;
+   int     with_h1;
    string  text;
  };
  
  
  title_desc::title_desc ()
!   : has_been_written(FALSE), has_been_found(FALSE), with_h1(FALSE)
  {
  }
  
***************
*** 1994,1999 ****
--- 1996,2006 ----
      do_center(a);
    } else if (strncmp(t, ".tl", 3) == 0) {
      supress_sub_sup = TRUE;
+     title.with_h1 = TRUE;
+     do_title();
+   } else if (strncmp(t, ".html-tl", 8) == 0) {
+     supress_sub_sup = TRUE;
+     title.with_h1 = FALSE;
      do_title();
    } else if (strncmp(t, ".fi", 3) == 0) {
      do_fill(TRUE);
***************
*** 2360,2365 ****
--- 2367,2373 ----
    switch (code) {
  
    case 'l':
+ # if 0
      if (np == 2) {
        page_contents->add_line(&sbuf_style,
                              line_number,
***************
*** 2367,2372 ****
--- 2375,2381 ----
      } else {
        error("2 arguments required for line");
      }
+ # endif
      break;
    case 't':
      {
***************
*** 2435,2441 ****
    indentation(0),
    prev_indent(0),
    line_number(0),
!   background(NULL)
  {
  #if defined(DEBUGGING)
    file_list.add_new_file(stdout);
--- 2444,2450 ----
    indentation(0),
    prev_indent(0),
    line_number(0),
!   background(default_background)
  {
  #if defined(DEBUGGING)
    file_list.add_new_file(stdout);
***************
*** 2617,2625 ****
        html.put_string("</title>").nl().nl();
      } else {
        title.has_been_written = TRUE;
!       html.put_string("<h1 align=center>");
!       html.put_string(title.text);
!       html.put_string("</h1>").nl().nl();
      }
    } else if (in_head) {
      // place empty title tags to help conform to `tidy'
--- 2626,2636 ----
        html.put_string("</title>").nl().nl();
      } else {
        title.has_been_written = TRUE;
!       if (title.with_h1) {
!       html.put_string("<h1 align=center>");
!       html.put_string(title.text);
!       html.put_string("</h1>").nl().nl();
!       }
      }
    } else if (in_head) {
      // place empty title tags to help conform to `tidy'
***************
*** 2821,2833 ****
      { "version", no_argument, 0, 'v' },
      { NULL, 0, 0, 0 }
    };
!   while ((c = getopt_long(argc, argv, "o:i:I:D:F:vdhlrn", long_options, NULL))
         != EOF)
      switch(c) {
      case 'v':
        printf("GNU post-grohtml (groff) version %s\n", Version_string);
        exit(0);
        break;
      case 'F':
        font::command_line_font_dir(optarg);
        break;
--- 2832,2849 ----
      { "version", no_argument, 0, 'v' },
      { NULL, 0, 0, 0 }
    };
!   while ((c = getopt_long(argc, argv, "o:i:I:D:F:vbdhlrn", long_options, 
NULL))
         != EOF)
      switch(c) {
      case 'v':
        printf("GNU post-grohtml (groff) version %s\n", Version_string);
        exit(0);
        break;
+     case 'b':
+       // set background color to white
+       default_background = new color;
+       default_background->set_rgb(1.0, 1.0, 1.0);
+       break;
      case 'F':
        font::command_line_font_dir(optarg);
        break;
***************
*** 2882,2887 ****
  
  static void usage(FILE *stream)
  {
!   fprintf(stream, "usage: %s [-vlnh] [-D dir] [-I image_stem] [-F dir] [files 
...]\n",
          program_name);
  }
--- 2898,2903 ----
  
  static void usage(FILE *stream)
  {
!   fprintf(stream, "usage: %s [-vblnh] [-D dir] [-I image_stem] [-F dir] 
[files ...]\n",
          program_name);
  }
*** groff-cvs/src/devices/grohtml/grohtml.man   Thu Dec  6 10:03:22 2001
--- groff-html/src/devices/grohtml/grohtml.man  Thu Dec 27 18:08:08 2001
***************
*** 81,86 ****
--- 81,89 ----
  option.
  .SH OPTIONS
  .TP
+ .B -b
+ initialize the background color to white.
+ .TP
  .B -h
  Generates section and number headings by using
  .BR <B> .\|.\|. </B>
***************
*** 113,120 ****
  .TP
  .BI \-i resolution
  Select the resolution for all images.
! By default this is 80 pixels per inch.
! Example: -i100 indicates 100 pixels per inch.
  .TP
  .BI \-I stem
  Determine the image stem name.
--- 116,123 ----
  .TP
  .BI \-i resolution
  Select the resolution for all images.
! By default this is 100 pixels per inch.
! Example: -i200 indicates 200 pixels per inch.
  .TP
  .BI \-I stem
  Determine the image stem name.
*** groff-cvs/src/roff/troff/node.cc    Fri Oct  5 15:12:24 2001
--- groff-html/src/roff/troff/node.cc   Thu Dec 27 13:55:12 2001
***************
*** 967,974 ****
    int height = tf->get_char_height(ci).to_units();
    int width = tf->get_width(ci).to_units()
              + tf->get_italic_correction(ci).to_units();
    check_output_limits(output_hpos, output_vpos - height);
!   check_output_limits(output_hpos + width, output_vpos);
  }
  
  void troff_output_file::put_char_width(charinfo *ci, tfont *tf, hunits w,
--- 967,975 ----
    int height = tf->get_char_height(ci).to_units();
    int width = tf->get_width(ci).to_units()
              + tf->get_italic_correction(ci).to_units();
+   int depth = tf->get_char_depth(ci).to_units();
    check_output_limits(output_hpos, output_vpos - height);
!   check_output_limits(output_hpos + width, output_vpos + depth);
  }
  
  void troff_output_file::put_char_width(charinfo *ci, tfont *tf, hunits w,
*** groff-cvs/tmac/www.tmac     Thu Dec  6 10:03:24 2001
--- groff-html/tmac/www.tmac    Thu Dec 27 19:04:30 2001
***************
*** 166,171 ****
--- 166,228 ----
  .   HTML-TAG ".no-auto-rule"
  ..
  .\"
+ .\"  end-nowhere - end of input trap called to finish diversion.
+ .\"
+ .de end-nowhere
+ .   di
+ ..
+ .\"
+ .\"  HTML-TL - generate a HTML title only
+ .\"            which differs from the -ms .TL which generates
+ .\"            both a HTML title and a H1 heading.
+ .\"            This is useful when an author wishes to use a HTML title
+ .\"            as search engine fodder but use a graphic in the document.
+ .\"
+ .de HTML-TL
+ .   HTML-TAG ".html-tl"
+ .   if !'\*(.T'html' \{\
+ .      di nowhere
+ .      it 2 end-nowhere
+ .   \}
+ ..
+ .ds HTML-LEVEL1     \(bu\[space]\[space]
+ .ds HTML-LEVEL2     \(sq\[space]\[space]
+ .ds HTML-LEVEL3     \(ci\[space]\[space]
+ .nr address@hidden 0
+ .de PUSH-LEVEL
+ .    nr address@hidden  address@hidden
+ .    if address@hidden>3 address@hidden "too many levels of indentation 
(address@hidden)"
+ ..
+ .de POP-LEVEL
+ .    if address@hidden address@hidden "trying to terminate a list which does 
not exist"
+ .    nr address@hidden  address@hidden
+ .    HTML  "</ul>"
+ ..
+ .de UL-BEGIN
+ .   PUSH-LEVEL
+ .   ie '\*(.T'html' .HTML "<ul>"
+ .   el \{\
+ .      br
+ .      in +(u;\w'address@hidden)'
+ .   \}
+ ..
+ .de UL-END
+ .   ie '\*(.T'html' .HTML "</ul>"
+ .   el \{\
+ .      br
+ .      in -(u;\w'address@hidden)'
+ .   \}
+ .   POP-LEVEL
+ ..
+ .de LI
+ .   ie '\*(.T'html' .HTML "<li>"
+ .   el \{\
+ .      br
+ .      ti -(u;\w'address@hidden')
+ address@hidden
+ .   \}
+ ..
+ .\"
  .\" supplimentary macros used by other macro sets
  .\"
  .\" here are some tags specially for -Tps or -Thtml when invoked by pre-html
*** groff-cvs/tmac/html.tmac    Thu Dec  6 10:03:24 2001
--- groff-html/tmac/html.tmac   Thu Dec 27 13:22:02 2001
***************
*** 531,536 ****
  .defcolor yellow rgb #ffff00
  .defcolor yellow1 rgb #fffc17
  .defcolor yellowgreen rgb #52d017
! .\" background color defaults to white and glyph color to black
! \M[white]\m[black]\c
  .\" end of file, make sure this is the last line
--- 531,536 ----
  .defcolor yellow rgb #ffff00
  .defcolor yellow1 rgb #fffc17
  .defcolor yellowgreen rgb #52d017
! .\" default glyph color to black (leave the background color alone)
! \m[black]\c
  .\" end of file, make sure this is the last line
*** groff-cvs/src/libs/libgroff/tmpfile.cc      Sun Aug 19 22:32:28 2001
--- groff-html/src/libs/libgroff/tmpfile.cc     Fri Dec 28 11:15:14 2001
***************
*** 140,146 ****
  
  static void add_tmp_file(const char *name)
  {
!   char *s = new char[strlen(name)];
    strcpy(s, name);
    xtmpfile_list *x = new xtmpfile_list(s);
    x->next = xtmpfiles_to_delete;
--- 140,146 ----
  
  static void add_tmp_file(const char *name)
  {
!   char *s = new char[strlen(name)+1];  // +1 to ensure space for the nul
    strcpy(s, name);
    xtmpfile_list *x = new xtmpfile_list(s);
    x->next = xtmpfiles_to_delete;
*** groff-cvs/doc/Makefile      Tue Sep 11 22:40:36 2001
--- groff-html/doc/Makefile     Sat Dec 29 19:08:36 2001
***************
*** 68,74 ****
        GROFF_BIN_PATH=$(groff_bin_path); \
        export GROFF_BIN_PATH; \
        sed -e "s;@VERSION@;$(version)$(revision);" $< \
!       | $(GROFF) -P-I`echo $< | sed -e 's|.ms$$||'` \
                   -P-D -Pimg -Thtml $(FFLAG) -U -ms >$@
  
  .ms.ascii:
--- 68,74 ----
        GROFF_BIN_PATH=$(groff_bin_path); \
        export GROFF_BIN_PATH; \
        sed -e "s;@VERSION@;$(version)$(revision);" $< \
!       | $(GROFF) -P-b -P-I`echo $< | sed -e 's|.ms$$||'` \
                   -P-D -Pimg -Thtml $(FFLAG) -U -ms >$@
  
  .ms.ascii:
***************
*** 92,97 ****
--- 92,102 ----
  
  groff: groff.texinfo
        makeinfo groff.texinfo
+ 
+ gnubw.eps: gnubw-master-image
+       pngtopnm gnubw-master-image | pnmscale 0.1 | pnmtops -noturn > gnubw.eps
+ 
+ homepage.html: gnubw.eps
  
  install:
  
*** groff-cvs/doc/homepage.ms   Sun Jun 24 14:03:27 2001
--- groff-html/doc/homepage.ms  Sat Dec 29 19:16:29 2001
***************
*** 2,19 ****
  .\" with groff.
  .\"
  .\"
! .\" To make it work with other output devices also, we include arkup.tmac
  .\" directly.
  .mso www.tmac
! .\"
! .LP
! .\"
! .\"  set a longer line than the default as we have some long ftp addresses
! .\"  which groff cannot split
! .nr LL 7i
! .TL
  Home of Groff (GNU Troff).
! .sp 1i
  .LP
  GNU Troff
  .URL (Groff) http://groff.ffii.org/
--- 2,22 ----
  .\" with groff.
  .\"
  .\"
! .\" To make it work with other output devices also, we include www.tmac
  .\" directly.
  .mso www.tmac
! .defcolor darkred rgb 0.65f 0.1f 0.2f
! .defcolor darkgreen rgb 0.1f 0.5f 0.2f
! .defcolor darkblue rgb 0.1f 0.2f 0.6f
! .ds GNU \m[darkred]G\mP\m[darkgreen]N\mP\m[darkblue]U\mP
! .nr LL 8i
! .HTML-TL
  Home of Groff (GNU Troff).
! .HTML-IMAGE-LEFT
! .PSPIC -L gnubw.eps 1i 1i
! \v'-0.5i'\h'1.0i'\s[40]\*[GNU] Troff\s0
! .HTML-IMAGE-END
! .sp
  .LP
  GNU Troff
  .URL (Groff) http://groff.ffii.org/
***************
*** 24,29 ****
--- 27,33 ----
  .URL FFII http://ffii.org/ .
  .br
  .LINE
+ .LINKS
  .LP
  Groff (GNU Troff) is a document processor which reads plain text mixed with
  formatting commands and produces formatted output.

reply via email to

[Prev in Thread] Current Thread [Next in Thread]