home *** CD-ROM | disk | FTP | other *** search
/ Carousel Volume 2 #1 / carousel.iso / mactosh / unix / unix_mw2.sha / dvi.c next >
Encoding:
C/C++ Source or Header  |  1985-04-26  |  12.7 KB  |  880 lines

  1. #include    <stdio.h>
  2. #include    <ctype.h>
  3.  
  4. #include    "gen.h"
  5. #include    "option.h"
  6. #include    "md.h"
  7. #include    "dvi.h"
  8. #include    "fonts.h"
  9.  
  10.  
  11. LOCAL    SP    indent        = min_to_sp(   500 );
  12. LOCAL    SP    lmargin_h    = min_to_sp(   500 );
  13. LOCAL    SP    lmargin_v    = min_to_sp(  1000 );
  14. LOCAL    SP    rmargin_v    = min_to_sp( 10500 );
  15. LOCAL    SP    rmargin_h    = min_to_sp(  6500 );
  16. LOCAL    SP    tabs[TABMAX]    = { 0, };
  17. LOCAL    int    tabcnt        = 0;
  18. LOCAL    double    spacing    = 1.0;
  19. LOCAL    int    adjust = JST_LEFT;
  20.  
  21.  
  22. LOCAL    int    cur_font;
  23. LOCAL    int    pushmax        = 0;
  24. LOCAL    POS    stack[20];
  25. LOCAL    POS    * cur;
  26.  
  27. LOCAL    FILEPTR    last_page = -1;
  28.  
  29.  
  30. LOCAL    bool    silent = FALSE;
  31.  
  32.  
  33. init()
  34.     {
  35.     int    i;
  36.  
  37.     for( i=0; i<MAX_FONTS; i++ )
  38.         {
  39.         fonts[i].f_active = FALSE;
  40.         fonts[i].f_number = -1;
  41.         }
  42.     
  43.  
  44.     preamble();
  45.  
  46.     page_no = 0;
  47.     page();
  48.  
  49.     }
  50.  
  51. finish()
  52.     {
  53.     outcmd( EOP );
  54.     postamble();
  55.     }
  56.  
  57. preamble()
  58.     {
  59.     outcmd( TEX_ID );        /* tek version 2 */
  60.     out4( scale_num );        /* num */
  61.     out4( scale_denom );        /* denom  */
  62.     out4( 1000 );            /* mag */
  63.     out1( 0 );
  64.     }
  65.  
  66. postamble()
  67.     {
  68.     long    postptr;
  69.     int    i;
  70.  
  71.  
  72.     postptr = ftell( outfd );
  73.     outcmd( POST );
  74.     out4( last_page );
  75.     out4( scale_num );        /* num */
  76.     out4( scale_denom );        /* denom  */
  77.     out4( 1000 );            /* mag */
  78.     out4( min_to_sp( 11000 ) );    /* max height (fix this) */
  79.     out4( min_to_sp( 8500 ) );    /* max width (fix this) */
  80.     out2( pushmax );        /* max stack depth  */
  81.     out2( page_no );
  82.  
  83.     /*    font definitions    */
  84.     for( i=0; i<MAX_FONTS; i++ )
  85.         {
  86.         if( fonts[i].f_number == -1 )
  87.             break;
  88.         else
  89.             def_font( i );
  90.         }
  91.     
  92.     outcmd( POSTPOST );
  93.     out4( postptr );
  94.     out1( TEX_ID );
  95.  
  96.     /* output a signature    */
  97.     for( i=0; i<4; i++ )
  98.         out1( 223 );
  99.     
  100.     postptr = ftell(outfd);
  101.     
  102.     for( i=0; i< (postptr % 4); i++ )
  103.         out1( 223 );
  104.  
  105.     }
  106.  
  107.  
  108.  
  109. /*
  110.  *    do a page eject
  111.  */
  112. LOCAL    in_page = FALSE;
  113. LOCAL    in_footer = FALSE;
  114.  
  115. page()
  116.     {
  117.  
  118.     SP    bottom_margin;
  119.  
  120.     if( in_page )
  121.         {
  122.  
  123.         if( in_footer )
  124.             {
  125.             warning( "footer extends off the bottom of the page" );
  126.             return;
  127.             }
  128.  
  129.         bottom_margin = rmargin_v;
  130.  
  131.         cur->p_v = rmargin_v;
  132.         rmargin_v = min_to_sp( 11500 );
  133.         in_footer = TRUE;
  134.  
  135.         footer();
  136.  
  137.         in_footer = FALSE;
  138.         rmargin_v = bottom_margin;
  139.  
  140.         outcmd( EOP );
  141.  
  142.         }
  143.  
  144.     bop( ++page_no );
  145.     in_page = TRUE;
  146.  
  147.     /*    potentially, don't print header on title page  */
  148.     if( page_cnt++ || !title_page )
  149.         header();
  150.  
  151.     }
  152.  
  153.  
  154.  
  155. bop( page )
  156. int    page;
  157.     {
  158.     long    lastp;
  159.     int    i;
  160.  
  161.     lastp = ftell(outfd);
  162.  
  163.     outcmd( BOP );
  164.     out4( page );
  165.     for( i=0; i<9; i++ )
  166.         out4( 0 );
  167.     out4( last_page );
  168.  
  169.     last_page = lastp;
  170.  
  171.     cur = stack;
  172.     cur->p_v = cur->p_h = cur->p_w = 
  173.     cur->p_x = cur->p_y = cur->p_z = 0;
  174.     cur_font = -1;
  175.  
  176.     /*    start us out someplace reasonable    */
  177.     out_pos( 0L, lmargin_v );
  178.  
  179.     }
  180.  
  181.  
  182. push()
  183.     {
  184.     if( cur - stack >= 19 )
  185.         fatal( "botch: stack overflow" );
  186.     
  187.     outcmd( PUSH );
  188.  
  189.     *(cur+1) = *cur;
  190.     ++cur;
  191.  
  192.     pushmax = max( pushmax, cur - stack );
  193.     }
  194.  
  195. pop()
  196.     {
  197.     if( cur <= stack )
  198.         fatal( "botch: stack underflow" );
  199.     
  200.     outcmd( POP );
  201.  
  202.     --cur;
  203.     }
  204.  
  205.  
  206.  
  207. /*
  208.  *    format another line, dvi style
  209.  */
  210.  
  211. out_line( len, line )
  212. int    len;
  213. Char    * line;
  214.     {
  215.     WORD    words[MAX_WORDS];
  216.  
  217.     int    wordpos;
  218.     int    cpos;
  219.  
  220.     int    i;
  221.     int    j;
  222.  
  223.     int    cur_font;
  224.     int    this_font;
  225.  
  226.     SP    line_length;
  227.     SP    line_height;
  228.     SP    word_length;
  229.     SP    word_space;
  230.     SP    ss_space;
  231.     SP    margin;
  232.  
  233.     /*
  234.      *    initial indent
  235.      */
  236.     margin = indent;
  237.  
  238.     /*
  239.      *    break this paragraph into words
  240.      */
  241.     for( cpos=0; cpos < len; ) {
  242.  
  243.     /*
  244.      *    skip leading spaces
  245.      */
  246.     for( ; cpos < len; cpos++ )
  247.         if( line[cpos].c_char != ' ' )
  248.             break;
  249.  
  250.     cur_font = this_font = fontno( &line[cpos] );
  251.     word_space = font_ws( cur_font );
  252.     ss_space = font_ss( cur_font );
  253.     line_height = font_height( cur_font );
  254.  
  255.     wordpos = 0;
  256.     line_length = 0;
  257.  
  258.     /* leave yourself an initial null space */
  259.     words[wordpos].wd_length = 0;
  260.     words[wordpos++].wd_flags = 0;
  261.  
  262.     while( cpos < len && line_length < (rmargin_h - margin) )
  263.         {
  264.  
  265.         if( wordpos >= MAX_WORDS )
  266.             fatal( "(botch) too many words in this paragraph" );
  267.  
  268.         if( !isspace( line[cpos].c_char ) )
  269.             {
  270.             /*
  271.              *    non space characters
  272.              */
  273.             words[wordpos].wd_flags = WD_WORD;
  274.             words[wordpos].wd_pos = cpos;
  275.  
  276.             
  277.             word_length = 0;
  278.             while( cpos < len 
  279.             &&     !isspace( line[cpos].c_char ) )
  280.                 {
  281.                 word_length += ch_wid( &line[cpos] );
  282.  
  283.                 this_font = fontno( &line[cpos] );
  284.                 line_height = max( line_height,
  285.                     font_height( this_font ) );
  286.  
  287.                 cpos++;
  288.                 }
  289.             
  290.             /*
  291.              *    this_font is guaranteed to be set
  292.              */
  293.             if( this_font != cur_font )
  294.                 {
  295.                 cur_font = this_font;
  296.                 word_space = font_ws( cur_font );
  297.                 ss_space = font_ss( cur_font );
  298.                 }
  299.             
  300.             words[wordpos].wd_length = word_length;
  301.             words[wordpos++].wd_end = cpos;
  302.  
  303.             Debug {
  304.             fprintf( stderr, "line_out: -" );
  305.             for( i=words[wordpos-1].wd_pos; i<cpos; i++ )
  306.                 fprintf( stderr, "%c", line[i].c_char );
  307.             fprintf( stderr, "- (%2.2f)\n", sp_to_in(word_length),
  308.                 sp_to_in(line_length) );
  309.             }
  310.  
  311.             /*
  312.              *    will this word overflow the line? 
  313.              */
  314.             if(line_length + word_length > (rmargin_h - margin))
  315.                 {
  316.                 cpos = words[--wordpos].wd_pos;
  317.                 break;
  318.                 }
  319.             }
  320.         else
  321.             {
  322.  
  323.             SP    space;
  324.  
  325.             /*
  326.              *    process the word gap
  327.              */
  328.             words[wordpos].wd_flags = 0;
  329.             words[wordpos].wd_tabcnt = 0;
  330.             word_length = words[wordpos].wd_length = 0;
  331.  
  332.  
  333.             /* 
  334.              *    is this an inter-word or inter-sentence gap?
  335.              */
  336.             if( wordpos > 0 
  337.             &&  (words[wordpos-1].wd_flags & WD_WORD)
  338.             &&  ispunct(line[words[wordpos-1].wd_end-1].c_char ) )
  339.                 space = ss_space;
  340.             else
  341.                 space = word_space;
  342.                 
  343.  
  344.             /* 
  345.              *    eat up those spaces.  count those tabs
  346.              */
  347.             while( cpos < len 
  348.             &&     isspace( line[cpos].c_char ) )
  349.                 {
  350.                 if( line[cpos].c_char == '\t' )
  351.                     {
  352.                     words[wordpos].wd_flags |= WD_TAB;
  353.                     words[wordpos].wd_length = word_space;
  354.                     words[wordpos].wd_tabcnt++;
  355.                     }
  356.                 else
  357.                 if( line[cpos].c_char == ' ')
  358.                     {
  359.                     word_length = 
  360.                     words[wordpos].wd_length = space;
  361.                     }
  362.                 
  363.                 if( line[cpos].c_style & ST_UL )
  364.                     words[wordpos].wd_flags |= WD_UL;
  365.  
  366.                 cpos++;
  367.                 }
  368.                 
  369.             wordpos++;
  370.                 
  371.             }
  372.         
  373.         line_length += word_length;
  374.  
  375.         }
  376.  
  377.     /*
  378.  
  379.      *    print out the words in this line
  380.      */
  381.  
  382.  
  383.     /*     move to the next line */
  384.  
  385.     down( (SP)((line_height * 1.4) * spacing) );
  386.  
  387.  
  388.     push();        /* save the margin coordinates */
  389.  
  390.     if( cur->p_v > rmargin_v )
  391.         {
  392.         page();    /* you get an implicit pop when you page */
  393.         push();
  394.         }
  395.     right( margin );
  396.  
  397.     
  398.     /*
  399.      *    remove trailing white space
  400.      */
  401.     while( wordpos > 0 )
  402.         {
  403.         if( words[wordpos-1].wd_flags & WD_WORD )
  404.             break;
  405.         else
  406.             wordpos--;
  407.         }
  408.  
  409.     /*
  410.      *    center, justify, or whatever
  411.      */
  412.     justify( words, &wordpos, &cpos, margin, (cpos >= len) );
  413.  
  414.  
  415.     /*
  416.      *    print that suckah
  417.      */
  418.     for( i=0; i < wordpos; i++ )
  419.         {
  420.         if( words[i].wd_flags & WD_WORD )
  421.             {
  422.             for( j=words[i].wd_pos; j < words[i].wd_end; j++)
  423.                 set_ch( &line[j] );
  424.             }
  425.         else
  426.             right( words[i].wd_length );
  427.         }
  428.     
  429.     Debug {
  430.     fprintf( stderr, "line %2.2f, %2.2f\n", sp_to_in(cur->p_h ),
  431.         sp_to_in(cur->p_v) );
  432.     }
  433.  
  434.     pop();        /* restore the margin coordinates */
  435.  
  436.  
  437.     /*    do any underlining that might be appropriate    */
  438.     underline( words, wordpos, line, margin );
  439.     
  440.  
  441.     margin = lmargin_h;    /* undo the indent */
  442.  
  443.     }
  444.  
  445.     }
  446.  
  447.  
  448. /*
  449.  *    justify the line.  add some tabs
  450.  */
  451. justify( words, word_count, cur_pos, margin, last_line )
  452. WORD    * words;
  453. int    * word_count;
  454. int    * cur_pos;
  455. SP    margin;
  456. int    last_line;
  457.     {
  458.  
  459.     SP    spacelen;
  460.     SP    extra_space;
  461.     SP    line_len;
  462.     SP    line_wid;
  463.     REG    WORD    * cw;
  464.     REG    double    ratio;
  465.     REG    int    i;
  466.     int    lasttab;
  467.     int    wdcnt;
  468.  
  469.     wdcnt    = *word_count;
  470.  
  471.     /*
  472.      *    take care of tabs
  473.      */
  474.     lasttab = 0;
  475.  
  476.     if( adjust == JST_LEFT || adjust == JST_ADJ )
  477.         {
  478.         REG    SP cpos = margin;
  479.         int    tb;
  480.  
  481.         /*  modify tab width to justify next word */
  482.         for( cw=words; cw < &words[wdcnt]; cw++ )
  483.             {
  484.             if( cw->wd_flags & WD_TAB )
  485.                 {
  486.                 lasttab = (cw-words) + 1;
  487.  
  488.                 for( tb=0; tb < cw->wd_tabcnt; tb++ )
  489.                     {
  490.  
  491.                     for( i=0; i<tabcnt; i++ )
  492.                         if( cpos < tabs[i] )
  493.                             break;
  494.  
  495.                     if( i < tabcnt )
  496.                         cw->wd_length = tabs[i] - cpos;
  497.  
  498.                     }
  499.                 
  500.                 }
  501.             
  502.             /*  is the line now too large to fit? */
  503.             if( cpos + cw->wd_length > rmargin_h )
  504.                 break;
  505.                 
  506.             cpos += cw->wd_length;
  507.  
  508.             }
  509.         
  510.         /*    shorten this line.  tabs expanded it too much */
  511.         if( cw != &words[wdcnt] )
  512.             {
  513.             *cur_pos = cw->wd_pos;
  514.             wdcnt = *word_count = cw - words;
  515.             }
  516.         
  517.         /*    don't justify words before a tab stop    */
  518.         for( cw=words; cw < &words[lasttab]; cw++ )
  519.             margin += cw->wd_length;
  520.  
  521.         }
  522.     
  523.     /* figure out the current length of this line */
  524.     for  ( line_len = 0, cw = &words[lasttab]; cw < &words[wdcnt]; cw++ )
  525.         line_len += cw->wd_length;
  526.     
  527.     line_wid = rmargin_h - margin;
  528.  
  529.  
  530.     switch( adjust )
  531.         {
  532.         case JST_LEFT:
  533.             break;
  534.  
  535.         case JST_ADJ:
  536.             
  537.             if( last_line || line_len <= 0 )
  538.                 break;
  539.  
  540.             spacelen = 0;
  541.  
  542.             for( cw = &words[lasttab]; cw < &words[wdcnt]; cw++ )
  543.                 {
  544.                 if( !(cw->wd_flags & WD_WORD) )
  545.                     spacelen += cw->wd_length;
  546.                 }
  547.                 
  548.             extra_space = (line_wid-line_len) + spacelen;
  549.             ratio = ((double)extra_space) / spacelen;
  550.  
  551.  
  552.             for( cw = &words[lasttab]; cw < &words[wdcnt]; cw++ )
  553.                 if( !(cw->wd_flags & WD_WORD) )
  554.                     cw->wd_length = cw->wd_length * ratio; 
  555.             break;
  556.  
  557.  
  558.         case JST_RIGHT:
  559.             words[0].wd_length = line_wid - line_len;
  560.             break;
  561.  
  562.         case JST_CENTER:
  563.             words[0].wd_length = (line_wid - line_len) / 2;
  564.             break;
  565.         }
  566.     }
  567.  
  568.  
  569. underline( words, length, line, margin )
  570. WORD    * words;
  571. int    length;
  572. Char    * line;
  573. SP    margin;
  574.     {
  575.  
  576.     SP    cpos;
  577.     SP    ul_start;
  578.     REG    int    chpos;
  579.     REG    WORD    * wd;
  580.  
  581.     bool    ul    = FALSE;
  582.  
  583.     if( silent )
  584.         return;
  585.  
  586.     for( cpos = 0, wd = words; wd < &words[length]; wd++  )
  587.         {
  588.  
  589.         if( wd->wd_flags & WD_WORD )
  590.             {
  591.  
  592.             for( chpos = wd->wd_pos; chpos < wd->wd_end; chpos++ )
  593.                 {
  594.                 if( line[chpos].c_style & ST_UL && !ul )
  595.                     {
  596.                     ul_start = cpos;
  597.                     ul = TRUE;
  598.                     }
  599.                 else
  600.                 if( !(line[chpos].c_style & ST_UL) && ul )
  601.                     {
  602.                     ul = FALSE;
  603.  
  604.                     t_rule( margin+ul_start, mpt_to_sp(250),
  605.                         cpos-ul_start );
  606.                     }
  607.                 
  608.                 cpos += ch_wid( &line[chpos] );
  609.                 }
  610.             }
  611.         else
  612.             {
  613.  
  614.             if( (wd->wd_flags & WD_UL) &&  !ul )
  615.                 {
  616.                 ul = TRUE;
  617.                 ul_start = cpos;
  618.                 }
  619.             else
  620.             if( !(wd->wd_flags & WD_UL) &&  ul )
  621.                 {
  622.                 ul = FALSE;
  623.  
  624.                 t_rule( margin+ul_start, mpt_to_sp(250), 
  625.                     cpos-ul_start );
  626.                 }
  627.  
  628.             cpos += wd->wd_length;
  629.             }
  630.         
  631.         }
  632.     if( ul )
  633.         t_rule( margin+ul_start, mpt_to_sp(250), cpos-ul_start );
  634.  
  635.     }
  636.  
  637.  
  638. /*
  639.  *    gimme a transparent rule (assume you are at left margin to start)
  640.  */
  641. t_rule( start, h, w )
  642. SP    start;
  643. SP    h;
  644. SP    w;
  645.     {
  646.  
  647.     push();
  648.  
  649.     right( start );
  650.  
  651.     down( (SP)(h + mpt_to_sp(400)) );
  652.  
  653.     outcmd( PUTRULE );
  654.     out4( h );
  655.     out4( w );
  656.  
  657.     pop();
  658.  
  659.     }
  660.  
  661.  
  662. /*
  663.  *    put a character at the current position and advance
  664.  */
  665. set_ch( lptr )
  666. Char    * lptr;
  667.     {
  668.     int    font;
  669.  
  670.     if( silent )
  671.         return;
  672.  
  673.     if( (font = fontno(lptr)) != cur_font )
  674.         {
  675.  
  676.         cur_font = font;
  677.         if( !fonts[font].f_active )
  678.             def_font( font );
  679.  
  680.         outcmd( FONT0 + font );
  681.  
  682.         }
  683.  
  684.     outcmd( SET0 + lptr->c_char );
  685.  
  686.     cur->p_h += ch_wid( lptr );
  687.  
  688.     }
  689.  
  690.  
  691.  
  692. /*
  693.  *    measure the size of the footer
  694.  */
  695. init_footer()
  696.     {
  697.  
  698.     SP    top;
  699.  
  700.     push();
  701.     silent = TRUE;
  702.  
  703.     top = cur->p_v = min_to_sp( 500 );
  704.  
  705.     footer();
  706.  
  707.     rmargin_v = min_to_sp( 10500 ) - (cur->p_v - top);
  708.  
  709.     if( verbose )
  710.         fprintf( stderr, "footer length %3.2f in.\n", 
  711.             sp_to_in( cur->p_v - top ) );
  712.  
  713.     silent = FALSE;
  714.     pop();
  715.  
  716.     }
  717.     
  718.  
  719. set_ruler( lmargin, rmargin, indnt, space, just )
  720. PIX    lmargin;
  721. PIX    rmargin;
  722. PIX    indnt;
  723. int    space;
  724. int    just;
  725.     {
  726.  
  727.     lmargin_h = pix_to_sp( lmargin ) + min_to_sp( 1000 );;
  728.     rmargin_h = pix_to_sp( rmargin ) + min_to_sp( 1000 );;
  729.     indent = pix_to_sp( indnt ) + min_to_sp( 1000 );
  730.     adjust = just;
  731.  
  732.     switch( space )
  733.         {
  734.         case S_SINGLE:
  735.             spacing = 1.0;
  736.             break;
  737.  
  738.         case S_ONEANDHALF:
  739.             spacing = 1.5;
  740.             break;
  741.  
  742.         case S_DOUBLE:
  743.             spacing = 2.0;
  744.             break;
  745.  
  746.         default:
  747.             warning( "unknown line spacing" );
  748.             spacing = 1.0;
  749.             break;
  750.         }
  751.  
  752.     }
  753.  
  754.  
  755. /*    single level save    */
  756. LOCAL    SP    o_rmargin_h;
  757. LOCAL    SP    o_lmargin_h;
  758. LOCAL    SP    o_indent;
  759. LOCAL    double    o_spacing;
  760. LOCAL    int    o_adjust;
  761. LOCAL    SP    o_tabs[TABMAX];
  762. LOCAL    int    o_tabcnt;
  763.  
  764. save_ruler()
  765.     {
  766.     int    i;
  767.  
  768.     o_rmargin_h = rmargin_h;
  769.     o_lmargin_h = lmargin_h;
  770.     o_indent = indent;
  771.     o_spacing = spacing;
  772.     o_adjust = adjust;
  773.  
  774.     for( o_tabcnt = tabcnt, i=0; i<o_tabcnt; i++ )
  775.         o_tabs[i] = tabs[i];
  776.  
  777.     }
  778.  
  779. restore_ruler()
  780.     {
  781.     int    i;
  782.  
  783.     rmargin_h = o_rmargin_h;
  784.     lmargin_h = o_lmargin_h;
  785.     indent = o_indent;
  786.     spacing = o_spacing;
  787.     adjust = o_adjust;
  788.  
  789.     for( tabcnt = o_tabcnt, i=0; i<tabcnt; i++ )
  790.         tabs[i] = o_tabs[i];
  791.  
  792.     }
  793.  
  794.  
  795.  
  796.  
  797. clr_tabs()
  798.     {
  799.     tabcnt = 0;
  800.     }
  801.  
  802. set_tab( tab )
  803. PIX    tab;
  804.     {
  805.     tabs[tabcnt++] = pix_to_sp( tab ) + min_to_sp( 1000 );
  806.     }
  807.  
  808.  
  809. cr()
  810.     {
  811.     out_pos( lmargin_h, cur->p_v );
  812.     }
  813.  
  814.  
  815. right( h )
  816. SP    h;
  817.     {
  818.  
  819.     if( h == 0 )
  820.         return;
  821.  
  822.     outcmd( RIGHT4 );
  823.     out4( h );
  824.  
  825.     cur->p_h += h;
  826.  
  827.     }
  828.  
  829. down( v )
  830. SP    v;
  831.     {
  832.  
  833.     outcmd( DOWN4 );
  834.     out4( v );
  835.  
  836.     cur->p_v += v;
  837.  
  838.     }
  839.  
  840.  
  841. /*
  842.  *    go to the indicated position
  843.  */
  844. out_pos( h, v)
  845. long    h;
  846. long    v;
  847.     {
  848.  
  849.     if( h != cur->p_h )
  850.         {
  851.         outcmd( X4 );
  852.         out4( h - cur->p_h );
  853.         }
  854.     if( v != cur->p_v )
  855.         {
  856.         outcmd( Y4 );
  857.         out4( v - cur->p_v );
  858.         }
  859.  
  860.     cur->p_h = h;
  861.     cur->p_v = v;
  862.  
  863.     }
  864.  
  865. out( outfd, length, value )
  866. FILE    * outfd;
  867. int    length;
  868. long    value;
  869.     {
  870.     REG    int    i;
  871.     int    v;
  872.  
  873.     for( i=0; i<length; i++ )
  874.         {
  875.         v = value >> (((length-1) - i) * 8);
  876.         putc( v & 0xff, outfd );
  877.         }
  878.     
  879.     }
  880.