home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / misc / volume26 / hp2pbm / part02 / hpfntwrite.c next >
Encoding:
C/C++ Source or Header  |  1991-12-11  |  29.3 KB  |  1,539 lines

  1. /*
  2.     hpfntwrite.c
  3.  
  4.     converts hpcl output into a [series of] pbm file[s].
  5.     based on faxpak's fntwrite for texttopbm, which was ripped off 
  6.     from chart.c
  7.  
  8.     version 1.0, Copyright (C) 1991, klaus schallhorn, <klaus@cnix.uucp>
  9.  
  10.     Permission to use, copy, modify, and distribute this software and its
  11.     documentation for any purpose and without fee is hereby granted, provided
  12.     that the above copyright notice appear in all copies and that both that
  13.     copyright notice and this permission notice appear in supporting
  14.     documentation.  This software is provided "as is" without express or
  15.     implied warranty.
  16. */
  17.  
  18. #include "hptopbm.h"
  19.  
  20. #ifndef    lint
  21. char SCCSid[] = "@(#)hpfntwrite.c: 1.1 91/12/03 00:34:42";
  22. #endif
  23.  
  24. #ifdef    FAXPAK
  25. extern    struct FAXCONFIG fc;
  26. #endif
  27.  
  28. #ifndef    MAX_HITE
  29. #define    MAX_HITE    4200    /* 14 in @ 300 dpi */
  30. #endif
  31. #ifndef    MAX_WIDTH
  32. #define    MAX_WIDTH    2800
  33. #endif
  34.  
  35. #define    MAX_FONT    MAX_BUILTIN+MAX_DOWNLOAD
  36. #define    MAX_MACRO    32
  37. #define    MAX_PAT        14
  38.  
  39. #define    ESC        '\033'
  40. #define    setpix(y,x)    (block[y][x>>3] |= bit[x&7])
  41.  
  42. #ifndef    min
  43. #define    min(a,b)    ((a<b)?a:b)
  44. #define    max(a,b)    ((a>b)?a:b)
  45. #endif
  46.  
  47.  
  48. #define    relative()    movetype
  49.  
  50. extern    int builtin, dotted, movetype, lastfontid;
  51.  
  52. static    uchar *block[MAX_HITE];
  53.  
  54. static struct    MCENV
  55. {
  56.     int    page_len,
  57.         top_margin,
  58.         left_margin,
  59.         rite_margin,
  60.         cur_fnt,
  61.         cur_fID,
  62.         cur_mac,
  63.         pfont,
  64.         cur_chr,
  65.         underline,
  66.         dpi,
  67.         pID,
  68.         top_dots,
  69.         left_dots,
  70.         text_len;
  71.     double    hmi,
  72.         lhite,
  73.         Hlen, Vlen;
  74. } McEnv, orgenv, *curenv;
  75.  
  76. static struct    OVLY
  77. {
  78.     struct    MCENV ovly_env;
  79.     int    sfont;
  80.     double    BMX, BMY,         /* current abs xy */
  81.         GRAPHX;
  82.     double    lpi;
  83. } ovly, restore;
  84.  
  85. struct    FONT_ATTS
  86. {
  87.     int    orient,
  88.         symset,
  89.         prop_spaced,
  90.         style,
  91.         stroke,
  92.         typeface;
  93.     double    pitch,
  94.         points;
  95. } lastspec;
  96.  
  97. static    int sfont,
  98.     max_ln, max_col,     /* max dimen abs pels */
  99.     xmax_used, ymax_used,     /* max abs used */
  100.     bmx, bmy,         /* current abs xy */
  101.     see_thru,         /* dont paint anything */
  102.     new_topmargin,         /* takes effect on next page unless <ESC>&a0R */
  103.     env_saved,
  104.     stackpos,
  105.     auto_macro,
  106.     try_select,
  107.     virgin = TRUE,
  108.     no_bitmap = TRUE;
  109.  
  110. static    int xscale[MAX_WIDTH], yscale[MAX_HITE], fax_head_size;
  111.  
  112. static    double xdpi, ydpi, lpi, BMX, BMY, GRAPHX;
  113.  
  114. static    uchar bit[] =
  115. {
  116.     0x80,0x40,0x20,0x10,0x08,0x04,0x02,0x01
  117. };
  118.  
  119. struct    CHAR_BITMAP
  120. {
  121.     short len, hite, clen, toffs, loffs;
  122.     uchar **CH;
  123. };
  124.  
  125. struct    HPFONT
  126. {
  127.     int    fID,
  128.         active,
  129.         prop_spaced,
  130.         real_spaced,
  131.         permtype,
  132.         primtype,
  133.         builtin;
  134.     double    space_len,
  135.         real_space_len;        /* to restore reality */
  136.     struct    FONT_ATTS font_atts;
  137.     struct    CHAR_BITMAP chars[256];
  138. } hpfonts[MAX_FONT], *cfn, *getcfn(), *findlstid();
  139.  
  140. struct    MACRO
  141. {
  142.     int    active,
  143.         permtype,
  144.         magic,
  145.         len;
  146.     uchar    *macro;
  147. } macros[MAX_MACRO], *cmc, *getcmc();
  148.  
  149. struct    STACK
  150. {
  151.     double BMX, BMY;
  152. } stack[MAX_PUSHNPOP];
  153.  
  154. struct PAT
  155. {
  156.     uchar p;
  157.     struct PAT *xnext, *ynext;
  158. } pat[MAX_PAT][32][4];
  159.  
  160. char    *BuiltinFonts[]=
  161. {
  162. /* 0*/    "lp.sfp",
  163. /* 1*/    "",
  164. /* 2*/    "",
  165. /* 3*/    "cour.sfp",
  166. /* 4*/    "",
  167. /* 5*/    "",
  168. /* 6*/    "",
  169. /* 7*/    "",
  170.     NULL
  171. };
  172.  
  173. #define    GRAY        2
  174. #define    GRAY_BASE    0
  175. #define    RULE        3
  176. #define    RULE_BASE    7
  177. #define    SOLID        7
  178.  
  179. char    *BuiltinPats[]=
  180. {
  181.     "hprast1",
  182.     "hprast2",
  183.     "hprast3",
  184.     "hprast4",
  185.     "hprast5",
  186.     "hprast6",
  187.     "hprast7",
  188.     "hprast8",
  189.     "hppat1",
  190.     "hppat2",
  191.     "hppat3",
  192.     "hppat4",
  193.     "hppat5",
  194.     "hppat6",
  195.     NULL
  196. };
  197.  
  198.  
  199. /* STARTUP, automagically called from main ********************************* */
  200. rs_rastsize(x,y)
  201. double x,y;
  202. {
  203. #ifdef    FAXPAK
  204.     extern char *PGM;
  205.  
  206.     if (!strcmp(PGM,"hp2lofax"))
  207.         fax_head_size = 40;
  208.     else fax_head_size = 80;
  209. #endif
  210.  
  211.     xdpi = x;
  212.     ydpi = y;
  213.     see_thru = 0;
  214.     lpi = 6.0;
  215.     orgenv.page_len = PAGE_LEN;
  216.     orgenv.top_margin = new_topmargin = TOP_MARGIN;
  217.     orgenv.left_margin = LEFT_MARGIN;
  218.     orgenv.rite_margin = RITE_MARGIN;
  219.     orgenv.text_len = PAGE_LEN - TOP_MARGIN;
  220.     orgenv.text_len -= 3;
  221.     orgenv.lhite = 50;
  222.     orgenv.top_dots = fax_head_size + orgenv.top_margin*orgenv.lhite;
  223.     orgenv.left_dots = 47;    /* dots = .157 in */
  224.     orgenv.dpi = 75;    /* hp 2686a */
  225.     stackpos = 0;
  226.     try_select = 0;
  227.     builtin = -1;
  228.     orgenv.cur_fID = orgenv.cur_chr = -1;
  229.     orgenv.cur_mac = -1;
  230.     curenv = &orgenv;
  231.     auto_macro = -1;
  232.     cfn = NULL;
  233.     cmc = NULL;
  234.     fontinit();
  235.     xyinit();
  236.     macinit();
  237.     ovlyinit();
  238.     builtin_fontinit();
  239.     builtin_patinit();
  240. }
  241. fontinit()
  242. {
  243.     int i, j, *Yptr;
  244.     struct HPFONT *hf;
  245.     struct CHAR_BITMAP *cf;
  246.     double x;
  247.  
  248.     for (j=0; j<MAX_FONT; j++)
  249.     {
  250.         hf = &hpfonts[j];
  251.         hf->fID = hf->prop_spaced = hf->real_spaced = -1;
  252.         hf->permtype = hf->primtype = -1;
  253.         hf->space_len = -1.0;
  254.         hf->real_space_len = -1.0;
  255.         hf->active = hf->builtin = FALSE;
  256.         for (i=0; i<256; i++)    /* just to be safe */
  257.         {
  258.             cf = &hf->chars[i];
  259.             cf->CH = (uchar **)NULL;
  260.             cf->len = cf->hite = cf->clen = cf->toffs = cf->loffs = 0;
  261.         }
  262.     }
  263.     hf = &hpfonts[LINEPRINTER];
  264.     hf->prop_spaced = hf->real_spaced = 0;
  265.     hf->space_len = 18;
  266.     hf->real_space_len = 18;
  267.     hf->active = hf->builtin = TRUE;
  268.  
  269.     hf = &hpfonts[COURIER];
  270.     hf->prop_spaced = hf->real_spaced = 0;
  271.     hf->space_len = 30;
  272.     hf->real_space_len = 30;
  273.     hf->active = hf->builtin = TRUE;
  274.  
  275.     if (((int)xdpi == 300) && ((int)ydpi == 300))
  276.     {
  277.         Yptr = xscale;
  278.         for (i=0; i<MAX_WIDTH; i++)
  279.             *Yptr++ = i;
  280.         Yptr = yscale;
  281.         for (i=0; i<MAX_HITE; i++)
  282.             *Yptr++ = i;
  283.     }
  284.     else
  285.     {
  286.         Yptr = &xscale[1];
  287.         for (i=1; i<MAX_WIDTH; i++)
  288.         {
  289.             x = .5 + ((double)i * xdpi);
  290.             x /= 300.0;
  291.             *Yptr++ = (int)x;
  292.         }
  293.         Yptr = &yscale[1];
  294.         for (i=1; i<MAX_HITE; i++)
  295.         {
  296.             x = .5 + ((double)i * ydpi);
  297.             x /= 300.0;
  298.             *Yptr++ = (int)x;
  299.         }
  300.     }
  301. }
  302. xyinit()
  303. {
  304.     BMY = orgenv.top_dots;
  305.     BMX = 0.0;
  306.     GRAPHX = 0.0;
  307. }
  308. ovlyinit()
  309. {
  310.     ovly.ovly_env = orgenv;
  311.     ovly.sfont = sfont;
  312.     ovly.BMX = BMX;
  313.     ovly.BMY = BMY;
  314.     ovly.GRAPHX = GRAPHX;
  315.     ovly.lpi = lpi;
  316. }
  317. builtin_fontinit()
  318. {
  319.     int i;
  320.  
  321.     for (i=0; i<MAX_BUILTIN; i++)
  322.         if (BuiltinFonts[i] && *BuiltinFonts[i])
  323.         {
  324.             builtin = i;
  325.             loadbuiltin(BuiltinFonts[i]);
  326.         }
  327.     builtin = -1;
  328.     curenv->cur_fnt = COURIER;
  329. }
  330. builtin_patinit()
  331. {
  332.     int i,j,k,x,y;
  333.     FILE *fp;
  334.     char buf[256], fname[256];
  335.     struct PAT *ptr;
  336.  
  337.     for (k=0; k<MAX_PAT; k++)
  338.     {
  339. #ifdef    FAXPAK
  340.         sprintf(fname, "%s/hplib/%s", fc.faxlib, BuiltinPats[k]);
  341. #else
  342.         sprintf(fname, BUILTINDIR, LIBDIR, BuiltinPats[k]);
  343. #endif
  344.         if ((fp = fopen(fname, "r")) == NULL)
  345.             die("can't open %s\n",fname);
  346.         if (fgets(buf, 80, fp) == NULL || strncmp(buf, "P4", 2))
  347.             die("%s doesn't look like a pbm file\n",fname);
  348.         for (;;)
  349.         {
  350.             if (fgets(buf, 256, fp) == NULL)
  351.                 die("A: %s doesn't look like a pbm file\n",fname);
  352.             if (buf[0] != '#')
  353.             {
  354.                 if (sscanf(buf, "%d %d",&x,&y) != 2)
  355.                     die("B: %s doesn't look like a pbm file\n",fname);
  356.                 break;
  357.             }
  358.         }
  359.         if (!(x % 8))
  360.             x /= 8;
  361.         else x = 1+(x/8);
  362.         if (x < 4 || y < 32)
  363.             die("%s is not a known pattern\n",fname);
  364.  
  365.          for (j=0; j<31; j++)
  366.         {
  367.             for (i=0; i<3; i++)
  368.             {
  369.                 ptr = &pat[k][j][i];
  370.                 ptr->p = getc(fp);
  371.                 ptr->xnext = &pat[k][j][i+1];
  372.                 ptr->ynext = &pat[k][j+1][i];
  373.             }
  374.             ptr = &pat[k][j][3];
  375.             ptr->p = getc(fp);
  376.             ptr->xnext = &pat[k][j][0];
  377.             ptr->ynext = &pat[k][j+1][3];
  378.         }
  379.         for (i=0; i<3; i++)
  380.         {
  381.             ptr = &pat[k][j][i];
  382.             ptr->p = getc(fp);
  383.             ptr->xnext = &pat[k][j][i+1];
  384.             ptr->ynext = &pat[k][0][i];
  385.         }
  386.         ptr = &pat[k][j][3];
  387.         ptr->p = getc(fp);
  388.         ptr->xnext = &pat[k][j][0];
  389.         ptr->ynext = &pat[k][0][3];
  390.         fclose(fp);
  391.     }
  392. }
  393. make_bitmap(x,y)
  394. int x,y;
  395. {
  396.     int i, orgx, xa, ya;
  397.  
  398.     if (x > MAX_WIDTH || y > MAX_HITE)
  399.         die("requested bitmap too large\n");
  400.  
  401.     orgx = x;
  402.     if (x%32)            /* set to 32bit/4byte boundary */
  403.         x = x+32-(x%32);
  404.     x /= 8;
  405.  
  406.     xa = xscale[x];
  407.     ya = yscale[y];
  408.  
  409.     for (i=0; i<ya; i++)
  410.         if ((block[i] = (uchar *)calloc(xa,sizeof(uchar))) == NULL)
  411.             die("not enough memory\n");
  412.     for (; i<MAX_HITE; i++)
  413.         block[i] = NULL;
  414.  
  415.     max_ln = y-1;
  416.     max_col = (orgx)-1;
  417.     no_bitmap = FALSE;
  418. }
  419.  
  420. end_bitmap(tname)
  421. char *tname;
  422. {
  423.     int i, j, xmax;
  424.     FILE *fp;
  425.  
  426.     if ((fp = fopen(tname, "w")) == NULL)
  427.         die("cannot create pbm file %s\n",tname);
  428.  
  429.     ymax_used = yscale[max_ln-1];
  430. #ifdef    FAXPAK
  431.     xmax = min(216, xscale[(max_col+7)/8]);        /* max 1728 pels */
  432. #else
  433.     xmax = xscale[(max_col+7)/8];
  434. #endif
  435.     if (fprintf(fp,"P4\n%d %d\n",xmax*8,ymax_used) == EOF)
  436.         die("can't init pbmfile %s\n",tname);
  437.  
  438.     for (i=0; i<ymax_used; i++)
  439.     {
  440.         if ((j = fwrite((char*)block[i], 1, xmax, fp)) != xmax)
  441.             die("premature EOF after %d bytes of %d, line %d of %d\n",
  442.                 j,xmax,i,ymax_used);
  443.         (void)memset((char*)block[i], '\0', xmax);
  444.     }
  445.     fclose(fp);
  446.  
  447.     ymax_used = xmax_used = 0;
  448.     orgenv.top_margin = new_topmargin;
  449.     orgenv.top_dots = fax_head_size + orgenv.top_margin*orgenv.lhite;
  450.     curenv = &orgenv;
  451.     dotted = FALSE;
  452.     virgin = TRUE;
  453.     stackpos = 0;
  454. }
  455.  
  456. /* FONT stuff ************************************************************** */
  457. struct HPFONT *getcfn()
  458. {
  459.     struct HPFONT *hpf;
  460.  
  461.     if (curenv->cur_fnt < 0 || curenv->cur_fnt >= MAX_FONT)
  462.         die("don't know font %d\n",curenv->cur_fnt);
  463.     hpf = &hpfonts[curenv->cur_fnt];
  464.     if (!hpf->active)
  465.         die("font %d not active\n",curenv->cur_fnt);
  466.     curenv->cur_fID = hpf->fID;
  467.     return(hpf);
  468. }
  469. struct HPFONT *findlstid()
  470. {
  471.     struct HPFONT *hpf;
  472.     int i;
  473.  
  474.     for (i=0; i<MAX_FONT; i++)
  475.     {
  476.         hpf = &hpfonts[i];
  477.         if (hpf->active && hpf->fID == lastfontid)
  478.             return(hpf);
  479.     }
  480.     return(NULL);
  481. }
  482. /* defaults are set from various places after various events, almost circular */
  483. tlen_default()
  484. {
  485.     curenv->text_len = curenv->page_len - curenv->top_margin;
  486.     curenv->text_len -= (300/curenv->lhite)/2;
  487. }
  488. mtop_default()
  489. {
  490.     curenv->top_margin = TOP_MARGIN;
  491.     curenv->top_dots = fax_head_size + curenv->top_margin*curenv->lhite;
  492. }
  493. lr_default()
  494. {
  495.     curenv->left_margin = LEFT_MARGIN;
  496.     curenv->left_dots = 47;
  497.     curenv->rite_margin = RITE_MARGIN;
  498. }
  499. hmi_default()
  500. {
  501.     cfn = getcfn();
  502.     curenv->hmi = cfn->real_space_len;
  503.     cfn->space_len = cfn->real_space_len;
  504. }
  505. setshift(n)
  506. int n;
  507. {
  508.     if (try_select)
  509.         best_match();
  510.  
  511.     cfn = getcfn();
  512.     cfn->primtype = n;
  513.     curenv->cur_fID = cfn->fID;
  514.     hmi_default();
  515. }
  516.  
  517. /* clearing fonts or chars ************************************************* */
  518. clearchar(cptr)
  519. struct CHAR_BITMAP *cptr;
  520. {
  521.     int i;
  522.  
  523.     for (i=0 ;i<cptr->hite; i++)
  524.         if (cptr->CH[i])
  525.             free((char*)cptr->CH[i]);
  526.     if (cptr->CH)
  527.         free((char*)cptr->CH);
  528.     cptr->CH = (uchar **)NULL;
  529.     cptr->len = cptr->hite = cptr->clen = cptr->toffs = cptr->loffs = 0;
  530. }
  531. clear1font(fptr)
  532. struct HPFONT *fptr;
  533. {
  534.     int i;
  535.  
  536.     for (i=32; i<256; i++)
  537.         clearchar(&fptr->chars[i]);
  538.     fptr->fID = fptr->prop_spaced = fptr->real_spaced = 
  539.         fptr->permtype = fptr->primtype = -1;
  540.     fptr->space_len = -1;
  541.     fptr->real_space_len = -1;
  542.     fptr->active = FALSE;
  543. }
  544. clearallfonts()
  545. {
  546.     clearfonts(TEMPORARY);
  547.     clearfonts(PERMANENT);
  548.     orgenv.cur_fnt = COURIER;
  549.     orgenv.cur_fID = -1;
  550.     env_saved = FALSE;
  551.     curenv = &orgenv;
  552. }
  553. clearfonts(type)
  554. int type;
  555. {
  556.     int i;
  557.     struct HPFONT *cf;
  558.  
  559.     for (i=0; i<MAX_FONT; i++)
  560.     {
  561.         cf = &hpfonts[i];
  562.         if ((!cf->builtin) && cf->active && cf->permtype == type)
  563.         {
  564.             if (curenv->cur_fnt == i && dotted)
  565.             {
  566.                 pbmeject(TRUE);
  567.                 curenv = &orgenv;
  568.                 curenv->cur_fID = -1;
  569.                 curenv->cur_fnt = COURIER;
  570.                 env_saved = FALSE;
  571.             }
  572.             clear1font(&hpfonts[i]);
  573.         }
  574.     }
  575. }
  576. clearcurfont()
  577. {
  578.     struct HPFONT *hp;
  579.  
  580.     if ((hp = findlstid()) != (struct HPFONT*)NULL)
  581.         if (!cfn->builtin)
  582.         {
  583.             if (hp == cfn)
  584.                 orgenv.cur_fnt = COURIER;
  585.             clear1font(hp);
  586.             curenv = &orgenv;
  587.             curenv->cur_fID = -1;
  588.             env_saved = FALSE;
  589.             if (dotted)
  590.                 pbmeject(TRUE);
  591.         }
  592. }
  593. clearlastchar()
  594. {
  595.     cfn = getcfn();
  596.     if ((!cfn->builtin) && cfn->chars[curenv->cur_chr].len)
  597.         clearchar(&cfn->chars[curenv->cur_chr]);
  598. }
  599. makeftype(what)
  600. int what;
  601. {
  602.     int i;
  603.     struct HPFONT *hpf;
  604.  
  605.     if (lastfontid == -1)
  606.         return;
  607.     if ((hpf = findlstid()) != (struct HPFONT *)NULL)
  608.         hpf->permtype = what;
  609.     else
  610.     {
  611.         for (i=0; i<MAX_FONT; i++)
  612.         {
  613.             hpf = &hpfonts[i];
  614.             if (!hpf->active)
  615.             {
  616.                 hpf->active = TRUE;
  617.                 hpf->fID = lastfontid;
  618.                 hpf->permtype = what;
  619.                 break;
  620.             }
  621.         }
  622.         if (i == MAX_FONT)
  623.             die("too many fonts\n");
  624.     }
  625. }
  626. best_match()
  627. {
  628.     int i, *ip, best, bestfnt, canuse[MAX_FONT];
  629.     struct HPFONT *hf;
  630.  
  631.     try_select = FALSE;
  632.  
  633.     ip = canuse;
  634.     for (i=0; i<MAX_FONT; i++)
  635.         *ip++ = 0;
  636.  
  637.     ip = canuse;
  638.     for (i=0; i<MAX_FONT; i++, ip++)
  639.     {
  640.         hf = &hpfonts[i];
  641.         if (hf->active)
  642.         {
  643.             if (hf->font_atts.orient == lastspec.orient)
  644.                 *ip = 8;
  645.             if (hf->font_atts.symset == lastspec.symset)
  646.                 *ip += 7;
  647.             if (hf->font_atts.prop_spaced == lastspec.prop_spaced)
  648.                 *ip += 6;
  649.             if (hf->font_atts.pitch == lastspec.pitch)
  650.                 *ip += 5;
  651.             if (hf->font_atts.points == lastspec.points)
  652.                 *ip += 4;
  653.             if (hf->font_atts.style == lastspec.style)
  654.                 *ip += 3;
  655.             if (hf->font_atts.stroke == lastspec.stroke)
  656.                 *ip += 2;
  657.             if (hf->font_atts.typeface == lastspec.typeface)
  658.                 *ip += 1;
  659.         }
  660.     }
  661.     ip = canuse;
  662.     for (bestfnt = best = -1, i=0; i<MAX_FONT; i++, ip++)
  663.         if (*ip > best)
  664.         {
  665.             best = *ip;
  666.             bestfnt = i;
  667.         }
  668.     if (bestfnt > -1 && bestfnt < MAX_FONT)
  669.     {
  670.         curenv->cur_fnt = bestfnt;
  671.         hf = getcfn();
  672.     }
  673. }
  674.  
  675. /* mostly char/line based dimension defaults ******************************* */
  676. rs_plen(n)
  677. double n;
  678. {
  679.     if (n && curenv->lhite && curenv->lhite*n < 14*300)
  680.     {
  681.         curenv->page_len = (int)n;
  682.         mtop_default();
  683.         tlen_default();
  684.         lr_default();
  685.     }
  686.     (void)rs_auto_enable(FALSE);
  687. }
  688. rs_mtop(n)
  689. double n;
  690. {
  691.     if (curenv->lhite && curenv->lhite*n < curenv->lhite*curenv->page_len)
  692.     {
  693.         new_topmargin = (int)n;
  694.         if (virgin)
  695.         {
  696.             curenv->top_margin = new_topmargin;
  697.             curenv->top_dots = fax_head_size + curenv->top_margin*curenv->lhite;
  698.         }
  699.         tlen_default();
  700.     }
  701. }
  702. rs_tlen(n)
  703. double n;
  704. {
  705.     if (n && (n <= (curenv->page_len - curenv->top_margin)))
  706.         curenv->text_len = (int)n;
  707.     else if (!n)
  708.         tlen_default();
  709. }
  710. rs_mleft(n)
  711. double n;
  712. {
  713.     cfn = getcfn();
  714.     if (n < curenv->rite_margin)
  715.     {
  716.         curenv->left_margin = (int)n;
  717.         curenv->left_dots = curenv->left_margin * cfn->space_len;
  718.     }
  719. }
  720. rs_mright(n)
  721. double n;
  722. {
  723.     if (n > curenv->left_margin)
  724.         curenv->rite_margin = (int)n;
  725. }
  726. rs_col(n)
  727. double n;
  728. {
  729.     cfn = getcfn();
  730.     if (relative())
  731.         BMX += n*cfn->space_len;
  732.     else if (!(int)n)
  733.         BMX = curenv->left_dots;
  734.     else BMX = n*cfn->space_len;
  735.     BMX = max(0.0, BMX);
  736.     BMX = min(BMX, (double)((RITE_MARGIN-1)*30));    /* using 10cpi for max */
  737. }
  738. rs_row(n)
  739. double n;
  740. {
  741.     double largest;
  742.  
  743.     if (!(int)n)
  744.     {
  745.         curenv->top_margin = new_topmargin;
  746.         curenv->top_dots = fax_head_size + curenv->top_margin*curenv->lhite;
  747.         BMY = (double)curenv->top_dots * curenv->lhite;
  748.         return;
  749.     }
  750.     if (relative())
  751.     {
  752.         BMY += n*curenv->lhite;
  753.         if (n > 0 && BMY > (curenv->top_margin+curenv->text_len)*curenv->lhite)
  754.         {
  755.             pbmeject(TRUE);
  756.             rs_row(0.0);
  757.             return;
  758.         }
  759.         else if (BMY < 0)
  760.             BMY = curenv->top_dots * curenv->lhite;
  761.     }
  762.     else
  763.         BMY = curenv->top_dots + n * curenv->lhite;
  764.     BMY = max(0.0, BMY);
  765.     largest = (double)(fax_head_size+curenv->top_margin+curenv->text_len)*curenv->lhite;
  766.     BMY = min(BMY, largest);
  767. }
  768. half_linefeed()
  769. {
  770.     BMY += curenv->lhite/2.0;
  771. }
  772. /* dotty stuff ************************************************************* */
  773. rs_lpi(n)
  774. double n;
  775. {
  776.     int pels;
  777.  
  778.     pels = (int)n;
  779.     switch(pels)
  780.     {
  781.     case 1:        curenv->lhite = 300.0;    break;
  782.     case 2:        curenv->lhite = 150.0;    break;
  783.     case 3:        curenv->lhite = 100.0;    break;
  784.     case 4:        curenv->lhite =  75.0;    break;
  785.     case 6:        curenv->lhite =  50.0;    break;
  786.     case 8:        curenv->lhite =  37.5;    break;
  787.     case 12:    curenv->lhite =  25.0;    break;
  788.     case 16:    curenv->lhite =  18.75;    break;
  789.     case 24:    curenv->lhite =  12.5;    break;
  790.     case 48:    curenv->lhite =   6.25;    break;
  791.     default:    return;
  792.     }
  793.     lpi = n;
  794. }
  795. rs_vmi(n)
  796. double n;
  797. {
  798.     if (n >= 0 && n < 126)
  799.         curenv->lhite = n*300/48;
  800. }
  801. rs_hmi(n)
  802. double n;
  803. {
  804.     cfn = getcfn();
  805.     if (n >= 0 && n < 126 && cfn->active) {
  806.         cfn->space_len = n*300/120;
  807.         curenv->hmi = cfn->space_len;
  808.     }
  809. }
  810. rs_X(x)
  811. double x;
  812. {
  813.     if (relative())
  814.         BMX += x;
  815.     else BMX = x;
  816.     BMX = max(0.0, BMX);
  817.             /* max == rightmost legal pixel */
  818.             /* would be pixel 29 if RIGHT_MARGIN == 0 */
  819.     BMX = min(BMX, (double)((1+RITE_MARGIN)*30)-1);    
  820. }
  821. rs_Y(y,decipt)
  822. double y;
  823. int decipt;
  824. {
  825.     if (relative())
  826.         BMY += y;
  827.     else BMY = curenv->top_dots+y;
  828.     BMY = max(0.0, BMY);
  829.     if (decipt)
  830.         y = PAGE_LEN * 50;
  831.     else y = (fax_head_size+curenv->top_margin+curenv->text_len)*curenv->lhite;
  832.     BMY = min(BMY, y);
  833. }
  834. /* font settings *********************************************************** */
  835. rs_symset(set)
  836. int set;
  837. {
  838.     lastspec.symset = set;
  839. }
  840. rs_spacing(n)
  841. int n;
  842. {
  843.     cfn = getcfn();
  844.     cfn->prop_spaced = n;
  845.     if (cfn->real_spaced)
  846.     {
  847.         cfn->space_len = cfn->real_space_len;
  848.         curenv->hmi = cfn->real_space_len;
  849.     }
  850.     lastspec.prop_spaced = n;
  851. }
  852. rs_pitch(n)
  853. double n;
  854. {
  855.     lastspec.pitch = n;
  856.     try_select = 1;
  857. }
  858. rs_points(n)
  859. double n;
  860. {
  861.     lastspec.points = n;
  862.     try_select = 1;
  863. }
  864. rs_style(n)
  865. int n;
  866. {
  867.     lastspec.style = n;
  868.     try_select = 1;
  869. }
  870. rs_stroke(n)
  871. int n;
  872. {
  873.     lastspec.stroke = n;
  874.     try_select = 1;
  875. }
  876. rs_typeface(n)
  877. int n;
  878. {
  879.     lastspec.typeface = n;
  880.     try_select = 1;
  881. }
  882. rs_setpitch(n)
  883. double n;
  884. {
  885.     cfn = getcfn();
  886.     if (!cfn->prop_spaced)
  887.     {
  888.         cfn->space_len = 300/n;
  889.         curenv->hmi = cfn->space_len;
  890.     }
  891. }
  892. /* unclassified ************************************************************ */
  893. rs_ul(n)
  894. double n;
  895. {
  896.     curenv->underline = (int)n;
  897. }
  898. rs_thru(n)
  899. double n;
  900. {
  901.     see_thru = (int)n;
  902. }
  903. rs_stack(n)
  904. double n;
  905. {
  906.     struct STACK *st;
  907.  
  908.     if (n && stackpos > 0)
  909.     {
  910.         st = &stack[--stackpos];
  911.         BMX = st->BMX;
  912.         BMY = st->BMY;
  913.     }
  914.     else if ((!n) && stackpos < MAX_PUSHNPOP-1)
  915.     {
  916.         st = &stack[stackpos++];
  917.         st->BMX = BMX;
  918.         st->BMY = BMY;
  919.     }
  920. }
  921. #ifdef    TRIMPAGE
  922. rs_ymax(n)    /* used to force full height 1st page, faxpak related */
  923. int n;
  924. {
  925.     ymax_used = yscale[n];
  926. }
  927. #endif
  928. /* font work *************************************************************** */
  929. rs_font(n, ptype)
  930. int n, ptype;    /* secondary or primary, not yet used */
  931. {
  932.     int i;
  933.     struct HPFONT *cf;
  934.  
  935.     for (i=0; i<MAX_FONT; i++)
  936.     {
  937.         cf = &hpfonts[i];
  938.         if (cf->active && cf->fID == n)
  939.         {
  940.             orgenv.cur_fnt = i;
  941.             orgenv.cur_fID = n;
  942.             break;
  943.         }
  944.     }
  945.     if (i == MAX_FONT)
  946.         die("font %d not found\n",n);
  947.  
  948.     cfn = &hpfonts[orgenv.cur_fnt];
  949.     cfn->space_len = cfn->real_space_len;
  950.     curenv->hmi = cfn->space_len;
  951.     curenv->cur_fID = n;
  952. }
  953. rs_fc_ctl(n)
  954. double n;
  955. {
  956.     switch((int)n)
  957.     {
  958.     case 0:        clearallfonts();    break;
  959.     case 1:        clearfonts(TEMPORARY);    break;
  960.     case 2:        clearcurfont();        break;
  961.     case 3:        clearlastchar();    break;
  962.     case 4:        makeftype(TEMPORARY);    break;
  963.     case 5:        makeftype(PERMANENT);    break;
  964.     case 6:        cfn = getcfn();
  965.             cfn->fID = curenv->cur_fID = lastfontid;
  966.             if (!cfn->builtin)
  967.                 cfn->permtype = TEMPORARY;
  968.             break;
  969.     }
  970. }
  971. create_fnthdr(orient,symset,prop,pitch,style,stroke,face,pt)
  972. int orient,symset,prop,pitch,style,stroke,face;
  973. double pt;
  974. {
  975.     static struct HPFONT *hpf;
  976.     int i;
  977.  
  978.     if (curenv->cur_fnt < 0 || curenv->cur_fnt >= MAX_FONT)
  979.         die("don't know font %d\n",curenv->cur_fnt);
  980.     if (builtin > -1 && builtin < MAX_FONT)
  981.         hpf = &hpfonts[builtin];
  982.     else
  983.     {
  984.         if ((hpf = findlstid()) == (struct HPFONT*)NULL)
  985.         {
  986.             for (i=0; i<MAX_FONT; i++)
  987.             {
  988.                 hpf = &hpfonts[i];
  989.                 if (!hpf->active)
  990.                 {
  991.                     hpf->active = TRUE;
  992.                     hpf->fID = curenv->cur_fID = lastfontid;
  993.                     orgenv.cur_fnt = curenv->cur_fnt = i;
  994.                     break;
  995.                 }
  996.             }
  997.             if (i == MAX_FONT)
  998.                 die("too many fonts\n");
  999.         }
  1000.     }
  1001.  
  1002.     hpf->real_space_len = pitch/4;
  1003.     hpf->space_len = hpf->real_space_len;
  1004.     hpf->chars[' '].clen = hpf->space_len;
  1005.     curenv->hmi = hpf->space_len;
  1006.  
  1007.     hpf->prop_spaced = hpf->real_spaced = prop;
  1008.     hpf->primtype = TEMPORARY;    /* hp users manual hp2686a, 4-49 */
  1009.     hpf->font_atts.orient = orient;
  1010.     hpf->font_atts.symset = symset;
  1011.     hpf->font_atts.prop_spaced = prop;
  1012.     hpf->font_atts.pitch = 4.0*300.0/(double)pitch;
  1013.     hpf->font_atts.points = pt;
  1014.     hpf->font_atts.style = style;
  1015.     hpf->font_atts.stroke = stroke;
  1016.     hpf->font_atts.typeface = face;
  1017. }
  1018. char_download(c,id,left,top,width,hite,delta,buf)
  1019. int c,id,left,top,width,hite,delta;
  1020. uchar *buf;
  1021. {
  1022.     struct CHAR_BITMAP *cbm;
  1023.     struct HPFONT *cf;
  1024.     int i;
  1025.  
  1026.     if (builtin > -1 && builtin < MAX_FONT)
  1027.     {
  1028.         cf = &hpfonts[builtin];
  1029.         i = builtin;
  1030.     }
  1031.     else
  1032.     {
  1033.         for (i=0; i<MAX_FONT; i++)
  1034.         {
  1035.             cf = &hpfonts[i];
  1036.             if (cf->active && cf->fID == id)
  1037.                 break;
  1038.         }
  1039.     }
  1040.     if (i == MAX_FONT)
  1041.         die("can't download a char without font header\n");
  1042.  
  1043.     cbm = &cf->chars[c];
  1044.     curenv->cur_chr = c;
  1045.  
  1046.     if (cbm->hite && cbm->CH)
  1047.         clearchar(cbm);
  1048.  
  1049.     cbm->loffs = left;
  1050.     cbm->toffs = top;
  1051.     if (width%8)
  1052.         cbm->len = width/8 + 1;
  1053.     else cbm->len = width/8;
  1054.     cbm->hite = hite;
  1055.     if ((cbm->clen = delta/4) == 0)
  1056.         cbm->clen = 8*cbm->len;    /* yes, I do have some strange fonts */
  1057.  
  1058.     if (!cf->prop_spaced && c == 'x' && (!cf->chars[' '].clen))
  1059.         cf->space_len = cbm->clen;
  1060.  
  1061.     buf += sizeof(struct download);
  1062.     if ((cbm->CH = (uchar**)malloc(hite * sizeof(uchar *))) == (uchar **)NULL)
  1063.         die("not enough memory for bitmap array char %d\n",c);
  1064.  
  1065.     for (i=0; i<cbm->hite; i++)
  1066.     {
  1067.         if ((cbm->CH[i] = (uchar *)malloc(cbm->len)) == (uchar *)NULL)
  1068.             die("not enough memory for bitmap at char %d\n",c);
  1069.         (void)memcpy((char*)cbm->CH[i], (char*)buf, cbm->len);
  1070.         buf += cbm->len;
  1071.     }
  1072. }
  1073. /* paintwork *************************************************************** */
  1074. rs_dpi(n)
  1075. double n;
  1076. {
  1077.     curenv->dpi = (int)n;
  1078. }
  1079. rs_graphxy(n)
  1080. double n;
  1081. {
  1082.     if ((int)n)
  1083.         GRAPHX = BMX;
  1084.     else GRAPHX = 0.0;
  1085. }
  1086. rs_pix(pels, len)
  1087. uchar *pels;
  1088. int len;
  1089. {
  1090.     int i, k, localy, inc, graphx, graphy;
  1091.  
  1092.     if (see_thru)
  1093.         return;
  1094.     if (no_bitmap)
  1095.         die("no can do without a bitmap\n");
  1096.  
  1097.     inc = 300/curenv->dpi;
  1098.  
  1099.     graphy = (int)(BMY + .5);
  1100.     graphx = (int)(GRAPHX + .5);
  1101.     if (graphy < 0 || inc+graphy >= max_ln)
  1102.         return;
  1103.     localy = yscale[graphy];
  1104.  
  1105.     if (graphx + (inc*len*8) > max_col)
  1106.         len = ((max_col-graphx)/8)/inc;
  1107.  
  1108.     switch(curenv->dpi)    /* hey, who says we're trying to be efficient? */
  1109.     {
  1110.     case 300:    for (i=0; i<len; i++, pels++)
  1111.                 for (k=0; k<8; k++, graphx++)
  1112.                     if (*pels & bit[k])
  1113.                         setpix(localy, xscale[graphx]);
  1114.             break;
  1115.     case 150:    for (i=0; i<len; i++, pels++)
  1116.                 for (k=0; k<8; k++, graphx += inc)
  1117.                     if (*pels & bit[k])
  1118.                     {
  1119.                         setpix(localy, xscale[graphx]);
  1120.                         setpix(localy, xscale[graphx+1]);
  1121.  
  1122.                         setpix(localy+1, xscale[graphx]);
  1123.                         setpix(localy+1, xscale[graphx+1]);
  1124.                     }
  1125.             break;
  1126.     case 100:    for (i=0; i<len; i++, pels++)
  1127.                 for (k=0; k<8; k++, graphx += inc)
  1128.                     if (*pels & bit[k])
  1129.                     {
  1130.                         setpix(localy, xscale[graphx]);
  1131.                         setpix(localy, xscale[graphx+1]);
  1132.                         setpix(localy, xscale[graphx+2]);
  1133.  
  1134.                         setpix(localy+1, xscale[graphx]);
  1135.                         setpix(localy+1, xscale[graphx+1]);
  1136.                         setpix(localy+1, xscale[graphx+2]);
  1137.  
  1138.                         setpix(localy+2, xscale[graphx]);
  1139.                         setpix(localy+2, xscale[graphx+1]);
  1140.                         setpix(localy+2, xscale[graphx+2]);
  1141.                     }
  1142.             break;
  1143.     case 75:    for (i=0; i<len; i++, pels++)
  1144.                 for (k=0; k<8; k++, graphx += inc)
  1145.                     if (*pels & bit[k])
  1146.                     {
  1147.                         setpix(localy, xscale[graphx]);
  1148.                         setpix(localy, xscale[graphx+1]);
  1149.                         setpix(localy, xscale[graphx+2]);
  1150.                         setpix(localy, xscale[graphx+3]);
  1151.  
  1152.                         setpix(localy+1, xscale[graphx]);
  1153.                         setpix(localy+1, xscale[graphx+1]);
  1154.                         setpix(localy+1, xscale[graphx+2]);
  1155.                         setpix(localy+1, xscale[graphx+3]);
  1156.  
  1157.                         setpix(localy+2, xscale[graphx]);
  1158.                         setpix(localy+2, xscale[graphx+1]);
  1159.                         setpix(localy+2, xscale[graphx+2]);
  1160.                         setpix(localy+2, xscale[graphx+3]);
  1161.  
  1162.                         setpix(localy+3, xscale[graphx]);
  1163.                         setpix(localy+3, xscale[graphx+1]);
  1164.                         setpix(localy+3, xscale[graphx+2]);
  1165.                         setpix(localy+3, xscale[graphx+3]);
  1166.                     }
  1167.             break;
  1168.     }
  1169.     BMY += inc;
  1170.     BMX = (double)(graphx + inc);
  1171.     ymax_used = max(ymax_used,(localy-1)+inc);
  1172.     xmax_used = max(xmax_used,xscale[(graphx-1)+inc]);
  1173.     dotted = TRUE;
  1174.     virgin = FALSE;
  1175. }
  1176. /* build in rules, patterns, shades **************************************** */
  1177. rs_hsize(n)
  1178. double n;
  1179. {
  1180.     curenv->Hlen = n;
  1181. }
  1182. rs_hdsize(n)
  1183. double n;
  1184. {
  1185.     curenv->Hlen = n*300.0/720.0;
  1186. }
  1187. rs_vsize(n)
  1188. double n;
  1189. {
  1190.     curenv->Vlen = n;
  1191. }
  1192. rs_vdsize(n)
  1193. double n;
  1194. {
  1195.     curenv->Vlen = n*300.0/720.0;
  1196. }
  1197. rs_pid(n)
  1198. double n;
  1199. {
  1200.     curenv->pID = n;
  1201. }
  1202. rs_prnpat(n)
  1203. double n;
  1204. {
  1205.     struct PAT *ptr;
  1206.     int i,j,k,l,x,y,localy,localx, maxx, maxy, maxb, hlen, vlen;
  1207.  
  1208.     switch((int)n)
  1209.     {
  1210.     case 0:        k = SOLID;            break;
  1211.     case RULE:    k = RULE_BASE + curenv->pID;    break;
  1212.     case GRAY:    k = GRAY_BASE;
  1213.             if (curenv->pID >= 3 && curenv->pID <= 10)
  1214.                 k += 1;
  1215.             else if (curenv->pID >= 11 && curenv->pID <= 20)
  1216.                 k += 2;
  1217.             else if (curenv->pID >= 21 && curenv->pID <= 35)
  1218.                 k += 3;
  1219.             else if (curenv->pID >= 36 && curenv->pID <= 55)
  1220.                 k += 4;
  1221.             else if (curenv->pID >= 66 && curenv->pID <= 80)
  1222.                 k += 5;
  1223.             else if (curenv->pID >= 81 && curenv->pID <= 99)
  1224.                 k += 6;
  1225.             else k += 7;
  1226.             break;
  1227.     }
  1228.     if (k < 0 || k >= MAX_PAT)
  1229.         k = SOLID;
  1230.  
  1231.     bmx = (int)(BMX + .5);
  1232.     bmy = (int)(BMY + .5);
  1233.     hlen = (int)(curenv->Hlen + .5);
  1234.     vlen = (int)(curenv->Vlen + .5);
  1235.  
  1236.     x = bmx % 32;
  1237.     y = bmy % 32;
  1238.     maxx = min(max_col-bmx, hlen);        /* max dist in pels */
  1239.     maxb = ((maxx%8)>0) + (maxx/8);        /* max bytes */
  1240.     maxx += bmx;                /* reset to last col */
  1241.     maxy = min(max_ln-bmy, vlen);        /* max rules */
  1242.  
  1243.     ptr = &pat[k][y][x/8];
  1244.     for (j=0; j<maxy; j++, bmy++, ptr = ptr->ynext)
  1245.     {
  1246.         localy = yscale[bmy];
  1247.         localx = bmx;
  1248.         l = localx%8;
  1249.         for (i=0; localx<maxx; i++, ptr = ptr->xnext)
  1250.         {
  1251.             for (; l<8 && localx<maxx; l++, localx++)
  1252.             {
  1253.                 if (ptr->p & bit[l])
  1254.                     setpix(localy, xscale[localx]);
  1255.             }
  1256.             l = 0;
  1257.         }
  1258.         for (   ; i%4; i++, ptr = ptr->xnext)
  1259.             ;    /* reset xnext to starting pt */
  1260.     }
  1261.     virgin = FALSE;
  1262. }    
  1263. /* prose ******************************************************************* */
  1264. prt_hpchr(c)
  1265. int c;
  1266. {
  1267.     struct CHAR_BITMAP *cbm, *ubm;
  1268.     int i, j, k, curx, cury, localy, clen, before;
  1269.  
  1270.     if (see_thru)
  1271.         return;
  1272.  
  1273.     if (try_select)
  1274.         best_match();    /* speculate */
  1275.  
  1276.     switch(c)
  1277.     {
  1278.     case 0x0a:    rs_row(1.0);        return;
  1279.     case 0x0d:    rs_col((double)curenv->left_margin);    return;
  1280.     case 0x0e:    setshift(SECONDARY);    return;
  1281.     case 0x0f:    setshift(PRIMARY);    return;
  1282.     }
  1283. /* 
  1284.    now, we're thinking in terms of 300 dpi, but we're actually
  1285.    drawing at a possibly scaled resolution selected at startup,
  1286. */
  1287.     cfn = getcfn();
  1288.     cbm = &cfn->chars[c];
  1289.  
  1290.     if (cfn->prop_spaced && c > ' ')
  1291.         clen = cbm->clen;
  1292.     else clen = cfn->space_len;
  1293.     if ((!cbm->len) && c != ' ' && c != '\b')
  1294.         return;
  1295.  
  1296.     bmx = (int)(BMX + .5);
  1297.     bmy = (int)(BMY + .5);
  1298.     if (bmx + clen + cbm->loffs >= max_col)
  1299.         return;
  1300.     cury = bmy - cbm->toffs;
  1301.     if (cury < 0)
  1302.         return;
  1303.  
  1304.     if ((cury+cbm->hite) > max_ln)
  1305.         return;
  1306.  
  1307.     before = curx = bmx + cbm->loffs;
  1308.     if (c != ' ' && c != '\b')
  1309.         for (i=0; i<cbm->hite; i++)
  1310.         {
  1311.             curx = before;
  1312.             localy = yscale[cury+i];
  1313.  
  1314.             for (j=0; j<cbm->len; j++)
  1315.                 for (k=0; k<8; k++,curx++)
  1316.                     if (cbm->CH[i][j] & bit[k])
  1317.                         setpix(localy, xscale[curx]);
  1318.         }
  1319.  
  1320.     if (c > ' ')
  1321.     {
  1322.         BMX += (double)clen;
  1323.         ymax_used = max(ymax_used,yscale[cury + cbm->hite]);
  1324.         xmax_used = max(xmax_used,xscale[curx]);
  1325.     }
  1326.     else
  1327.     {
  1328.         if (c != '\b')
  1329.             BMX += (double)clen;
  1330.         else BMX -= (double)clen;
  1331.         xmax_used = max(xmax_used,xscale[bmx]);
  1332.     }
  1333.  
  1334.     if (curenv->underline)
  1335.     {
  1336.         int after = curx;
  1337.  
  1338.         ubm = &cfn->chars['_'];
  1339.         for (i=0; i<cbm->hite; i++)
  1340.         {
  1341.             curx = before;
  1342.             localy = yscale[cury+i];
  1343.  
  1344.             for (j=0; curx<after; )
  1345.                 for (k=0; k<8 && curx<after; k++,curx++)
  1346.                     if (ubm->CH[i][j] & bit[k])
  1347.                         setpix(localy,xscale[curx]);
  1348.         }
  1349.     }
  1350.     dotted = TRUE;
  1351.     virgin = FALSE;
  1352. }
  1353.  
  1354. /* MACROS ****************************************************************** */
  1355. struct MACRO *getcmc()
  1356. {
  1357.     static struct MACRO *mac;
  1358.  
  1359.     if (curenv->cur_mac < 0 || curenv->cur_mac >= MAX_MACRO)
  1360.         die("don't know macro %d\n",curenv->cur_mac);
  1361.     mac = ¯os[curenv->cur_mac];
  1362.     if (!mac->active)
  1363.         die("macro %d not active\n",curenv->cur_mac);
  1364.     return(mac);
  1365. }
  1366. uchar *rs_get_macro(into)
  1367. int *into;
  1368. {
  1369.     cmc = getcmc();
  1370.     *into = cmc->len;
  1371.     return(cmc->macro);
  1372. }
  1373. macinit()
  1374. {
  1375.     struct MACRO *mptr;
  1376.     int i;
  1377.  
  1378.     for (i=0; i<MAX_MACRO; i++)
  1379.     {
  1380.         mptr = ¯os[i];
  1381.         mptr->active = mptr->len = mptr->permtype = mptr->magic = 0;
  1382.         mptr->macro = (uchar*)NULL;
  1383.     }
  1384. }
  1385. mac_download(len,buf)
  1386. int len;
  1387. uchar *buf;
  1388. {
  1389.     uchar *ptr;
  1390.  
  1391.     cmc = getcmc();
  1392.     if (!cmc->len)
  1393.     {
  1394.         if ((cmc->macro = (uchar*)malloc(len)) == NULL)
  1395.             die("not enough memory for macro %d\n",curenv->cur_mac);
  1396.         ptr = cmc->macro;
  1397.         cmc->len = len;
  1398.     }
  1399.     else
  1400.     {
  1401.         if ((cmc->macro = (uchar*)realloc(cmc->macro,
  1402.             cmc->len + len)) == NULL)
  1403.             die("not enough memory for macro %d\n",curenv->cur_mac);
  1404.         ptr = cmc->macro + cmc->len;
  1405.         cmc->len += len;
  1406.     }
  1407.     (void)memcpy((char*)ptr, (char*)buf, len);
  1408. }
  1409. rs_macro_id(n)
  1410. double n;
  1411. {
  1412.     curenv->cur_mac = (int)n;
  1413. }
  1414. rs_mac_startdef()
  1415. {
  1416.     cmc = getcmc();
  1417.     cmc->active = TRUE;
  1418.     cmc->permtype = TEMPORARY;
  1419.     cmc->magic = FALSE;
  1420. }
  1421. rs_mac_enddef()
  1422. {
  1423.     cmc = getcmc();
  1424.     cmc->active = TRUE;
  1425. }
  1426. rs_call_macro(type)
  1427. int type;
  1428. {
  1429.     cmc = getcmc();
  1430.     if (type == SAVE)
  1431.     {
  1432.         McEnv = orgenv;
  1433.         curenv = &McEnv;
  1434.         env_saved = TRUE;
  1435.     }
  1436.     else if (type == RESTORE && env_saved)
  1437.     {
  1438.         orgenv = McEnv;
  1439.         curenv = &orgenv;
  1440.     }
  1441. }
  1442. rs_auto_enable(on)
  1443. int on;
  1444. {
  1445.     int i;
  1446.  
  1447.     if (on)
  1448.     {
  1449.         cmc = getcmc();
  1450.         cmc->magic = TRUE;
  1451.         auto_macro = curenv->cur_mac;
  1452.     }
  1453.     else
  1454.     {
  1455.         for (i=0; i<MAX_MACRO; i++)
  1456.             macros[i].magic = 0;
  1457.         auto_macro = -1;
  1458.     }
  1459.     return(auto_macro);
  1460. }
  1461. rs_del_macros(t,p)
  1462. int t,p;
  1463. {
  1464.     if (t)
  1465.         del_macros(t);
  1466.     if (p)
  1467.         del_macros(p);
  1468. }
  1469. rs_del_macro()
  1470. {
  1471.     cmc = getcmc();
  1472.     curenv->cur_mac = -1;
  1473.     del_macro(cmc);
  1474. }
  1475. rs_makemtype(what)
  1476. int what;
  1477. {
  1478.     cmc = getcmc();
  1479.     cmc->permtype = what;
  1480. }
  1481. del_macros(type)
  1482. int type;
  1483. {
  1484.     int i;
  1485.  
  1486.     for (i=0; i<MAX_MACRO; i++)
  1487.         if (macros[i].active && macros[i].permtype == type)
  1488.         {
  1489.             if (curenv->cur_mac == i)
  1490.                 curenv->cur_mac = -1;
  1491.             del_macro(¯os[i]);
  1492.         }
  1493. }
  1494. del_macro(mptr)
  1495. struct MACRO *mptr;
  1496. {
  1497.     mptr->active = mptr->len = mptr->permtype = mptr->magic = 0;
  1498.     if (mptr->macro)
  1499.     {
  1500.         free((char*)mptr->macro);
  1501.         mptr->macro = (uchar*)NULL;
  1502.     }
  1503. }
  1504. rs_auto()
  1505. {
  1506.     restore.ovly_env = orgenv;    /* save current env && bits */
  1507.     restore.sfont = sfont;
  1508.     restore.BMX = BMX;
  1509.     restore.BMY = BMY;
  1510.     restore.GRAPHX = GRAPHX;
  1511.     restore.lpi = lpi;
  1512.  
  1513.     orgenv = ovly.ovly_env;        /* install virgin defaults */
  1514.     sfont = ovly.sfont;
  1515.     BMX = ovly.BMX;
  1516.     BMY = ovly.BMY;
  1517.     GRAPHX = ovly.GRAPHX;
  1518.     lpi = ovly.lpi;
  1519.  
  1520.     curenv->cur_mac = auto_macro;    /* fetch auto_macro */
  1521.     cmc = getcmc();
  1522.  
  1523.     hptoany();            /* action */
  1524.  
  1525.     orgenv = restore.ovly_env;    /* restore real environment */
  1526.     sfont = restore.sfont;
  1527.     BMX = restore.BMX;
  1528.     BMY = restore.BMY;
  1529.     GRAPHX = restore.GRAPHX;
  1530.     lpi = restore.lpi;
  1531.                 /* mark page unused, as we only want to */
  1532.                 /* flush it if anything else goes onto it */
  1533.     dotted = 0;
  1534.     cmc = getcmc();
  1535. }
  1536. /******** loose ends */
  1537. rs_lterm(){}
  1538.  
  1539.