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