[net.sources.mac] Scribepic.shar

info-mac@uw-beaver (08/30/85)

From: Richard M. Alderson <INFO-MAC-REQUEST@SUMEX-AIM.arpa>


Here is the source mentioned in the July 14 posting:

: to unbundle, "sh" this file -- DO NOT use csh
:  SHAR archive format.  Archive created Sun Jul 14 01:15:41 MDT 1985
echo x - READ_ME
sed 's/^X//' >READ_ME <<'+FUNKY+STUFF+'
XThese programs are for creating bitmap illustrations into
XPostScript/Scribe documents.  These support MacPaint files and Apollo GMF
Xand BM files.  However, any bitmap format using the MacPaint compression
Xscheme could be adapted without too much trouble.
X
XThe MacPaint version (extract_top.c) should run on any Unix system, the
Xapollo version must be run on an Apollo.
X
XFiles in this directory:
X
X	extract_top.c -	C program to extract Scribe-able PostScript pictures
X			from MacPaint files.
X
X	extract_top.hlp - Documentation for the above.
X	
X	apollo_scribepic.c - Converts apollo GMF or Bitmap files into
X			     Scribe-able pictures.  GMF files are generated
X			     by the DM's "XI" command and the cpscr command.
X
X	gmf_inq.pas - Helper routine for apollo_scribepic.c (Must be
X		      bound to apollo_scribepic.  Use:
X		       pas gmf_inq.pas; cc apollo_scribepic.c
X		       bind gmf_inq.bin apollo_scribepic.bin -b apollo_scribepic
X		      to compile and link it.
X
X	scribepic.ps - PostScript preamble used by both programs.
X
XNOTE:  Before using these, you'll want to edit them to change the
Xconstant POSTDEF to reflect where the scribepic.ps file lives.
X
+FUNKY+STUFF+
ls -l READ_ME
echo x - extract_top.c
sed 's/^X//' >extract_top.c <<'+FUNKY+STUFF+'
X/*
X   Yet another hack with P. Rowley's (U Toronto) macpaint code - this 
X   extracts the top left portion and spits it out in hex, for putting illo's
X   in Scribe files.
X
X   J.W. Peterson
X   Computer Science Department
X   University of Utah.
X*/
X
X#include <stdio.h>
X
X#define and &&
X#define or ||
X
X/*  Flags & defaults for user */
X
X#define FFLAG          'f'	/* -f macpaint_file (input macpaint file) */
X#define COLFLAG        'c'	/* -c col_width (column width to center on) */
X#define HEIGHTFLAG     'h'      /* -h height    (height of Scribe picture) */
X#define SIZEFLAG       's'      /* -s x y   (Size of macpaint picture (in pixels)) */
X#define UPFLAG         'u'	/* -u updist (amount to translate up) */
X#define POSTFLAG       'P'      /* -P postfile (PostScript file to use) */
X
X/* Default values */
X
X/* These determine the size of the picture (values here are for exactly the
X * size of the window MacPaint displays (416 x 240)) */
X
X/* This defines the width of the scanline accepted, IN BYTES (which equals
X * the number of pixels / 8)
X */
X#define LINE_WIDTH  52
X#define DEF_SCANLINES      240 	/* This defines the height (# of scanlines) */
X
X#define OUTDEF         stdout
X#define POSTDEF        "/v/misc/mac/lw/scribe_pics/scribepic.ps"
X
X#define COLUMNDEF      6.5     /*  Assume 6.5" text column */
X#define HEIGHTDEF      2       /*  Assume 2" height */
X#define UPDEF          0       /*  Assume 0" move UP */
X
Xint line_width, scanlines;
X
Xchar in_line[72];
X
XFILE *infil, *fopen();
X
Xmain(argc,argv) 
Xint argc;
Xchar *argv[];
X{
X    int i, j, c;
X    int size_x, size_y;    		/* Size of MacPaint picture grabbed*/
X    float columnwidth, height, up, atof();
X    FILE *fpost;
X    char postfile[255], filename[255];
X
X    infil = stdin;      /* assume stdin */
X    filename[0] = '\0';
X    strcpy(postfile, POSTDEF);
X
X    /* Scribe defaults */
X    height = HEIGHTDEF;
X    columnwidth = COLUMNDEF;
X    up = UPDEF;
X
X    /* Default size clipped from MacPaint page */
X    size_x = LINE_WIDTH * 8;
X    size_y = DEF_SCANLINES;
X
X    /* Command line parsing */
X
X    for (i=1; i<argc; i++)
X    {
X	if (argv[i][0] == '-')
X	{
X	    switch (argv[i][1])
X	    {
X		case FFLAG:    strcpy(filename, argv[i+1]);
X		               break;
X             
X                case POSTFLAG: strcpy(postfile, argv[i+1]);
X                               break;
X
X		case COLFLAG: columnwidth = atof( argv[i+1] );
X		               break;
X
X		case HEIGHTFLAG: height = atof( argv[i+1] );
X		                 break;
X
X		case UPFLAG:   up = atof( argv[i+1] );
X		               break;
X
X		case SIZEFLAG: size_x = atoi( argv[i+1] );
X		               size_y = atoi( argv[i+2] );
X			       break;
X		default:
X                               printf(
X"Usage: extract_top [-f macpaintfile] [-P header.ps] [-c width] [-h height] \n			            [-s x_size y_size] [-u up]\n");
X	    		       exit(1);
X			       break;
X	    }
X	}
X    }
X
X    if ((strlen(filename) > 0) and ((infil = fopen(filename, "r")) == NULL)) {
X        printf("Can't open input file %s\n", filename);
X        exit(1);
X    }
X
X    if ((fpost = fopen(postfile, "r")) == NULL) {
X        printf("Can't open PostScript header file %s\n", postfile);
X        exit(1);
X    }
X
X    /* read and discard 512 byte MacPaint header */
X    for (i=0; i<512; i++)
X	    getc(infil);
X
X    /* Copy the postscript header to stdout */
X    while ((c = getc(fpost)) != EOF)
X        putc(c, stdout);
X
X    line_width = (int) size_x / 8;	/* Convert to number of bytes */
X    scanlines = size_y;
X
X    /* Print a preamble describing size and shape */
X    printf( "1 %d %d %f %f %f\n", line_width, scanlines,
X             columnwidth, height, up );
X
X    /* read and process each of scanlines scan lines (others get tossed) */
X    for (i=0; i < scanlines; i++)	
X    {
X	    do_scan();
X    }
X}
X
Xdo_scan() {
X	int in_pos, count, data_byte, mcount;
X	unsigned int raw_data;
X
X	in_pos = 0;
X	while (in_pos < 72) {
X		count = getc(infil);
X
X 		if (count > 127) count -= 256;
X
X		/* Prevent computed count from exceding line_width */
X		mcount = count;		/* Modified count */
X
X		/* run too long */
X                if ((count >= 0) and ((count + 1 + in_pos) > line_width))
X		    mcount = line_width - 1 - in_pos;
X
X		/* Data string too long */
X		if ((count < 0) and ((-count + 1 + in_pos) > line_width))
X		    mcount = -( line_width - in_pos -1 );
X		    
X		if (in_pos < line_width)
X		    printf ( "%02X", (mcount+256) & 0xFF );
X
X		if (count >= 0) {		/* run of raw bytes */
X			count++;		/* # of bytes to read */
X			while (count--) {
X				raw_data = getc(infil);
X				if (in_pos < line_width)
X				    printf ( "%02X", raw_data );
X				in_pos++;
X			}
X		}
X		else {				/* run of repeated byte */
X			count = -count+1;	/* repetition factor */
X			data_byte = getc(infil);  /* byte to repeat */
X			if (in_pos < line_width)
X			    printf ( "%02X", data_byte );
X
X			while (count--)		/* Kinda dumb... */
X			    in_pos++;
X		}
X	}
X	printf ("\n");
X}
X
+FUNKY+STUFF+
ls -l extract_top.c
echo x - extract_top.hlp
sed 's/^X//' >extract_top.hlp <<'+FUNKY+STUFF+'
XExtract_top is a program for taking a portion of a MacPaint picture and
Xconverting it to a PostScript file that can be used with the @Picture command
Xin Scribe.
X
XThe PostScript output generated by extract_top can be included in a Scribe
Xfile with a Scribe command like the following:
X
X	@figure[
X	@picture(Size=3 inch, ScaleableLaser=[postscript_output.ps])
X	@caption(System Overview)
X	@tag(SysView)
X	]
X
XIn this case, the file "postscript_output.ps" is included into the scribe
Xfile, and Scribe will leave 3 inches of column space for it.  The "Size"
Xspecified in the @Picture command should match the height given to
Xextract_top with the "-h" option.  (Extract_top's default is 2 inches).
X
XTo upload a MacPaint file to the vax, you'll need to run MacTerminal on
Xthe mac, and use "macget -d filename" to upload the file.  (Macget will
Xcreate "filename.data" on the vax).  See the man page for macget(1) for
Xmore information on uploading files.
X
XExtract_top scales the macpaint picture to match the aspect ratio of the
Xarea extracted, and centers it within the Scribe text column (assumed to
Xbe 6.5 inches - i.e, 1" margins).  You can use the -c option to change
Xthe width of the column extract_top centers the picture in.  Normally
Xthe MacPaint image is placed at the bottom of the area Scribe allocates
Xfor it, you can use the -u option to slide it up a specified number of
Xinches.
X
XThe upper left portion of the MacPaint page is extracted by extract_top, the
Xrest of the image is ignored.  You can use the "Show Page" option in
XMacPaint's "Goodies" menu to move your image to the upper left part of the
Xpage.  By default, extract_top selects an area the size of the window
Xdisplayed in MacPaint (416 x 240 pixels).  You can use the -s option to
Xchange this size.  Other useful sizes are 512x480 (a dithered frame buffer
Ximage) and 576x720 (a full MacPaint page).
X
XSummary of extract_top options:
X
X
X    Option	Description				Default
X    ------	-----------				-------
X
X    -f file 	MacPaint file to get picture from	Read from stdin
X    -c XX	Set column width to center on (inches)  6.5 (Scribe's default)
X    -h XX	Height of the resulting macpaint image  2.0 inches
X    -s x y      Size (in pixels) of the area extracted	416 240 (M.P. window)
X    -P postfile PostScript preamble file to use.        ~mac/lw/scribe_pics/scribepic.ps
X    -u XX	Amount to slide MacPaint picture up	0.0 inches.
X
XExamples:
X
XTo extract a MacPaint-window sized image into a PostScript file for 
Xgenerating a 2" tall picture in Scribe:
X
X	extract_top -f kloo_pic.data > kloo_pic.ps
X
XTo extract a full page MacPaint picture into a PostScript file for a 5.5"
Xtall picture in Scribe:
X
X	extract-top -f kloo_page.data -h 5.5 -s 576 720 > kloo_page.ps
+FUNKY+STUFF+
ls -l extract_top.hlp
echo x - apollo_scribepic.c
sed 's/^X//' >apollo_scribepic.c <<'+FUNKY+STUFF+'
X/***********************************************************************
X*                                                                      *
X*     University of Utah - APOLLO Graphics Helper Routine              *
X*                  Copyright 1985 University of Utah                   *
X*                                                                      *
X*                         SCRIBEPIC                                    *
X*                                                                      *
X*      Module: Main module (scribepic.c)                               *
X*                                                                      *
X*   Version    Date    Person          Description                     *
X*----------------------------------------------------------------------*
X*      0.1   2-Jun-85  J. Schimpf      Make a MACPAINT style file      *
X*                                      from a screen                   *
X*      0.2   5-Jun-85  J. Schimpf      Use level 2 I/O for speed       *
X*      0.3   5-Jun-85  J. Schimpf      Added read GMF format stuff     *
X*      0.4  14-Jun-85  J. Schimpf      Don't invert windows only       *
X*                                      screens                         *
X*      0.5  26-Jun-85  J. Schimpf      Added margin,height & POSTSCRIPT*
X*                                      info so SCRIBE picture file     *
X*                                      can be built                    *
X*                                                                      *
X*   Description of code:                                               *
X*      Copy Apollo Window or Screen to a file suitable for use in a    *
X*      SCRIBE @picture command.  (See Below)                           *
X*      File produced is a POSTSCRIPT program with the run length       *
X*      encoded version of the bit map following it                     *
X*                                                                      *
X*      SCRIBE Picture Command is of the form:                          *
X*                                                                      *
X*              @picture(size=2inch, ScalableLaser=[mypic.ps])          *
X*                                                                      *
X*      And the command used to make the mypic.ps file (assuming you    *
X*      have a window or screen bit map in the file screen) is          *
X*                                                                      *
X*              scribepic -f screen -h 2 -m 6 -o mypic.ps               *
X*                                                                      *
X*              This sets the height at 2 inches, the distance between  *
X*              margins as 6 inches and the output file as mypic.ps     *
X*              the other values are defaulted (see below)              *
X*                                                                      *
X*      SYNTAX: scribepic -f (filename) [-i] [-b]                       *
X*                                    [-o <output file>]                *
X*                                    [-m <page margin (in)>]           *
X*                                    [-h <Picture height(in)>]         *
X*                                    [-P <POSTSCRIPT CODE FILE>]       *
X*                                    [-u <Translate picture UP (in)>]  *
X*                                                                      *
X*      Parameter       Use                     Default                 *
X*----------------------------------------------------------------------*
X*              ****** FILE CONTROL *****                               *
X*                                                                      *
X*      -f <filename>   Input Screen file       NONE - ERROR if missing *
X*      -b              Input is APOLLO BM file GMF file assumed        *
X*                                              (All STD screens &      *
X*                                               Apollo windows are GMF)*
X*      -i              Invert Input file       NOT Inverted            *
X*      -o <filename>   Output Picture file     STDOUT                  *
X*                                                                      *
X*              ***** SCRIBE FORMAT CONTROL *****                       *
X*                                                                      *
X*      -m <Margin>     Page margin  (inches)   6 inches                *
X*      -h <Height>     Picture heigh (inches)  2 inches                *
X*      -u <Move up>    Move picture up page    0 inches                *
X*                                                                      *
X*              ***** POSTSCRIPT CONTROL ****                           *
X*                                                                      *
X*      -P <CODE FILE>  Postscript code         ~/bin/scribepic.ps      *
X*                                                                      *
X*----------------------------------------------------------------------*
X*                                                                      *
X*      Output File is of the form:                                     *
X*      <POSTSCRIPT CODE>                                               *
X*      <Invert> <X size> <Y size> <Margin> <Height> <Move UP>          *
X*      <Run length encoded bitmap (see cmprs_line)                     *
X*                                                                      *
X*   Procedures:                                                        *
X*                                                                      *
X*   Written+   Name                    Description                     *
X*----------------------------------------------------------------------*
X*      y       main()                  Bring in bit map to memory bm   *
X*      y       get_bitmap()            Read bitmap file                *
X*      y       get_line()              Get one scan line               *
X*      y       cmprs_line()            Compress 1 scan line            *
X*      y       out_buf()               Output one scan line as hex     *
X*      y       write_buf()             Output one character to output  *
X*      y       hex_con()               Convert nibble to ASCII hex     *
X*                                                                      *
X*      EXTERNAL                                                        *
X*              gmf_inq()               Get info on GMF file            *
X*                                                                      *
X*      + (N - no; Y - yes (y - untested); P - partially written)       *
X*                                                                      *
X***********************************************************************/
X                             
X/*  Include files ***********/
X
X#include <stdio.h>
X#include "/sys/ins/base.ins.c"
X#include "/sys/ins/gpr.ins.c"
X#include "/sys/ins/gmf.ins.c"
X
X/*  Global Constants *******/
X                         
X#define GPR_MODE       gpr_$borrow     /*  Display MODE */
X#define TRUE           1
X#define FALSE          0
X
X#define SCREEN_X       1024            /* DN 300 Screen constants */
X#define SCREEN_Y       800
X#define SCREEN_WD      64
X
X#define MAX_SCAN_LINE  256
X#define BUF_SZ         50000
X
X#define LF             0x0a
X
X#define SAME           1
X#define NOTSAME        0             
X
X/*  Flags & defaults for user */
X
X#define INVFLAG        'i'
X#define FFLAG          'f'
X#define BITFLAG        'b'
X#define OUTFLAG        'o'
X#define MARGFLAG       'm'
X#define HEIGHTFLAG     'h'
X#define UPFLAG         'u'
X#define POSTFLAG       'P'
X
X#define OUTDEF         stdout
X#define POSTDEF        "//a/utah/printers/scribe/scribepic.ps"
X
X#define MARGINDEF      6       /*  Assume 6" margins */
X#define HEIGHTDEF      2       /*  Assume 2" height */
X#define UPDEF          0       /*  Assume 0" move UP */
X
X/*  Globals used by all routines */
X
X       int     line_sz;        /* # Bytes/scan line */
X       int     separation;     /* Bytes between scan lines */
X       int     x_size,y_size;  /* Raster size       */
X       char    *bitp;          /* Pointer to bitmap */
X       
Xmain(argc,argv)
Xint argc;
Xchar *argv[];
X{
X
X       name_$pname_t   filename;
X       gpr_$bitmap_desc_t     bitmap,get_bitmap(),get_gmf();
X       status_$t       status;
X       int psn = 0;
X       int outnum;
X       int             n,i,j,size;
X       int             invert,bitfile;
X       unsigned char   scanline[MAX_SCAN_LINE];
X       float height,margin,up,atof();
X       FILE *fopen(),*fout,*fpost;
X       char postfile[30],outfile[30];
X           
X       /*  Scan command line for input file & other stuff, set other stuff
X           for defaults
X       */                                             
X      
X       /*  Set default file control stuff */
X       
X       invert  = TRUE;
X       bitfile = FALSE;
X       filename[0] = '\0';
X
X       fout = OUTDEF;
X       strcpy(postfile,POSTDEF);
X
X       /*  Set default SCRIBE stuff */
X
X       height = HEIGHTDEF;
X       margin = MARGINDEF;
X       up = UPDEF;
X                  
X       /*  Now scan command line and set all the stuff */
X      
X       for( i=1; i<argc; i++ )
X       {
X               if( argv[i][0] == '-' )
X               {
X                       switch( argv[i][1] ) {
X                       
X                       case INVFLAG:   invert = FALSE;
X                                       break;
X
X                       case FFLAG:     strcpy(filename,argv[i+1]);
X                                       break;
X
X                       case BITFLAG:   bitfile = TRUE;
X                                       break;
X
X                       case OUTFLAG:   strcpy(outfile,argv[i+1]);
X                                       break;
X
X                       case POSTFLAG:  strcpy(postfile,argv[i+1]);
X                                       break;
X
X                       case MARGFLAG:  margin = atof( argv[i+1] );
X                                       break;
X
X                       case HEIGHTFLAG: height = atof( argv[i+1] );
X                                       break;
X
X                       case UPFLAG:    up = atof( argv[i+1] );
X                                       break;
X
X                       }
X               }
X       }
X
X       if( strlen(filename) == 0 )
X       {
X               fprintf(stderr,"*** scribepic: Syntax No filename input\n");
X               exit(-1);
X       }
X
X       /*  Open Output & postscript files - use defaults if failure */
X
X       if( (fout = fopen(outfile,"w")) == NULL )
X       {
X               printf("*** scribepic: Bad output file %s\n",outfile);
X               printf("**** Stdout used\n");
X               fout = OUTDEF;
X       }
X
X       if( (fpost = fopen(postfile,"r")) == NULL )
X       {
X               printf("*** scribepic:Cannot find POSTSCRIPT file %s\n",postfile);
X               printf("**** %s used\n",POSTDEF);
X               strcpy(postfile,POSTDEF);
X               if( ( fpost = fopen(postfile,"r")) == NULL )
X               {
X                       fprintf(stderr,"scribepic:Cannot find DEFAULT POSTSCRIPT file %s\n",postfile);
X                       exit(-1);
X               }
X       }
X
X       /*  Get fileid associated with output */
X
X       outnum = fileno( fout );
X
X       /*  Get the bit map on the screen where we can fiddle with it */
X
X       if( bitfile )
X               bitmap = get_bitmap(filename);
X       else
X               bitmap = get_gmf(filename);
X
X       if( bitmap == NULL )
X       {
X               fprintf(stderr,"makemap: Bad bit map file - %s\n",filename);
X               exit(-1);
X       }
X
X       /*  Initialize the buffer */
X
X       out_buf(scanline,-1,outnum);
X
X       /*  Put out the POSTSCRIPT file first to output */
X
X       while( 1 )
X       {
X               fgets(scanline,MAX_SCAN_LINE,fpost);
X               if( feof( fpost ) )
X                       break;
X               fputs(scanline,fout);
X       }
X       fflush(fout);
X
X       /*  Put out the x & y size of the file first in the file
X           NOTE: X size is # bytes/line
X       */
X
X       sprintf(scanline,"%d %d %d %f %f %f\n",
X               invert,line_sz,y_size,margin,height,up);
X       for( i=0; i< strlen(scanline); i++ )
X               write_buf(scanline[i],0,outnum);
X
X       /*  Loop through scan lines reading data and compressing it for output */
X
X       for( i=0; i<y_size; i++ )
X       {
X               size = get_line(bitp,i,line_sz,separation,scanline);
X               size = comprs_line(scanline,size);
X               out_buf(scanline,size,outnum);
X       }
X
X       /*  Flush the buffer */
X
X       out_buf(scanline,-1,outnum);
X
X       gpr_$terminate(0,status); 
X}
X
X/***************************************************************************
X*
X*      GET_BITMAP(filename)
X*
X*      INPUT: filename         - Bitmap file name
X*
X*      OUTPUT: Bitmap discriptor NULL if not found
X*              line_sz         - # Bytes/scan line set
X*              separation      - Bytes between scan lines
X*              x_size,y_size   - Size of map in raster units
X*
X*      SIDE EFFECTS:   Bit map moved into virtual memory
X*                      Graphics inited for BORROW mode
X*
X****************************************************************************/
X
Xgpr_$bitmap_desc_t get_bitmap(filename)
Xchar filename[];
X{
X       gpr_$window_t                       window;
X       gpr_$bmf_group_header_array_t       header;
X       short                               length,sep;
X       gpr_$plane_t                        hi_plane = 7;
X       short                               groups;
X       gpr_$bitmap_desc_t                  bitmap,filebm;
X       status_$t                           status;
X       gpr_$version_t                      version;
X       gpr_$attribute_desc_t               attribs;
X       boolean                             created;
X
X       length = strlen(filename);
X
X       /*  Init the bit map dimensions  */
X
X       window.window_base.x_coord = (short) 0;
X       window.window_base.y_coord = (short) 0;
X       window.window_size.x_size  = (short) SCREEN_X;
X       window.window_size.y_size  = (short) SCREEN_Y;
X
X       /*  Initialize by borrowing the display  */
X
X       gpr_$init(GPR_MODE,1,window.window_size,hi_plane,bitmap,status);
X                                                                    
X       /*  Set up an attribute block for the Xfer */
X
X       gpr_$allocate_attribute_block(attribs,status);
X
X       /*  Open the bit map file */
X                                                     
X       gpr_$open_bitmap_file(gpr_$readonly,filename,length,
X            version,window.window_size,groups,header,
X            attribs,filebm,created,status);
X        
X       /*  If it didn't open tell user and quit */
X
X       if( status.fail )
X       {
X               bitmap = NULL;
X               gpr_$terminate(0,status); 
X               return( bitmap );
X       }
X         
X       /*  Move Bit map to internal bit map */
X
X       gpr_$pixel_blt(filebm,window,window.window_base,status);
X
X       /*  Get the information on this bitmap
X           Scan line separation
X           X_size in bytes
X           Y_size in scan lines
X           Scan line separation
X       */
X
X       gpr_$inq_bitmap_pointer(bitmap,bitp,sep,status);          
X       line_sz = header[0].bytes_per_line;
X       separation = 2*sep;
X       x_size = window.window_size.x_size;
X       y_size = window.window_size.y_size;
X
X       return( bitmap );
X}
X
X/***************************************************************************
X*
X*      GET_GMF(filename)
X*
X*      INPUT: filename         - GMF file name
X*
X*      OUTPUT: Bitmap discriptor NULL if not found
X*              line_sz         - # Bytes/scan line set
X*              separation      - Bytes between scan lines
X*              x_size,y_size   - Size of map in raster units
X*
X*      SIDE EFFECTS:   Bit map moved into virtual memory
X*                      Graphics inited for BORROW mode
X*                      If this is a full window then DON'T invert it before
X*                      use
X*
X****************************************************************************/
X
Xgpr_$bitmap_desc_t get_gmf(filename)
Xchar filename[];
X{
X       gpr_$window_t                       window;
X       gpr_$bmf_group_header_array_t       header;
X       short                               length,sep;
X       gpr_$plane_t                        hi_plane = 7;
X       short                               groups,words,bpi,x_dim,y_dim;
X       gpr_$bitmap_desc_t                  bitmap,filebm;
X       status_$t                           status;
X       gpr_$version_t                      version;
X       gpr_$attribute_desc_t               attribs;
X       stream_$id_t                        stream;
X       length = strlen(filename);
X
X       /*  Init the bit map dimensions  */
X
X       window.window_base.x_coord = (short) 0;
X       window.window_base.y_coord = (short) 0;
X       window.window_size.x_size  = (short) SCREEN_X;
X       window.window_size.y_size  = (short) SCREEN_Y;
X
X       /*  Initialize by borrowing the display  */
X
X       gpr_$init(GPR_MODE,1,window.window_size,hi_plane,bitmap,status);
X                                                                    
X       /*  Set up an attribute block for the Xfer */
X
X       gpr_$allocate_attribute_block(attribs,status);
X
X       /*  Open the GMF file and read it in */
X
X       gmf_$open(filename,length,gmf_$read,stream,status);
X
X       /*  If it didn't open tell user and quit */
X
X       if( status.fail )
X       {
X               bitmap = NULL;
X               gpr_$terminate(0,status); 
X               return( bitmap );
X       }
X                                         
X       /*  Get access and display information, bitmap & GMF stuff */
X
X       gpr_$enable_direct_access(status);    
X
X       gpr_$inq_bitmap_pointer(bitmap,bitp,sep,status);
X       separation = 2*sep;
X                     
X       /*  Get information on GMF file, use JW's function */
X
X       gmf_$inquire(&stream,&x_dim,&y_dim,&words,&status);
X
X       /*  ***** words is really # 16 bits words/line - just divide
X           x_dim by 16 to get what we want  We used it to hold bits/inch
X           which we will throw away
X        */
X
X       words = x_dim/(short)16;
X       line_sz = 2 * (int) words;
X       x_size  = (int) x_dim;
X       y_size  = (int) y_dim;
X
X       /*  Set window for blt */
X
X       window.window_size.x_size  = x_dim;
X       window.window_size.y_size  = y_dim;
X       
X       /*  Move the plane onto the bit map */
X
X       gmf_$restore_plane(stream,(short)SCREEN_X,(short)SCREEN_Y,
X                          (short)SCREEN_WD,bitp,bpi,status);
X
X       /*  Since this is a GMF we have to invert it (GMF stuff comes out
X           inverted) but only if it is a WINDOW if screen leave it alone
X       */
X                                                                        
X       if( x_size == SCREEN_X && y_size == SCREEN_Y )
X       {
X               gpr_$set_raster_op((short)0,(short)10,status);   /*  Compliment */
X               gpr_$pixel_blt(bitmap,window,window.window_base,status);
X       }
X
X       /*  Close GMF & return bit map to user */
X
X       gmf_$close(stream,status);
X       return( bitmap );
X}
X
X/****************************************************************************
X*
X*      GET_LINE(ptr,line,size,sep,out)
X*
X*      INPUT:  ptr             - Pointer to UL corner of BM
X*              line            - Scan line # to read out
X*              size            - # bytes/scan line
X*              sep             - Gaps between scan lines
X*              
X*      OUTPUT: scanline        - Scan line data 
X*              # Bytes in scan line
X*
X*****************************************************************************/
X
Xget_line(ptr,line,size,sep,out)
Xunsigned char *ptr,out[];
Xint line,size,sep;
X{
X       int i,j;
X       unsigned char *locptr;
X
X/*---------------------------------------------------------------------------
X
X       OPERATION:
X
X       1) Set bit pointer to point to this scan line
X       2) Move scan line data to scanline
X       3) Return count
X
X----------------------------------------------------------------------------*/
X
X       locptr = ptr + sep*line;
X
X       for( i=0; i<size; i++ )
X       {
X               out[i] = *(locptr);
X               *(locptr++) = ~out[i];
X       }
X
X       return( size );
X}
X
X/*****************************************************************************
X*
X*      COMPRS_LINE(line,size)
X*
X*      INPUT:  line            - Scan line to be compressed
X*              size            - # bytes in scan line
X*
X*      OUTPUT: size of new scan line
X*              line compressed as shown below
X*
X*      Compression is as follows:
X*
X*      <CNT><Byte><Byte>...    If <CNT>  < 0x80  i.e. <CNT> different bytes
X*      <CNT><Byte>             If <CNT>  > 0x80  i.e. <CNT> repeated bytes
X*
X*****************************************************************************/
X
Xcomprs_line(line,size)
Xunsigned char line[];
Xint size;
X{
X       int i,j,k,cntpsn,count;
X       int flag;
X       unsigned char pixel;
X       unsigned char out[MAX_SCAN_LINE];
X
X/*-----------------------------------------------------------------------------
X       
X       OPERATION:
X
X       1) Init counters, Check line - if first two byte == set flag
X          flag for same else, set for NOTSAME
X       2) Reserve a slot in the output list for the count
X       3) 
X
X------------------------------------------------------------------------------*/
X
X
X                      
X       i = 0;
X       j = 2;
X       if( line[0] == line[1] )
X       {
X               flag = SAME;
X               cntpsn = 0;
X               out[1] = line[0];
X       }
X       else
X       {
X               flag = NOTSAME;
X               cntpsn = 0;
X               out[1] = line[0];
X       }
X
X       while( i < size )
X       {
X               switch( flag ) {
X                                
X       /*  Same case see how far the run goes then update stuff */
X
X               case SAME:      count = 0;
X                               for( k=i; k<size; k++ )
X                               {
X                                       if( out[j-1] != line[k] )
X                                               break;
X                                       else
X                                               count++;
X                               }
X
X       /* If count is zero then just skip all this stuff and try again
X           with the flag the other way
X       */
X                               if( count != 0 )
X                               {
X
X       /*  Ok update the count and save the byte in the output line
X           NOTE: Count is just 2's compliment of the value
X       */
X                                       pixel = -1 * (count-1);
X                                       out[cntpsn] = 0xff & pixel;
X
X       /*  Set the flag for the other & go to advance j to next frame */
X                       
X                                       flag = NOTSAME;
X                               }
X                               else
X                                       flag = NOTSAME;
X                               break;
X                                
X       /*  Not the same, look for a run of something if found quit */
X
X               case NOTSAME:   count = 0;
X                               for( k=i+1; k<size; k++ )
X                               {
X                                       if( out[j-1] == line[k] )
X                                               break;
X                                       else
X                                       {
X                                               count++;
X                                               out[j++] = line[k];
X                                       }
X                               }
X       /*  If count is zero then skip all the updating stuff and just try the
X           other method
X       */
X                               if( count != 0 )
X                               {
X
X                                       out[cntpsn] = count - 1;
X
X       /*  Set the flag for the other and back up the psn to get the
X           start of the run
X       */
X                                           
X                                       k = k - 1;
X                                       j--;
X                                       flag = SAME;
X                               }
X                               else
X                                       flag = SAME;
X                               break;
X               }
X
X
X       /*  End of loop update the positions of the count save lcn and
X           next character to look at 
X
X           Only do update on non zero counts 
X       */
X                                             
X               if( count != 0 )
X               {
X                       cntpsn = j;
X                       out[++j] = line[k];
X                       j++;
X                       i = k;
X               }
X       }
X
X       /*  All done now j is the size of the output array, so move it
X           back to the orignal array and return the size
X       */
X
X       size = j - 2;
X
X       for( i=0; i<size; i++ )
X               line[i] = out[i];
X
X       return( size );
X}
X
X/********************************************************************************
X*
X*      OUT_BUF(data,size,channel)
X*
X*      INPUT:  data            - Output data in bytes to be transmitted
X*                                as hex followed by a newline
X*              size            - # Bytes of data
X*                                -1 => Initialize buffer for run flush channel
X*
X*              channel         - fileid to use for output
X*
X*      OUTPUT: If size = -1    Reset buffer pointers for output
X*                              flush channel data ignored
X*
X*                      <>-1    Output data to buffer and write each time full
X*
X*********************************************************************************/
X
Xout_buf(data,size,channel)
Xchar data[];
Xint size,channel;
X{       
X       int i;
X       char hexh,hexl,hex_con();
X
X       /*  Ok look for the flush command */
X
X       if( size == -1 )
X       {
X               write_buf(hexl,1,channel);
X               return;
X       }
X
X       /* No flush - output the data as hex bytes to the buffer
X          if full write
X       */
X
X       for( i=0; i<size; i++ )
X       {       
X
X       /*  Convert the data to hex  - two bytes */
X
X               hexh = hex_con(data[i],1);
X               hexl = hex_con(data[i],0);
X
X       /*  Output the bytes to the buffer */
X
X               write_buf(hexh,0,channel);
X               write_buf(hexl,0,channel);
X       }
X
X       /*  Put a LF on the end of the line */
X       
X       write_buf(LF,0,channel);
X}
X
X/******************************************************************************
X*
X*      WRITE_BUF(ch,flush,channel)
X*      
X*      INPUT:  ch              - Character to be written to buffer
X*              flush           - 0 Write character to buffer
X*                                1  Flush channel and reset
X*              channel         - Channel to write to
X*
X*      OUTPUT: Data written to channel and buffer written if necessary
X*
X******************************************************************************/
X
Xwrite_buf(ch,flush,channel)
Xchar ch;
Xint flush,channel;
X{
X       static int bufpsn = 0;
X       static char buffer[BUF_SZ];
X
X       /*  Initialize and flush channel, if there is data flush it */
X
X       if( flush == 1 )
X       {                   
X               if( bufpsn != 0 )
X                       write(channel,buffer,bufpsn);
X
X               fsync(channel);
X               bufpsn = 0;
X               return;
X       }
X       else
X       {
X
X       /*  Write the stuff out to the channel */
X
X               buffer[bufpsn++] = ch;
X               if( bufpsn == BUF_SZ )
X               {
X                       write(channel,buffer,BUF_SZ);
X                       bufpsn = 0;
X               }
X       }
X}
X
X/*******************************************************************************
X*
X*      HEX_CON(ch,nibble)
X*      
X*      INPUT:  ch              - Character to convert to hex
X*              nibble          - 0 Top nibble
X*                                1 Bottom nibble
X*
X*      OUTPUT: Hex character representation of the nibble
X*
X********************************************************************************/
X
Xchar hex_con(ch,nibble)
Xchar ch;
Xint nibble;
X{
X       char nib;
X
X       /*  Select the nibble from the character */
X
X       if( nibble == 1 )
X               nib = ( 0xf0 & ch ) >> 4;
X       else
X               nib = 0x0f & ch;
X
X       /*  Convert to hex */
X       
X       if( nib > 9 )
X               nib = nib + 'a' - 10;
X       else
X               nib = nib + '0';
X
X       return( nib );
X}
+FUNKY+STUFF+
ls -l apollo_scribepic.c
echo x - gmf_inq.pas
sed 's/^X//' >gmf_inq.pas <<'+FUNKY+STUFF+'
X
Xmodule gmf_$extend;
X
XDEFINE gmf_$inquire;
X
X%include '/sys/ins/base.ins.pas';
X%include '/sys/ins/streams.ins.pas';
X
Xprocedure gmf_$inquire(
X        in id: stream_$id_t;
X        out x_dim,y_dim, bpi: integer; out status: status_$t );  EXTERN;
X
Xprocedure gmf_$inquire;
X
Xconst
X         gmf_$not_gmf =      16#06040006;
X
XTYPE  header_t = PACKED RECORD
X        kind : INTEGER;    { type of header }
X     version : INTEGER;    {                }
X           x : INTEGER;    { x dimension of bitmap in bits }
X           y : INTEGER;    { y dimension of bitmap in bits }
X     gmf_bpi : INTEGER;    { resolution of data in bits per inch, to whatever degree of }
X                           {  accuracy is feasible (0 means each bit is one dot         }
X                           {  regardless of the dot size of the output device)          }
X      END;
X
X  wordsin_t = array [0..1023] of pinteger;     { scanline-size array of read words from streams file }
X  wordsin_ptr_t = ^wordsin_t;
X
Xvar
X  t,lines       :integer;                    { counters }
X  header        :header_t;                   { header identifier }
X  wordsin       :wordsin_t;                  { input buffer from map file }
X  bufptr,retptr :wordsin_ptr_t;
X  retlen        :integer32;
X  seek_key      :stream_$sk_t;
X
Xbegin
X  stream_$seek( id, stream_$rec, stream_$absolute, 1, status );
X  if status.all <> status_$ok then begin
X    status.fail := true;
X    return;
X  end;
X
X  bufptr := addr(wordsin);
X
X  { setup header information from map file }
X  stream_$get_rec (id,bufptr,SIZEOF(header_t),retptr,retlen,seek_key,status);
X
X  if status.all <> status_$ok then begin
X    status.fail := true;
X    return;
X  end;
X  for t := 0 to 10 do wordsin[t] := retptr^[t];
X
X  with header do begin
X    kind := wordsin[0];
X    version := wordsin[1];
X    x := wordsin[2];
X    x_dim := wordsin[2];
X    y := wordsin[3];
X    y_dim := wordsin[3];
X    gmf_bpi := wordsin[4];
X    bpi := wordsin[4];
X  end;
X
X  { re-wind the input for future use... }
X  stream_$seek( id, stream_$rec, stream_$absolute, 1, status );
X  if status.all <> status_$ok then begin
X    status.fail := true;
X    return;
X  end;
X                     
X  { is opened file really a gmf map file? }
X  if header.kind <> 1 then 
X    begin
X      status.all :=  gmf_$not_gmf;
X      return;
X    end;
X
Xend;
+FUNKY+STUFF+
ls -l gmf_inq.pas
echo x - scribepic.ps
sed 's/^X//' >scribepic.ps <<'+FUNKY+STUFF+'
X%!
X% Postscript pre-amble to parse scribepic output.  This is a fairly
X% straightforward translation of Peter Rowley's (U Toronto) C code to
X% do the same thing. 
X%
X%   Originally converted to PostScript by J.W. Peterson
X%   Arbitrary bitmap sizing added by J. Schimpf
X%   Margin & format control added by J. Schimpf
X%
X%   SEE SCRIBEPIC info sheet for the use of this file
X%   YOU SHOULDN'T TRY TO EDIT THIS FILE - IT IS COPIED
X%   FOR YOU.
X%
X%---------------------------------------------------------------------
X%
X%      HEX FILE FORMAT
X%
X%      <Invert> <XBYTES> <YSIZE> <Margin> <Height> <Move UP>
X%      <Hex Data.......>
X%             
X%      Where Invert -> 1 For straight through data
X%                      0 To invert data
X%      Where YSIZE  ->  # Of Scan lines
X%            XBYTES  -> # Bytes/scan line
X%            Margin  -> Width of the scribe column (in inches)
X%            Height  -> Height of picture (in inches)
X%            Move UP -> Distance picture is moved up (in inches)
X%
X%      Hex data is of the form:
X%
X%      <Count><Data>   -> If <Count> < 0x80 then this is count
X%                         of # bytes to read here
X%                      -> If <Count> >= 0x80 This is count of # times
X%                         next byte is to be repeated
X%
X%--------------------------------------------------------------------------
X%  Open file routine
X/infile (%stdin) (r) file def		% This gets around broke "currentfile"?
X
X%--------------------------------------------------------------------------
X%  Get a byte from file routine
X/getbyte 
X  { infile (x) readhexstring 
X    pop 0 get } def  			% Reads 1 byte of data
X
X%-------------------------------------------------------------------------
X%  Useful routines & definitions
X/inch { 72 mul } def			% Conversion inches => points
X/inc { 1 add } def			% increment TOS
X                                       
X%--------------------------------------------------------------------------
X%  Read file and form 1 scan line
X/parseline
X{
X  /in_pos 0 def				% output array pos
X  {
X     in_pos xbytes lt			% while in_pos < xbytes DO...
X     {
X     	/cnt getbyte def		% get run length
X  
X	cnt 127 gt
X	  { /cnt cnt 256 sub def } 	% if cnt > 128, cnt -= 256;
X	if
X
X	cnt 0 ge			% if cnt >= 0...
X	{  
X     	  cnt inc 			% for count+1 times...
X	  { scanline in_pos getbyte put % scanline[in_pos] = getbyte...
X	    /in_pos in_pos inc def	% in_pos++
X	  } repeat			
X	}
X	 				% ELSE
X	{
X	  /data_byte getbyte def	% fetch the run data
X	  cnt neg 1 add			% -cnt + 1
X	  { scanline in_pos data_byte put   % scanline[in_pos] = getbyte...
X	    /in_pos in_pos inc def	% in_pos++
X	  } repeat
X	}
X	ifelse
X     }
X     { exit }				% Exit loop if !(in_pos < xbytes)
X     ifelse
X
X  }
X  loop
X  scanline				% leave the data on the stack
X} def
X
X 
X%----------------------------------------------------------------------
X%  MAIN ROUTINE
X%
X% Group all the operations to draw the picture into one procedure, to
X% minimize confusion between PostScript commands and hex data...
X%
X/drawpaint 
X{
X  gsave                        % Push graphics enviroment
X   
X%  Read if this is to be inverted or not put onto the stack, then decide
X%  If we should invert the data
X
X    infile token pop
X    1 eq
X    {
X       /invstat true def               % Don't Invert the data
X    }
X    {
X       /invstat false def              % Invert the data
X    }
X   ifelse
X
X%  Get the X & Y size from the file
X
X    /xbytes infile token pop def     % Bytes/scanline
X    /ysize infile token pop def      % # Scan lines
X
X%  Get the margin, height & upward movement
X
X    /margin infile token pop def     % Default usually 6.5 in
X    /height infile token pop def     % Default usually 2   in
X    /up     infile token pop def     % Default usually 0
X
X%  Generate some constants we will need
X
X    /scanline xbytes string def      % Create output scan buffer
X    /nysize ysize neg def            %  Used in matrix to define size
X    /xbits xbytes 8 mul def          % Calculate # pixels/scanline
X    /width height xbits ysize div mul def  % Width = height * (x / y)
X
X% Generate the transformation to place the "unit square" imagemask uses.
X
X  margin width sub 2 div inch	% center on page (with scribe margins)
X  				% with x xlate = (margin - width) / 2
X  up inch			% Y translate by UP translate
X  translate 			% Center image on the page.
X
X  width inch			% Adjust X size to keep aspect ratio right
X  height inch 			% convert Y height to inches
X  scale 
X
X%------------------------------------------------------------------
X% 
X%  Generate image in unit box
X
X       %  The next 5 things are placed on the stack for
X       %  the imagemask function
X
X       xbits                   % # Pixels/Scanline
X       ysize                   % # Scan lines
X
X       invstat		  	 % Use invstat to choose pixel black/white
X    [ xbits 0 0 nysize 0 ysize ] % Bit map description matrix
X    { parseline }                % Routine to read scan lines
X  imagemask			 % Move bitmap to page
X  grestore                       % Restore graphics enviroment
X} def
X
X% Put the hex data directly after the "drawpaint" command...
Xdrawpaint
+FUNKY+STUFF+
ls -l scribepic.ps
exit 0
-------