home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / mail / pp / pp-6.0 / Format / ascii2fax / hdr2fax.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-12-18  |  17.5 KB  |  892 lines

  1. /* hdr2fax.c: convert 822 hdr to fax image */
  2.  
  3. # ifndef lint
  4. static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Format/ascii2fax/RCS/hdr2fax.c,v 6.0 1991/12/18 20:15:19 jpo Rel $";
  5. # endif
  6.  
  7. /*
  8.  * $Header: /xtel/pp/pp-beta/Format/ascii2fax/RCS/hdr2fax.c,v 6.0 1991/12/18 20:15:19 jpo Rel $
  9.  *
  10.  * $Log: hdr2fax.c,v $
  11.  * Revision 6.0  1991/12/18  20:15:19  jpo
  12.  * Release 6.0
  13.  *
  14.  */
  15. #include     <stdio.h>
  16. #include     "util.h"
  17. #include    <isode/cmd_srch.h>
  18. #include    "or.h"
  19. #include     "IOB-types.h"
  20. #include    "table.h"
  21. #include    "fonts.h"
  22. #include    "ap.h"
  23. #include    "pg_sizes.h"
  24.  
  25. extern BitMap    new_bitmap(), file2bitmap();
  26.  
  27. char        *myname;
  28. static char    buffer[BUFSIZ], buf2[BUFSIZ];
  29. static char    *read822hdr();
  30. static int    draw2Str(), drawStr();
  31. char        *loc_telfax_number;
  32. char        *loc_company;
  33. char        *postscript;
  34. char        *outmta;
  35.  
  36. #define    OPT_FROM    1
  37. #define    OPT_TO        2
  38. #define OPT_SUBJECT    3
  39. #define OPT_TABLE    4
  40. #define OPT_OUTMTA    6
  41.  
  42. CMD_TABLE    tbl_options [] = { /* hdr2fax commandline options */
  43.     "-from",    OPT_FROM,
  44.     "-to",        OPT_TO,
  45.     "-subject",    OPT_SUBJECT,
  46.     "-table",    OPT_TABLE,
  47.     "-outmta",    OPT_OUTMTA,
  48.     0,        -1
  49.     };
  50.  
  51. char    *to, 
  52.     *from, 
  53.     *subject, 
  54.     *page, 
  55.     *display_str,
  56.     *date = NULLCP,
  57.     *from822 = NULLCP;
  58. int    x_start, 
  59.     y_start,
  60.     page_x,
  61.     page_y;
  62. PPFontPtr    large = NULL, 
  63.         bold = NULL,
  64.         norm = NULL;
  65.  
  66. double    res = 3.85; /*7.7;*/    /* pixels/lines per mm in y direction */
  67. double    xres = FAX_WIDTH_LINES/FAX_WIDTH;    /* pixels per mm in x direct */
  68. int    tab;
  69. Table    *table = NULLTBL;
  70.  
  71. main(argc, argv)
  72. int    argc;
  73. char    **argv;
  74. {
  75.     struct type_IOB_G3FacsimileBodyPart    *p2;
  76.     BitMap    coversheet;
  77.  
  78.     sys_init(argv[0]);
  79.     argv++;
  80.     while (*argv != NULL) {
  81.         switch (cmd_srch(*argv,tbl_options)) {
  82.             case OPT_FROM:
  83.             if (*(argv+1) == NULLCP)
  84.                 fprintf(stderr,
  85.                        "no sender given with flag %s", *argv);
  86.             else {
  87.                 argv++;
  88.                 from = *argv;
  89.             }
  90.             break;
  91.             
  92.             case OPT_TO:
  93.             if (*(argv+1) == NULLCP)
  94.                 fprintf(stderr,
  95.                        "no recipient given with flag %s", *argv);
  96.             else {
  97.                 argv++;
  98.                 to = *argv;
  99.             }
  100.             break;
  101.  
  102.             case OPT_OUTMTA:
  103.             if (*(argv+1) == NULLCP)
  104.                 fprintf(stderr,
  105.                        "no recipient given with flag %s", *argv);
  106.             else {
  107.                 argv++;
  108.                 if (lexequ(*argv, "none") != 0)
  109.                     outmta = *argv;
  110.             }
  111.             break;
  112.  
  113.             case OPT_SUBJECT:
  114.             if (*(argv+1) == NULLCP)
  115.                 fprintf(stderr,
  116.                        "no subject given with flag %s", *argv);
  117.             else {
  118.                 argv++;
  119.                 subject = *argv;
  120.             }
  121.             break;
  122.             
  123.             case OPT_TABLE:
  124.             if (*(argv+1) == NULLCP)
  125.                 fprintf(stderr,
  126.                        "no table given with flag %s", *argv);
  127.             else {
  128.                 argv++;
  129.                 if (lexequ(*argv, "none") != 0
  130.                     && ((table = tb_nm2struct (*argv)) == NULLTBL)) {
  131.                     fprintf(stderr,
  132.                         "Cannot initialise table '%s'\n", *argv);
  133.                         exit (1);
  134.                     }
  135.             }
  136.             break;
  137.  
  138.             default:
  139.             fprintf(stderr,
  140.                    "unknown option '%s'", *argv);
  141.             exit(1);
  142.         }
  143.         argv++;
  144.     }
  145.  
  146.     if (table == NULLTBL) {
  147.         fprintf(stderr,
  148.             "No table passed over in info field for filter '%s'",
  149.             argv[0]);
  150.         exit(1);
  151.     }
  152.     
  153.     if (initialise_globals() != OK) {
  154.         fprintf(stderr,
  155.             "Unable to initialise fonts");
  156.         exit(1);
  157.     }
  158.  
  159.     p2 = (struct type_IOB_G3FacsimileBodyPart *) 
  160.         calloc (1, sizeof(struct type_IOB_G3FacsimileBodyPart));
  161.  
  162.     p2 -> parameters = (struct type_IOB_G3FacsimileParameters *)
  163.         calloc (1, sizeof(struct type_IOB_G3FacsimileParameters));
  164.     
  165.     p2 -> parameters -> optionals = 
  166.         opt_IOB_G3FacsimileParameters_number__of__pages;
  167.  
  168.     coversheet = new_bitmap(FAX_WIDTH_LINES, FAX_HEIGHT_LINES);
  169.  
  170.     if (create_cover_sheet(coversheet, 
  171.                    FAX_WIDTH_LINES, FAX_HEIGHT_LINES) != OK)
  172.         exit(1);
  173.  
  174.     encodeImage(coversheet,
  175.             FAX_WIDTH_LINES, FAX_HEIGHT_LINES,
  176.              p2);
  177.     outputFax(p2, stdout);
  178.     free_bitmap(coversheet, FAX_WIDTH_LINES, FAX_HEIGHT_LINES);
  179.     exit(0);
  180. }
  181.  
  182. /*   */
  183.  
  184. /* replace \n's with \n's ! */
  185.  
  186. static char    *mystrdup(str)
  187. char    *str;
  188. {
  189.     char    *retstr = malloc((strlen(str)+1) * sizeof(char));
  190.     char    *ix, *iy;
  191.     
  192.     for (ix = str, iy = retstr; *ix != '\0'; ix++, iy++) {
  193.         if (*ix == '\\') {
  194.             switch (*(ix+1)) {
  195.                 case 'n':
  196.                 *iy = '\n';
  197.                 ix++;
  198.                 break;
  199.                 default:
  200.                 *iy = *ix;
  201.                 break;
  202.             }
  203.         } else
  204.             *iy = *ix;
  205.     }
  206.     *iy = '\0';
  207.     return retstr;
  208. }
  209.  
  210. extern PPFontPtr file2font();
  211.  
  212. int
  213. initialise_globals()
  214. {
  215.     FILE    *fp;
  216.     x_start = LEFT_PAD_LINES;
  217.     y_start = TOP_PAD_LINES;
  218.     page = NULLCP; page_x = 0; page_y = 0;
  219.     tab = 50; /* mm */
  220.     loc_company = NULLCP;
  221.     loc_telfax_number = NULLCP;
  222.     postscript = NULLCP;
  223.  
  224.     if (table != NULLTBL) {
  225.         if (tb_k2val (table, "keyfont", buffer, TRUE) != NOTOK) {
  226.             if ((fp = fopen(buffer, "r")) == NULL
  227.                 || (large = file2font(fp)) == (PPFontPtr) NOTOK)
  228.                 return NOTOK;
  229.             fclose(fp);
  230.         }
  231.                 
  232.         if (tb_k2val (table, "valuefont", buffer, TRUE) != NOTOK) {
  233.             if ((fp = fopen(buffer, "r")) == NULL
  234.                 || (bold = file2font(fp)) == (PPFontPtr) NOTOK)
  235.                 return NOTOK;
  236.             fclose(fp);
  237.         }
  238.         if (tb_k2val (table, "textfont", buffer, TRUE) != NOTOK) {
  239.             if ((fp = fopen(buffer, "r")) == NULL
  240.                 || (norm = file2font(fp)) == (PPFontPtr) NOTOK)
  241.                 return NOTOK;
  242.             fclose(fp);
  243.         }
  244.         if (tb_k2val (table, "xstart", buffer, TRUE) != NOTOK)
  245.             x_start = str2mm(buffer) * xres + X_ALLOWED_NOT_PRINT;
  246.         if (tb_k2val (table, "ystart", buffer, TRUE) != NOTOK)
  247.             y_start = (str2mm(buffer) + Y_ALLOWED_NOT_PRINT_TOP) * res;
  248.         if (tb_k2val (table, "tab", buffer, TRUE) != NOTOK)
  249.             tab = str2mm(buffer);
  250.         if (tb_k2val (table, "coverpage", buffer, TRUE) != NOTOK)
  251.             page = strdup(buffer);
  252.         if (tb_k2val (table, "localOrg", buffer, TRUE) != NOTOK) 
  253.             loc_company = mystrdup(buffer);
  254.         if (tb_k2val (table, "localNumber", buffer, TRUE) != NOTOK)
  255.             loc_telfax_number = strdup(buffer);
  256.         if (tb_k2val (table, "postscript", buffer, TRUE) != NOTOK)
  257.             postscript = mystrdup(buffer);
  258.     } else
  259.         return NOTOK;
  260.     return OK;
  261. }
  262.  
  263. /* copied from Chans/fax_aux.c */
  264. get_fax_number(adr, ptelno, porg)
  265. char    *adr;
  266. char    **ptelno, **porg;
  267. {
  268.     OR_ptr    or, or2;
  269.     char    *telno = NULLCP;
  270.  
  271.     *porg = NULLCP;
  272.     *ptelno = NULLCP;
  273.  
  274.     or = or_std2or(adr);
  275.     or2 = or;
  276.     while (or2 = or_locate (or2, OR_DD)) {
  277.         if (cmd_srch(or2->or_ddname, 
  278.                  ortbl_ddvalid) == OR_DDVALID_FAX) {
  279.             telno = strdup (or2->or_value);
  280.             break;
  281.         } else if (or2 -> or_next != NULLOR)
  282.             or2 = or2 -> or_next;
  283.         else
  284.             break;
  285.         
  286.     }
  287.     
  288.     /* use outmta */
  289.     if (telno == NULLCP
  290.         && outmta != NULLCP)
  291.         telno = strdup(outmta);
  292.  
  293.     if (telno != NULLCP
  294.         && table != NULLTBL
  295.         && tb_k2val (table, telno, buffer, TRUE) != NOTOK) {
  296.         free(telno);
  297.         tblentry2num(buffer, ptelno, porg);
  298.     } else {
  299.         *ptelno = telno;
  300.     }
  301.     or_free(or);
  302. }
  303.  
  304. tblentry2num(buf, ptelno, porg)
  305. char    *buf;
  306. char    **ptelno;
  307. char    **porg;
  308. {
  309.     char    *telno = NULLCP, *org = NULLCP, *ix, *iy;
  310.  
  311.     if ((ix = index(buf, ',')) == NULLCP) {
  312.         /* must all be number */
  313.         compress(buf,buf);
  314.     } else {
  315.         *ix++ = '\0';
  316.         compress(buf, buf);
  317.         /* for now rest is company */
  318.         if (*ix != '\0') 
  319.             org = strdup(ix);
  320.     }
  321.     telno = malloc(strlen(buf)*sizeof(char));
  322.     
  323.     ix = buf;
  324.     iy = telno;
  325.     
  326.     while (*ix != '\0')
  327.         switch (*ix) {
  328.             case 'p':
  329.             case 'P':
  330.             ix++;
  331.             break;
  332.             default:
  333.             *iy++ = *ix++;
  334.             break;
  335.         }
  336.  
  337.     *iy = '\0';
  338.  
  339.     if (ptelno != NULL) 
  340.         *ptelno = telno;
  341.     else if (telno != NULLCP)
  342.         free(telno);
  343.           
  344.     if (porg != NULL)
  345.         *porg = org;
  346.     else if (org != NULLCP)
  347.         free(org);
  348. }
  349.  
  350. extern char    *loc_or;
  351.  
  352. int
  353. create_cover_sheet(p, wid, ht)
  354. BitMap    p;
  355. int    wid, ht;
  356. {
  357.     int    x = x_start, y = y_start, nx, ny1, remain;
  358.     char    *rfchdr = NULLCP, *telno = NULLCP, *org = NULLCP;
  359.     AP_ptr    tree, group, name, local, domain, route;
  360.  
  361.     if (page != NULLCP) {
  362.         BitMap    b;
  363.         int    w, h;
  364.         FILE    *fp;
  365.         if ((fp = fopen(page, "r")) == NULL) {
  366.             PP_SLOG(LLOG_EXCEPTIONS, page,
  367.                 ("Can't open cover page bitmap file"));
  368.             return NOTOK;
  369.         }
  370.         if ((b = file2bitmap(fp, &w, &h)) == (BitMap) NOTOK) {
  371.             fprintf(stderr,
  372.                    "Unable to read in bitmap from file '%s'",
  373.                 page);
  374.             return NOTOK;
  375.         }
  376.         /* center on x */
  377.         remain = (wid - w - page_x)/2;
  378.         
  379.         if (insertbitmap(p, wid, ht, 
  380.                  b, w, h, 
  381.                  remain + page_x, page_y) == NOTOK) {
  382.             free_bitmap(b, w, h);
  383.             return NOTOK;
  384.         }
  385.         free_bitmap(b, w, h);
  386.     }
  387.     
  388.     rfchdr = read822hdr(&subject);
  389.  
  390.     if (to != NULLCP) {
  391.         OR_ptr    or, or2;
  392.         int    doneTo = FALSE;
  393.         or = or_std2or (to);
  394.         
  395.         or2 = or;
  396.         while (or2 = or_locate (or2, OR_DD)) {
  397.             if (cmd_srch(or2->or_ddname, 
  398.                      ortbl_ddvalid) == OR_DDVALID_ATTN) {
  399.                 char    *str;
  400.                 (void) sprintf(buf2, 
  401.                            "For the attention of: ");
  402.                 str = mystrdup(or2 -> or_value);
  403.                 draw2Str(p, wid, ht,
  404.                      &x, &y,
  405.                      buf2, large,
  406.                      str, bold);
  407.                 free(str);
  408.                 doneTo = TRUE;
  409.             } 
  410.             if (or2 -> or_next != NULLOR)
  411.                 or2 = or2 -> or_next;
  412.             else
  413.                 break;
  414.         }
  415.         
  416.         if (doneTo == FALSE) {
  417.             if (or_getpn(or, buffer) != TRUE)
  418.                 buffer[0] = '\0';
  419.             if (or2 = or_locate (or, OR_OU)) {
  420.                 /* see if local or not */
  421.                 or_or2std(or2, buf2, FALSE);
  422.                 if (lexequ(buf2, loc_or) != 0) {
  423.                     /* not local so add in mail box */
  424.                     if (or_or2rfc (or, buf2) == NOTOK)
  425.                         /* failed to convert to 822 */
  426.                         /* use x400 address */
  427.                         strcpy(buf2, to);
  428.                     if (buffer[0] == '\0')
  429.                         strcpy(buffer, buf2);
  430.                     else {
  431.                         strcat(buffer, " (");
  432.                         strcat(buffer, buf2);
  433.                         strcat(buffer, ")");
  434.                     }
  435.                 }
  436.             }
  437.             
  438.             if (buffer[0] == '\0')
  439.                 strcpy(buffer, to);
  440.             (void) sprintf(buf2, "To: ");
  441.             draw2Str(p, wid, ht,
  442.                  &x, &y,
  443.                  buf2, large,
  444.                  buffer, bold);
  445.         }                
  446.  
  447.         get_fax_number(to, &telno, &org);
  448.         if (org != NULLCP) {
  449.             char    *cp;
  450.             (void) sprintf (buf2, "At: ");
  451.             cp = mystrdup(org);
  452.             draw2Str (p, wid, ht,
  453.                   &x, &y, 
  454.                   buf2, large,
  455.                   cp, bold);
  456.             free(org);
  457.             free(cp);
  458.         }
  459.         if (telno != NULLCP && atoi(telno) != 0) {
  460.                 (void) sprintf (buf2, "TeleFax-No: ");
  461.  
  462.                 draw2Str (p, wid, ht,
  463.                       &x, &y, 
  464.                       buf2, large,
  465.                       telno, bold);
  466.                 free(telno);
  467.         } 
  468.         or_free(or);
  469.     }
  470.  
  471.     y += large->max_ht*2;
  472.  
  473.     /* try one from hdr.822 first */
  474.     if (from822 != NULLCP
  475.         && ap_s2p(from822,
  476.               &tree, &group, &name, 
  477.               &local, &domain, &route) != (char *) NOTOK) {
  478.         char    *m;
  479.         if (name != NULLAP) {
  480.             char    *ix;
  481.             m = ap_p2s(NULLAP, name,
  482.                    NULLAP, NULLAP,
  483.                    NULLAP);
  484.             if ((ix = rindex(m, '<')) != NULLCP)
  485.                 *ix = '\0';
  486.             strcpy(buffer, m);
  487.             free (m);
  488.         } else
  489.             strcpy(buffer, local->ap_obvalue);
  490.         m = ap_p2s(NULLAP, NULLAP,
  491.                local, domain,
  492.                NULLAP);
  493.         strcat(buffer, "(email=\"");
  494.         strcat(buffer, m);
  495.         strcat(buffer, "\")");
  496.         free (m);
  497.         ap_sqdelete(tree, NULLAP);
  498.         ap_free(tree);
  499.         free(from822);
  500.  
  501.         (void) sprintf(buf2, "From: ");
  502.         draw2Str (p, wid, ht,
  503.               &x, &y, 
  504.               buf2, large,
  505.               buffer, bold);
  506.     
  507.     } else if (from != NULLCP) {
  508.         /* try one from envelope */
  509.         OR_ptr    or, or2;
  510.         or = or_std2or (from);
  511.         
  512.         or2 = or;
  513.         if (or_getpn(or, buffer) == TRUE) {
  514.             if (or2 = or_locate(or, OR_OU)) {
  515.                 /* see if local or not */
  516.                 or_or2std(or2, buf2, FALSE);
  517.                 if (lexequ(buf2, loc_or) != 0) {
  518.                     or2 = or;
  519.                     (void) strcat (buffer, " (");
  520.                     while (or2 = or_locate (or2, OR_OU)) {
  521.                         (void) sprintf(buffer, "%s%s;",
  522.                                    buffer, or2 -> or_value);
  523.                         if (or2 -> or_next != NULLOR)
  524.                             or2 = or2 -> or_next;
  525.                         else
  526.                             break;
  527.                     }
  528.                     if (or2 = or_locate (or, OR_O)) 
  529.                         (void) sprintf(buffer, "%s%s;", 
  530.                                    buffer, or2 -> or_value);
  531.  
  532.                     if (or2 = or_locate (or, OR_PRMD)) 
  533.                         (void) sprintf(buffer, "%s%s;", 
  534.                                    buffer, or2 -> or_value);
  535.  
  536.                     if ((or2 = or_locate (or, OR_ADMD)) 
  537.                         && lexequ(or2 -> or_value, " ") != 0)
  538.                         (void) sprintf(buffer, "%s%s;", 
  539.                                    buffer, or2 -> or_value);
  540.  
  541.                     if (or2 = or_locate (or, OR_C)) 
  542.                         (void) sprintf(buffer, "%s%s", 
  543.                                    buffer, or2 -> or_value);
  544.                     (void) strcat (buffer, ")");
  545.                 }
  546.             }
  547.         } else if ((or2 = or_find(or, OR_DD, "RFC-822")) != NULLOR)
  548.             or_ps2asc(or2->or_value, buffer);
  549.         else
  550.             strcat(buffer, from);
  551.  
  552.         (void) sprintf(buf2, "From: ");
  553.         draw2Str (p, wid, ht,
  554.               &x, &y, 
  555.               buf2, large,
  556.               buffer, bold);
  557.     
  558.         or_free(or);
  559.     }
  560.  
  561.     if (loc_company != NULLCP) {
  562.         (void) sprintf(buf2, "Organisation: ");
  563.         (void) sprintf(buffer, loc_company);
  564.         draw2Str (p, wid, ht,
  565.               &x, &y, 
  566.               buf2, large,
  567.               buffer, bold);
  568.     }
  569.  
  570.     if (loc_telfax_number != NULLCP) {
  571.         (void) sprintf(buf2, "TeleFax-No: ");
  572.         (void) sprintf(buffer, "%s", loc_telfax_number);
  573.         draw2Str (p, wid, ht,
  574.               &x, &y, 
  575.               buf2, large,
  576.               buffer, bold);
  577.     }
  578.  
  579.     y += large->max_ht*2;
  580.  
  581.     if (date != NULLCP) {
  582.         (void) sprintf(buf2, "Date: ");
  583.         draw2Str (p, wid, ht,
  584.               &x, &y, 
  585.               buf2, large,
  586.               date, bold);
  587.         free(date);
  588.         date = NULLCP;
  589.     }
  590.  
  591.     if (subject != NULLCP) {
  592.         (void) sprintf(buf2, "Subject: ");
  593.         draw2Str (p, wid, ht,
  594.               &x, &y, 
  595.               buf2, large,
  596.               subject, bold);
  597.     }
  598.  
  599.     y += large->max_ht;
  600.     
  601.     if (rfchdr != NULLCP) {
  602.         drawStr(p, wid, ht,
  603.             norm,
  604.             x, y, 
  605.             rfchdr,
  606.             &nx, &y);
  607.         free(rfchdr);
  608.         rfchdr = NULLCP;
  609.     }
  610.  
  611.     y += large->max_ht;
  612.  
  613.     if (postscript != NULLCP) {
  614.         drawStr(p, wid, ht,
  615.             norm,
  616.             x, y,
  617.             postscript,
  618.             &nx, &ny1);
  619.         y = ny1;
  620.     }
  621.     return OK;
  622. }
  623.  
  624. /*   */
  625.  
  626. static int
  627. draw2Str(p, w, h, px, py, s1, f1, s2, f2)
  628. BitMap    p;
  629. int    w, h;
  630. int    *px, *py;
  631. char    *s1;
  632. PPFontPtr    f1;
  633. char    *s2;
  634. PPFontPtr    f2;
  635. {
  636.     int    nx, y1, y2;
  637.  
  638.     drawStr(p, w, h,
  639.         f1,
  640.         *px, *py,
  641.         s1,
  642.         &nx, &y1);
  643.     if (nx - *px < tab * xres)
  644.         nx = *px + (tab * xres);
  645.     drawStr(p, w, h,
  646.         f2,
  647.         nx, *py,
  648.         s2,
  649.         &nx, &y2);
  650.     *py = (y2 > y1) ? y2 : y1;
  651. }
  652.     
  653. static int    drawStr (p, w, h, f, x, y, s, nx, ny)
  654. BitMap    p;
  655. int    w, h;
  656. PPFontPtr    f;
  657. int    x, y;
  658. char    *s;
  659. int    *nx, *ny;
  660. {
  661.     int    nolines, ix, my_y = y, longest_x = 0;
  662.     char    *lines[100];
  663.  
  664.     nolines = sstr2arg (s, 100, lines, "\n");
  665.     
  666.     for (ix = 0; ix < nolines; ix++) {
  667.         int    dy, i = 0, dx;
  668.         char    *buffer = lines[ix];
  669.         char    *cix = &(buffer[0]);
  670.         /* take care of any folding */
  671.         while (cix - buffer < (int)strlen(buffer)) {
  672.             i = str_into_bitmap(p,f,x,my_y, &dx, &dy,
  673.                         FAX_WIDTH_LINES - LEFT_PAD_LINES,
  674.                         cix,
  675.                         strlen(cix));
  676.             cix += i;
  677.             if (dx > longest_x) longest_x = dx;
  678.             my_y += dy;
  679.         }
  680.     }
  681.  
  682.     *ny = my_y;
  683.     *nx = x + longest_x;
  684. }
  685.         
  686. /*   */
  687.  
  688. str2mm(s)
  689. char    *s;
  690. {
  691.     int    n, div = 1;
  692.     if (*s == NULL) return 0;
  693.     
  694.     n = 0;
  695.     while (*s != NULL && isspace(*s)) s++;
  696.     while (*s != NULL && isdigit(*s)) {
  697.         n = n * 10 + *s - '0';
  698.         s++;
  699.     }
  700.     if (*s == '.') {
  701.         /* after decimal points */
  702.         s++;
  703.         while (*s != NULL && isdigit(*s)) {
  704.             n = n * 10 + *s - '0';
  705.             if (div == 1)
  706.                 div = 10;
  707.             else
  708.                 div *= 10;
  709.             s++;
  710.         }
  711.     }
  712.     while (*s != NULL && isspace(*s)) s++;
  713.     if (*s != NULL && isalpha(*s)) {
  714.         if (lexequ (s, "cm") == 0) 
  715.             n *= 10;
  716.         else if (lexequ (s, "in") == 0) {
  717.             n *= 254;
  718.             if (div == 1)
  719.                 div = 10;
  720.             else
  721.                 div *= 10;
  722.         }
  723.     }
  724.     n = n / div;
  725.     return n;
  726. }
  727.  
  728. /*   */
  729. /* straight from submit/rd_rfchdr.c */
  730.  
  731. /* -- basic states for the state machine -- */
  732. #define HDV_EOH            0
  733. #define HDV_NEW            1
  734. #define HDV_MORE        2
  735.  
  736. /* -- munge the header lines of the message -- */
  737. #define HDR_FROM        1
  738. #define HDR_SENDER        2
  739. #define HDR_CC            3
  740. #define HDR_TO            4
  741. #define HDR_SUBJECT        5
  742. #define    HDR_DATE        6
  743.  
  744. static    CMD_TABLE  htbl_rfc [] = {
  745.     "from",            HDR_FROM,
  746.     "sender",        HDR_SENDER,
  747.     "cc",            HDR_CC,
  748.     "to",            HDR_TO,
  749.     "subject",        HDR_SUBJECT,
  750.     "date",            HDR_DATE,
  751.     0,            0
  752.     };
  753.  
  754. static int getline (bp, fp)
  755. char    **bp;
  756. FILE    *fp;
  757. {
  758.     static char *buf;
  759.     static int bufsiz = 0;
  760.     int    count;
  761.     char    *cp;
  762.     int    c;
  763.  
  764.     if (buf == NULLCP)
  765.         buf = smalloc (bufsiz = BUFSIZ);
  766.     for (cp = buf, count = 0; ; count ++) {
  767.         if (count >= bufsiz - 5) {
  768.             int curlen = cp - buf;
  769.             buf = realloc (buf, (unsigned) (bufsiz += BUFSIZ));
  770.             if (buf == NULL) {
  771.                 fprintf(stderr,
  772.                        "Out of memory");
  773.                 exit(1);
  774.             }
  775.             cp = buf + curlen;
  776.         }
  777.         switch (c = getc (fp)) {
  778.             case '\n':
  779.             if ((c = getc(fp)) == ' ' || c == '\t') {
  780.                 *cp ++ = '\n';
  781.                 continue;
  782.             }
  783.             ungetc (c, fp);
  784.             break;
  785.             case EOF:
  786.             if (cp == buf)
  787.                 return NOTOK;
  788.             break;
  789.             default:
  790.             *cp ++ = c;
  791.             continue;
  792.         }
  793.         break;
  794.     }
  795.     *cp = '\0';
  796.     *bp = buf;
  797.     return OK;
  798. }
  799.  
  800. static int hdr_parse (txt, name, contents)    /* -- parse one header line -- */
  801. register char        *txt;          /* -- a line of header text -- */
  802. char            **name;          /* -- location of field's name -- */
  803. char            **contents;    /* -- location of field's contents -- */
  804. {
  805.     char        linetype;
  806.  
  807.  
  808.     PP_DBG (("submit/hdr_parse (%s)", txt));
  809.  
  810.  
  811.     if (isspace (*txt)) {
  812.         /* -- continuation text -- */
  813.         if (*txt == '\n' || *txt == '\0')
  814.             return (HDV_EOH);
  815.         linetype = HDV_MORE;
  816.     }
  817.     else  {
  818.         linetype = HDV_NEW;
  819.  
  820.         *name = txt;
  821.         while (*txt && *txt != ':')
  822.             txt ++;
  823.         if (*txt == '\0' || *txt == '\n')
  824.             return NOTOK;
  825.         *txt ++ = '\0';
  826.  
  827.         (void) compress (*name, *name);
  828.     }
  829.  
  830.  
  831.     *contents = txt;
  832.  
  833.     return (linetype);
  834. }
  835.  
  836. static char    *read822hdr (psubject)
  837. char    **psubject;
  838. {
  839.     char    *retstr = NULLCP, *bp, *temp, *addon, *name, *contents;
  840.     int    retval, type, len;
  841.  
  842.     while (getline (&bp, stdin) == OK) {
  843.         switch (retval = hdr_parse (bp, &name, &contents)) {
  844.             case HDV_MORE:
  845.             continue;
  846.             case HDV_NEW:
  847.             if ((type = cmd_srch (name, htbl_rfc)) > 0) {
  848.                 switch (type) {
  849.                     case HDR_DATE:
  850.                     date = strdup(contents);
  851.                     break;
  852.  
  853.                     case HDR_SUBJECT:
  854.                     *psubject = strdup(contents);
  855.                     break;
  856.                     case HDR_FROM:
  857.                     from822 = strdup(contents);
  858.                     case HDR_SENDER:
  859.                     case HDR_CC:
  860.                     case HDR_TO:
  861.                     len = strlen(name) + strlen(contents) + 2;
  862.                     addon = calloc(len, sizeof(char));
  863.                     (void) sprintf(addon, "%s:%s",name,contents);
  864.  
  865.                     if (retstr == NULLCP)
  866.                         retstr = addon;
  867.                     else {
  868.                         len = strlen(addon) + strlen(retstr) + 1;
  869.                         temp = calloc(len, sizeof(char));
  870.                         (void) sprintf (temp, "%s\n%s", retstr, addon);
  871.                         free(retstr);
  872.                         free(addon);
  873.                         retstr = temp;
  874.                     }
  875.                     break;
  876.                     default:
  877.                     break;
  878.                 }
  879.             }
  880.             continue;
  881.             case HDV_EOH:
  882.             break;
  883.             case NOTOK:
  884.             fprintf(stderr,
  885.                 "hdr2fax: Unable to parse '%s' as key:field", bp);
  886.             break;
  887.         }
  888.         break;
  889.     }
  890.     return retstr;
  891. }
  892.