home *** CD-ROM | disk | FTP | other *** search
/ Carousel Volume 2 #1 / carousel.iso / mactosh / unix / scribepi.sha / apollo_scribepic.c next >
Encoding:
C/C++ Source or Header  |  1985-08-29  |  28.0 KB  |  819 lines

  1. /***********************************************************************
  2. *                                                                      *
  3. *     University of Utah - APOLLO Graphics Helper Routine              *
  4. *                  Copyright 1985 University of Utah                   *
  5. *                                                                      *
  6. *                         SCRIBEPIC                                    *
  7. *                                                                      *
  8. *      Module: Main module (scribepic.c)                               *
  9. *                                                                      *
  10. *   Version    Date    Person          Description                     *
  11. *----------------------------------------------------------------------*
  12. *      0.1   2-Jun-85  J. Schimpf      Make a MACPAINT style file      *
  13. *                                      from a screen                   *
  14. *      0.2   5-Jun-85  J. Schimpf      Use level 2 I/O for speed       *
  15. *      0.3   5-Jun-85  J. Schimpf      Added read GMF format stuff     *
  16. *      0.4  14-Jun-85  J. Schimpf      Don't invert windows only       *
  17. *                                      screens                         *
  18. *      0.5  26-Jun-85  J. Schimpf      Added margin,height & POSTSCRIPT*
  19. *                                      info so SCRIBE picture file     *
  20. *                                      can be built                    *
  21. *                                                                      *
  22. *   Description of code:                                               *
  23. *      Copy Apollo Window or Screen to a file suitable for use in a    *
  24. *      SCRIBE @picture command.  (See Below)                           *
  25. *      File produced is a POSTSCRIPT program with the run length       *
  26. *      encoded version of the bit map following it                     *
  27. *                                                                      *
  28. *      SCRIBE Picture Command is of the form:                          *
  29. *                                                                      *
  30. *              @picture(size=2inch, ScalableLaser=[mypic.ps])          *
  31. *                                                                      *
  32. *      And the command used to make the mypic.ps file (assuming you    *
  33. *      have a window or screen bit map in the file screen) is          *
  34. *                                                                      *
  35. *              scribepic -f screen -h 2 -m 6 -o mypic.ps               *
  36. *                                                                      *
  37. *              This sets the height at 2 inches, the distance between  *
  38. *              margins as 6 inches and the output file as mypic.ps     *
  39. *              the other values are defaulted (see below)              *
  40. *                                                                      *
  41. *      SYNTAX: scribepic -f (filename) [-i] [-b]                       *
  42. *                                    [-o <output file>]                *
  43. *                                    [-m <page margin (in)>]           *
  44. *                                    [-h <Picture height(in)>]         *
  45. *                                    [-P <POSTSCRIPT CODE FILE>]       *
  46. *                                    [-u <Translate picture UP (in)>]  *
  47. *                                                                      *
  48. *      Parameter       Use                     Default                 *
  49. *----------------------------------------------------------------------*
  50. *              ****** FILE CONTROL *****                               *
  51. *                                                                      *
  52. *      -f <filename>   Input Screen file       NONE - ERROR if missing *
  53. *      -b              Input is APOLLO BM file GMF file assumed        *
  54. *                                              (All STD screens &      *
  55. *                                               Apollo windows are GMF)*
  56. *      -i              Invert Input file       NOT Inverted            *
  57. *      -o <filename>   Output Picture file     STDOUT                  *
  58. *                                                                      *
  59. *              ***** SCRIBE FORMAT CONTROL *****                       *
  60. *                                                                      *
  61. *      -m <Margin>     Page margin  (inches)   6 inches                *
  62. *      -h <Height>     Picture heigh (inches)  2 inches                *
  63. *      -u <Move up>    Move picture up page    0 inches                *
  64. *                                                                      *
  65. *              ***** POSTSCRIPT CONTROL ****                           *
  66. *                                                                      *
  67. *      -P <CODE FILE>  Postscript code         ~/bin/scribepic.ps      *
  68. *                                                                      *
  69. *----------------------------------------------------------------------*
  70. *                                                                      *
  71. *      Output File is of the form:                                     *
  72. *      <POSTSCRIPT CODE>                                               *
  73. *      <Invert> <X size> <Y size> <Margin> <Height> <Move UP>          *
  74. *      <Run length encoded bitmap (see cmprs_line)                     *
  75. *                                                                      *
  76. *   Procedures:                                                        *
  77. *                                                                      *
  78. *   Written+   Name                    Description                     *
  79. *----------------------------------------------------------------------*
  80. *      y       main()                  Bring in bit map to memory bm   *
  81. *      y       get_bitmap()            Read bitmap file                *
  82. *      y       get_line()              Get one scan line               *
  83. *      y       cmprs_line()            Compress 1 scan line            *
  84. *      y       out_buf()               Output one scan line as hex     *
  85. *      y       write_buf()             Output one character to output  *
  86. *      y       hex_con()               Convert nibble to ASCII hex     *
  87. *                                                                      *
  88. *      EXTERNAL                                                        *
  89. *              gmf_inq()               Get info on GMF file            *
  90. *                                                                      *
  91. *      + (N - no; Y - yes (y - untested); P - partially written)       *
  92. *                                                                      *
  93. ***********************************************************************/
  94.                              
  95. /*  Include files ***********/
  96.  
  97. #include <stdio.h>
  98. #include "/sys/ins/base.ins.c"
  99. #include "/sys/ins/gpr.ins.c"
  100. #include "/sys/ins/gmf.ins.c"
  101.  
  102. /*  Global Constants *******/
  103.                          
  104. #define GPR_MODE       gpr_$borrow     /*  Display MODE */
  105. #define TRUE           1
  106. #define FALSE          0
  107.  
  108. #define SCREEN_X       1024            /* DN 300 Screen constants */
  109. #define SCREEN_Y       800
  110. #define SCREEN_WD      64
  111.  
  112. #define MAX_SCAN_LINE  256
  113. #define BUF_SZ         50000
  114.  
  115. #define LF             0x0a
  116.  
  117. #define SAME           1
  118. #define NOTSAME        0             
  119.  
  120. /*  Flags & defaults for user */
  121.  
  122. #define INVFLAG        'i'
  123. #define FFLAG          'f'
  124. #define BITFLAG        'b'
  125. #define OUTFLAG        'o'
  126. #define MARGFLAG       'm'
  127. #define HEIGHTFLAG     'h'
  128. #define UPFLAG         'u'
  129. #define POSTFLAG       'P'
  130.  
  131. #define OUTDEF         stdout
  132. #define POSTDEF        "//a/utah/printers/scribe/scribepic.ps"
  133.  
  134. #define MARGINDEF      6       /*  Assume 6" margins */
  135. #define HEIGHTDEF      2       /*  Assume 2" height */
  136. #define UPDEF          0       /*  Assume 0" move UP */
  137.  
  138. /*  Globals used by all routines */
  139.  
  140.        int     line_sz;        /* # Bytes/scan line */
  141.        int     separation;     /* Bytes between scan lines */
  142.        int     x_size,y_size;  /* Raster size       */
  143.        char    *bitp;          /* Pointer to bitmap */
  144.        
  145. main(argc,argv)
  146. int argc;
  147. char *argv[];
  148. {
  149.  
  150.        name_$pname_t   filename;
  151.        gpr_$bitmap_desc_t     bitmap,get_bitmap(),get_gmf();
  152.        status_$t       status;
  153.        int psn = 0;
  154.        int outnum;
  155.        int             n,i,j,size;
  156.        int             invert,bitfile;
  157.        unsigned char   scanline[MAX_SCAN_LINE];
  158.        float height,margin,up,atof();
  159.        FILE *fopen(),*fout,*fpost;
  160.        char postfile[30],outfile[30];
  161.            
  162.        /*  Scan command line for input file & other stuff, set other stuff
  163.            for defaults
  164.        */                                             
  165.       
  166.        /*  Set default file control stuff */
  167.        
  168.        invert  = TRUE;
  169.        bitfile = FALSE;
  170.        filename[0] = '\0';
  171.  
  172.        fout = OUTDEF;
  173.        strcpy(postfile,POSTDEF);
  174.  
  175.        /*  Set default SCRIBE stuff */
  176.  
  177.        height = HEIGHTDEF;
  178.        margin = MARGINDEF;
  179.        up = UPDEF;
  180.                   
  181.        /*  Now scan command line and set all the stuff */
  182.       
  183.        for( i=1; i<argc; i++ )
  184.        {
  185.                if( argv[i][0] == '-' )
  186.                {
  187.                        switch( argv[i][1] ) {
  188.                        
  189.                        case INVFLAG:   invert = FALSE;
  190.                                        break;
  191.  
  192.                        case FFLAG:     strcpy(filename,argv[i+1]);
  193.                                        break;
  194.  
  195.                        case BITFLAG:   bitfile = TRUE;
  196.                                        break;
  197.  
  198.                        case OUTFLAG:   strcpy(outfile,argv[i+1]);
  199.                                        break;
  200.  
  201.                        case POSTFLAG:  strcpy(postfile,argv[i+1]);
  202.                                        break;
  203.  
  204.                        case MARGFLAG:  margin = atof( argv[i+1] );
  205.                                        break;
  206.  
  207.                        case HEIGHTFLAG: height = atof( argv[i+1] );
  208.                                        break;
  209.  
  210.                        case UPFLAG:    up = atof( argv[i+1] );
  211.                                        break;
  212.  
  213.                        }
  214.                }
  215.        }
  216.  
  217.        if( strlen(filename) == 0 )
  218.        {
  219.                fprintf(stderr,"*** scribepic: Syntax No filename input\n");
  220.                exit(-1);
  221.        }
  222.  
  223.        /*  Open Output & postscript files - use defaults if failure */
  224.  
  225.        if( (fout = fopen(outfile,"w")) == NULL )
  226.        {
  227.                printf("*** scribepic: Bad output file %s\n",outfile);
  228.                printf("**** Stdout used\n");
  229.                fout = OUTDEF;
  230.        }
  231.  
  232.        if( (fpost = fopen(postfile,"r")) == NULL )
  233.        {
  234.                printf("*** scribepic:Cannot find POSTSCRIPT file %s\n",postfile);
  235.                printf("**** %s used\n",POSTDEF);
  236.                strcpy(postfile,POSTDEF);
  237.                if( ( fpost = fopen(postfile,"r")) == NULL )
  238.                {
  239.                        fprintf(stderr,"scribepic:Cannot find DEFAULT POSTSCRIPT file %s\n",postfile);
  240.                        exit(-1);
  241.                }
  242.        }
  243.  
  244.        /*  Get fileid associated with output */
  245.  
  246.        outnum = fileno( fout );
  247.  
  248.        /*  Get the bit map on the screen where we can fiddle with it */
  249.  
  250.        if( bitfile )
  251.                bitmap = get_bitmap(filename);
  252.        else
  253.                bitmap = get_gmf(filename);
  254.  
  255.        if( bitmap == NULL )
  256.        {
  257.                fprintf(stderr,"makemap: Bad bit map file - %s\n",filename);
  258.                exit(-1);
  259.        }
  260.  
  261.        /*  Initialize the buffer */
  262.  
  263.        out_buf(scanline,-1,outnum);
  264.  
  265.        /*  Put out the POSTSCRIPT file first to output */
  266.  
  267.        while( 1 )
  268.        {
  269.                fgets(scanline,MAX_SCAN_LINE,fpost);
  270.                if( feof( fpost ) )
  271.                        break;
  272.                fputs(scanline,fout);
  273.        }
  274.        fflush(fout);
  275.  
  276.        /*  Put out the x & y size of the file first in the file
  277.            NOTE: X size is # bytes/line
  278.        */
  279.  
  280.        sprintf(scanline,"%d %d %d %f %f %f\n",
  281.                invert,line_sz,y_size,margin,height,up);
  282.        for( i=0; i< strlen(scanline); i++ )
  283.                write_buf(scanline[i],0,outnum);
  284.  
  285.        /*  Loop through scan lines reading data and compressing it for output */
  286.  
  287.        for( i=0; i<y_size; i++ )
  288.        {
  289.                size = get_line(bitp,i,line_sz,separation,scanline);
  290.                size = comprs_line(scanline,size);
  291.                out_buf(scanline,size,outnum);
  292.        }
  293.  
  294.        /*  Flush the buffer */
  295.  
  296.        out_buf(scanline,-1,outnum);
  297.  
  298.        gpr_$terminate(0,status); 
  299. }
  300.  
  301. /***************************************************************************
  302. *
  303. *      GET_BITMAP(filename)
  304. *
  305. *      INPUT: filename         - Bitmap file name
  306. *
  307. *      OUTPUT: Bitmap discriptor NULL if not found
  308. *              line_sz         - # Bytes/scan line set
  309. *              separation      - Bytes between scan lines
  310. *              x_size,y_size   - Size of map in raster units
  311. *
  312. *      SIDE EFFECTS:   Bit map moved into virtual memory
  313. *                      Graphics inited for BORROW mode
  314. *
  315. ****************************************************************************/
  316.  
  317. gpr_$bitmap_desc_t get_bitmap(filename)
  318. char filename[];
  319. {
  320.        gpr_$window_t                       window;
  321.        gpr_$bmf_group_header_array_t       header;
  322.        short                               length,sep;
  323.        gpr_$plane_t                        hi_plane = 7;
  324.        short                               groups;
  325.        gpr_$bitmap_desc_t                  bitmap,filebm;
  326.        status_$t                           status;
  327.        gpr_$version_t                      version;
  328.        gpr_$attribute_desc_t               attribs;
  329.        boolean                             created;
  330.  
  331.        length = strlen(filename);
  332.  
  333.        /*  Init the bit map dimensions  */
  334.  
  335.        window.window_base.x_coord = (short) 0;
  336.        window.window_base.y_coord = (short) 0;
  337.        window.window_size.x_size  = (short) SCREEN_X;
  338.        window.window_size.y_size  = (short) SCREEN_Y;
  339.  
  340.        /*  Initialize by borrowing the display  */
  341.  
  342.        gpr_$init(GPR_MODE,1,window.window_size,hi_plane,bitmap,status);
  343.                                                                     
  344.        /*  Set up an attribute block for the Xfer */
  345.  
  346.        gpr_$allocate_attribute_block(attribs,status);
  347.  
  348.        /*  Open the bit map file */
  349.                                                      
  350.        gpr_$open_bitmap_file(gpr_$readonly,filename,length,
  351.             version,window.window_size,groups,header,
  352.             attribs,filebm,created,status);
  353.         
  354.        /*  If it didn't open tell user and quit */
  355.  
  356.        if( status.fail )
  357.        {
  358.                bitmap = NULL;
  359.                gpr_$terminate(0,status); 
  360.                return( bitmap );
  361.        }
  362.          
  363.        /*  Move Bit map to internal bit map */
  364.  
  365.        gpr_$pixel_blt(filebm,window,window.window_base,status);
  366.  
  367.        /*  Get the information on this bitmap
  368.            Scan line separation
  369.            X_size in bytes
  370.            Y_size in scan lines
  371.            Scan line separation
  372.        */
  373.  
  374.        gpr_$inq_bitmap_pointer(bitmap,bitp,sep,status);          
  375.        line_sz = header[0].bytes_per_line;
  376.        separation = 2*sep;
  377.        x_size = window.window_size.x_size;
  378.        y_size = window.window_size.y_size;
  379.  
  380.        return( bitmap );
  381. }
  382.  
  383. /***************************************************************************
  384. *
  385. *      GET_GMF(filename)
  386. *
  387. *      INPUT: filename         - GMF file name
  388. *
  389. *      OUTPUT: Bitmap discriptor NULL if not found
  390. *              line_sz         - # Bytes/scan line set
  391. *              separation      - Bytes between scan lines
  392. *              x_size,y_size   - Size of map in raster units
  393. *
  394. *      SIDE EFFECTS:   Bit map moved into virtual memory
  395. *                      Graphics inited for BORROW mode
  396. *                      If this is a full window then DON'T invert it before
  397. *                      use
  398. *
  399. ****************************************************************************/
  400.  
  401. gpr_$bitmap_desc_t get_gmf(filename)
  402. char filename[];
  403. {
  404.        gpr_$window_t                       window;
  405.        gpr_$bmf_group_header_array_t       header;
  406.        short                               length,sep;
  407.        gpr_$plane_t                        hi_plane = 7;
  408.        short                               groups,words,bpi,x_dim,y_dim;
  409.        gpr_$bitmap_desc_t                  bitmap,filebm;
  410.        status_$t                           status;
  411.        gpr_$version_t                      version;
  412.        gpr_$attribute_desc_t               attribs;
  413.        stream_$id_t                        stream;
  414.        length = strlen(filename);
  415.  
  416.        /*  Init the bit map dimensions  */
  417.  
  418.        window.window_base.x_coord = (short) 0;
  419.        window.window_base.y_coord = (short) 0;
  420.        window.window_size.x_size  = (short) SCREEN_X;
  421.        window.window_size.y_size  = (short) SCREEN_Y;
  422.  
  423.        /*  Initialize by borrowing the display  */
  424.  
  425.        gpr_$init(GPR_MODE,1,window.window_size,hi_plane,bitmap,status);
  426.                                                                     
  427.        /*  Set up an attribute block for the Xfer */
  428.  
  429.        gpr_$allocate_attribute_block(attribs,status);
  430.  
  431.        /*  Open the GMF file and read it in */
  432.  
  433.        gmf_$open(filename,length,gmf_$read,stream,status);
  434.  
  435.        /*  If it didn't open tell user and quit */
  436.  
  437.        if( status.fail )
  438.        {
  439.                bitmap = NULL;
  440.                gpr_$terminate(0,status); 
  441.                return( bitmap );
  442.        }
  443.                                          
  444.        /*  Get access and display information, bitmap & GMF stuff */
  445.  
  446.        gpr_$enable_direct_access(status);    
  447.  
  448.        gpr_$inq_bitmap_pointer(bitmap,bitp,sep,status);
  449.        separation = 2*sep;
  450.                      
  451.        /*  Get information on GMF file, use JW's function */
  452.  
  453.        gmf_$inquire(&stream,&x_dim,&y_dim,&words,&status);
  454.  
  455.        /*  ***** words is really # 16 bits words/line - just divide
  456.            x_dim by 16 to get what we want  We used it to hold bits/inch
  457.            which we will throw away
  458.         */
  459.  
  460.        words = x_dim/(short)16;
  461.        line_sz = 2 * (int) words;
  462.        x_size  = (int) x_dim;
  463.        y_size  = (int) y_dim;
  464.  
  465.        /*  Set window for blt */
  466.  
  467.        window.window_size.x_size  = x_dim;
  468.        window.window_size.y_size  = y_dim;
  469.        
  470.        /*  Move the plane onto the bit map */
  471.  
  472.        gmf_$restore_plane(stream,(short)SCREEN_X,(short)SCREEN_Y,
  473.                           (short)SCREEN_WD,bitp,bpi,status);
  474.  
  475.        /*  Since this is a GMF we have to invert it (GMF stuff comes out
  476.            inverted) but only if it is a WINDOW if screen leave it alone
  477.        */
  478.                                                                         
  479.        if( x_size == SCREEN_X && y_size == SCREEN_Y )
  480.        {
  481.                gpr_$set_raster_op((short)0,(short)10,status);   /*  Compliment */
  482.                gpr_$pixel_blt(bitmap,window,window.window_base,status);
  483.        }
  484.  
  485.        /*  Close GMF & return bit map to user */
  486.  
  487.        gmf_$close(stream,status);
  488.        return( bitmap );
  489. }
  490.  
  491. /****************************************************************************
  492. *
  493. *      GET_LINE(ptr,line,size,sep,out)
  494. *
  495. *      INPUT:  ptr             - Pointer to UL corner of BM
  496. *              line            - Scan line # to read out
  497. *              size            - # bytes/scan line
  498. *              sep             - Gaps between scan lines
  499. *              
  500. *      OUTPUT: scanline        - Scan line data 
  501. *              # Bytes in scan line
  502. *
  503. *****************************************************************************/
  504.  
  505. get_line(ptr,line,size,sep,out)
  506. unsigned char *ptr,out[];
  507. int line,size,sep;
  508. {
  509.        int i,j;
  510.        unsigned char *locptr;
  511.  
  512. /*---------------------------------------------------------------------------
  513.  
  514.        OPERATION:
  515.  
  516.        1) Set bit pointer to point to this scan line
  517.        2) Move scan line data to scanline
  518.        3) Return count
  519.  
  520. ----------------------------------------------------------------------------*/
  521.  
  522.        locptr = ptr + sep*line;
  523.  
  524.        for( i=0; i<size; i++ )
  525.        {
  526.                out[i] = *(locptr);
  527.                *(locptr++) = ~out[i];
  528.        }
  529.  
  530.        return( size );
  531. }
  532.  
  533. /*****************************************************************************
  534. *
  535. *      COMPRS_LINE(line,size)
  536. *
  537. *      INPUT:  line            - Scan line to be compressed
  538. *              size            - # bytes in scan line
  539. *
  540. *      OUTPUT: size of new scan line
  541. *              line compressed as shown below
  542. *
  543. *      Compression is as follows:
  544. *
  545. *      <CNT><Byte><Byte>...    If <CNT>  < 0x80  i.e. <CNT> different bytes
  546. *      <CNT><Byte>             If <CNT>  > 0x80  i.e. <CNT> repeated bytes
  547. *
  548. *****************************************************************************/
  549.  
  550. comprs_line(line,size)
  551. unsigned char line[];
  552. int size;
  553. {
  554.        int i,j,k,cntpsn,count;
  555.        int flag;
  556.        unsigned char pixel;
  557.        unsigned char out[MAX_SCAN_LINE];
  558.  
  559. /*-----------------------------------------------------------------------------
  560.        
  561.        OPERATION:
  562.  
  563.        1) Init counters, Check line - if first two byte == set flag
  564.           flag for same else, set for NOTSAME
  565.        2) Reserve a slot in the output list for the count
  566.        3) 
  567.  
  568. ------------------------------------------------------------------------------*/
  569.  
  570.  
  571.                       
  572.        i = 0;
  573.        j = 2;
  574.        if( line[0] == line[1] )
  575.        {
  576.                flag = SAME;
  577.                cntpsn = 0;
  578.                out[1] = line[0];
  579.        }
  580.        else
  581.        {
  582.                flag = NOTSAME;
  583.                cntpsn = 0;
  584.                out[1] = line[0];
  585.        }
  586.  
  587.        while( i < size )
  588.        {
  589.                switch( flag ) {
  590.                                 
  591.        /*  Same case see how far the run goes then update stuff */
  592.  
  593.                case SAME:      count = 0;
  594.                                for( k=i; k<size; k++ )
  595.                                {
  596.                                        if( out[j-1] != line[k] )
  597.                                                break;
  598.                                        else
  599.                                                count++;
  600.                                }
  601.  
  602.        /* If count is zero then just skip all this stuff and try again
  603.            with the flag the other way
  604.        */
  605.                                if( count != 0 )
  606.                                {
  607.  
  608.        /*  Ok update the count and save the byte in the output line
  609.            NOTE: Count is just 2's compliment of the value
  610.        */
  611.                                        pixel = -1 * (count-1);
  612.                                        out[cntpsn] = 0xff & pixel;
  613.  
  614.        /*  Set the flag for the other & go to advance j to next frame */
  615.                        
  616.                                        flag = NOTSAME;
  617.                                }
  618.                                else
  619.                                        flag = NOTSAME;
  620.                                break;
  621.                                 
  622.        /*  Not the same, look for a run of something if found quit */
  623.  
  624.                case NOTSAME:   count = 0;
  625.                                for( k=i+1; k<size; k++ )
  626.                                {
  627.                                        if( out[j-1] == line[k] )
  628.                                                break;
  629.                                        else
  630.                                        {
  631.                                                count++;
  632.                                                out[j++] = line[k];
  633.                                        }
  634.                                }
  635.        /*  If count is zero then skip all the updating stuff and just try the
  636.            other method
  637.        */
  638.                                if( count != 0 )
  639.                                {
  640.  
  641.                                        out[cntpsn] = count - 1;
  642.  
  643.        /*  Set the flag for the other and back up the psn to get the
  644.            start of the run
  645.        */
  646.                                            
  647.                                        k = k - 1;
  648.                                        j--;
  649.                                        flag = SAME;
  650.                                }
  651.                                else
  652.                                        flag = SAME;
  653.                                break;
  654.                }
  655.  
  656.  
  657.        /*  End of loop update the positions of the count save lcn and
  658.            next character to look at 
  659.  
  660.            Only do update on non zero counts 
  661.        */
  662.                                              
  663.                if( count != 0 )
  664.                {
  665.                        cntpsn = j;
  666.                        out[++j] = line[k];
  667.                        j++;
  668.                        i = k;
  669.                }
  670.        }
  671.  
  672.        /*  All done now j is the size of the output array, so move it
  673.            back to the orignal array and return the size
  674.        */
  675.  
  676.        size = j - 2;
  677.  
  678.        for( i=0; i<size; i++ )
  679.                line[i] = out[i];
  680.  
  681.        return( size );
  682. }
  683.  
  684. /********************************************************************************
  685. *
  686. *      OUT_BUF(data,size,channel)
  687. *
  688. *      INPUT:  data            - Output data in bytes to be transmitted
  689. *                                as hex followed by a newline
  690. *              size            - # Bytes of data
  691. *                                -1 => Initialize buffer for run flush channel
  692. *
  693. *              channel         - fileid to use for output
  694. *
  695. *      OUTPUT: If size = -1    Reset buffer pointers for output
  696. *                              flush channel data ignored
  697. *
  698. *                      <>-1    Output data to buffer and write each time full
  699. *
  700. *********************************************************************************/
  701.  
  702. out_buf(data,size,channel)
  703. char data[];
  704. int size,channel;
  705. {       
  706.        int i;
  707.        char hexh,hexl,hex_con();
  708.  
  709.        /*  Ok look for the flush command */
  710.  
  711.        if( size == -1 )
  712.        {
  713.                write_buf(hexl,1,channel);
  714.                return;
  715.        }
  716.  
  717.        /* No flush - output the data as hex bytes to the buffer
  718.           if full write
  719.        */
  720.  
  721.        for( i=0; i<size; i++ )
  722.        {       
  723.  
  724.        /*  Convert the data to hex  - two bytes */
  725.  
  726.                hexh = hex_con(data[i],1);
  727.                hexl = hex_con(data[i],0);
  728.  
  729.        /*  Output the bytes to the buffer */
  730.  
  731.                write_buf(hexh,0,channel);
  732.                write_buf(hexl,0,channel);
  733.        }
  734.  
  735.        /*  Put a LF on the end of the line */
  736.        
  737.        write_buf(LF,0,channel);
  738. }
  739.  
  740. /******************************************************************************
  741. *
  742. *      WRITE_BUF(ch,flush,channel)
  743. *      
  744. *      INPUT:  ch              - Character to be written to buffer
  745. *              flush           - 0 Write character to buffer
  746. *                                1  Flush channel and reset
  747. *              channel         - Channel to write to
  748. *
  749. *      OUTPUT: Data written to channel and buffer written if necessary
  750. *
  751. ******************************************************************************/
  752.  
  753. write_buf(ch,flush,channel)
  754. char ch;
  755. int flush,channel;
  756. {
  757.        static int bufpsn = 0;
  758.        static char buffer[BUF_SZ];
  759.  
  760.        /*  Initialize and flush channel, if there is data flush it */
  761.  
  762.        if( flush == 1 )
  763.        {                   
  764.                if( bufpsn != 0 )
  765.                        write(channel,buffer,bufpsn);
  766.  
  767.                fsync(channel);
  768.                bufpsn = 0;
  769.                return;
  770.        }
  771.        else
  772.        {
  773.  
  774.        /*  Write the stuff out to the channel */
  775.  
  776.                buffer[bufpsn++] = ch;
  777.                if( bufpsn == BUF_SZ )
  778.                {
  779.                        write(channel,buffer,BUF_SZ);
  780.                        bufpsn = 0;
  781.                }
  782.        }
  783. }
  784.  
  785. /*******************************************************************************
  786. *
  787. *      HEX_CON(ch,nibble)
  788. *      
  789. *      INPUT:  ch              - Character to convert to hex
  790. *              nibble          - 0 Top nibble
  791. *                                1 Bottom nibble
  792. *
  793. *      OUTPUT: Hex character representation of the nibble
  794. *
  795. ********************************************************************************/
  796.  
  797. char hex_con(ch,nibble)
  798. char ch;
  799. int nibble;
  800. {
  801.        char nib;
  802.  
  803.        /*  Select the nibble from the character */
  804.  
  805.        if( nibble == 1 )
  806.                nib = ( 0xf0 & ch ) >> 4;
  807.        else
  808.                nib = 0x0f & ch;
  809.  
  810.        /*  Convert to hex */
  811.        
  812.        if( nib > 9 )
  813.                nib = nib + 'a' - 10;
  814.        else
  815.                nib = nib + '0';
  816.  
  817.        return( nib );
  818. }
  819.