aboutsummaryrefslogtreecommitdiff
path: root/unix/gdev/sgidev
diff options
context:
space:
mode:
Diffstat (limited to 'unix/gdev/sgidev')
-rw-r--r--unix/gdev/sgidev/README24
-rw-r--r--unix/gdev/sgidev/README.gif438
-rw-r--r--unix/gdev/sgidev/mkpkg9
-rw-r--r--unix/gdev/sgidev/mkpkg.sh60
-rw-r--r--unix/gdev/sgidev/sgi2gif.c731
-rw-r--r--unix/gdev/sgidev/sgi2svg.c245
-rw-r--r--unix/gdev/sgidev/sgi2uapl.c545
-rw-r--r--unix/gdev/sgidev/sgi2ueps.c530
-rw-r--r--unix/gdev/sgidev/sgi2uhpgl.c160
-rw-r--r--unix/gdev/sgidev/sgi2uhplj.c223
-rw-r--r--unix/gdev/sgidev/sgi2uimp.c341
-rw-r--r--unix/gdev/sgidev/sgi2uptx.c61
-rw-r--r--unix/gdev/sgidev/sgi2uqms.c296
-rw-r--r--unix/gdev/sgidev/sgi2xbm.c135
-rw-r--r--unix/gdev/sgidev/sgiUtil.c132
-rw-r--r--unix/gdev/sgidev/sgiUtil.h10
-rw-r--r--unix/gdev/sgidev/sgidispatch.c70
17 files changed, 4010 insertions, 0 deletions
diff --git a/unix/gdev/sgidev/README b/unix/gdev/sgidev/README
new file mode 100644
index 00000000..363b490f
--- /dev/null
+++ b/unix/gdev/sgidev/README
@@ -0,0 +1,24 @@
+SGIDEV -- This directory contains the UNIX dependent sources for the metacode
+or bitmap translation programs for all devices supported by the SGI graphics
+kernel. See gio$sgikern or `help sgikern' for further information on SGI.
+
+To add a new SGI device:
+
+ [1] Add source file for translator to this directory.
+ [2] Add references to mkpkg.csh and mkpkg.
+ [3] Run `mkpkg update' in this directory to install new translator.
+
+ [4] Add entry to graphcap file, including DD command string
+ containing host command to dispose of the output.
+
+ [5] Test new device interface.
+
+Alternatively, you might wish to install the source for the translator in
+local somewhere, to avoid a merge operation when a new version of the VMS
+host system interface is installed.
+
+Note that some example graphcap entries for SGI devices might require non-
+standard tasks residing outside of IRAF, for example the `impress300'
+command to ship Impress output from a UNIX node to a VMS node running
+Eunice in order to execute the VMS IMPRINT command. These are considered
+so unusual that support is not included in the standard system.
diff --git a/unix/gdev/sgidev/README.gif b/unix/gdev/sgidev/README.gif
new file mode 100644
index 00000000..85833d3f
--- /dev/null
+++ b/unix/gdev/sgidev/README.gif
@@ -0,0 +1,438 @@
+
+Announcement for adass.iraf.system:
+
+ An SGI translator which converts IRAF graphics directly to GIF
+images is now available from our anonymous ftp archive as
+
+ ftp://iraf.noao.edu/pub/sgi2gif.c
+ ftp://iraf.noao.edu/pub/sgi2gif.readme
+
+The associated readme file describes how to install the translator and
+configure a variety of graphcap entries for it.
+ SGI translators are used to convert IRAF graphics to some other
+format, usually Postscript, for disposal to a printer or some other
+hardcopy device. The SGI2GIF translator now allows users to generate
+GIF images (suitable for web page presentation) directly from IRAF using
+the familiar ":.snap" command or non-interactively. See the readme file
+for a full discussion of the capabilities and configuration options, or
+contact site support (iraf@noao.edu) with questions or problems.
+
+--------------------------------------------------------------------------------
+
+README:
+
+1. Introduction
+---------------
+
+ IRAF hardcopy graphics are generated by converting the graphics
+metacode through the SGI (Simple Graphics Interface) kernel which
+translates the numerous graphics commands to a minimal set of move/draw
+instructions or a bitmap raster of the plot. In the case of
+hardcopy/output graphics (i.e. the SGI kernel), the dev$graphcap file
+defines parameters for this conversion which include the plot size, SGI
+kernel options, and most especially a "device dispose" (DD) string which
+specifies the SGI translator to be used and what to do with the resulting
+translator output. The SGI kernel is not a full graphics kernel so
+information such as line color and fill areas are lost, below we will
+discuss how to retain this when producing a GIF images using other
+translators and graphcap file trickery.
+
+ For most printer devices the "sgi2uapl" Postscript translator is
+used to convert the SGI kernel metacode from a series of move/draw
+instructions to equivalent postscript commands, other translators are
+available to convert to other printer languages. The SGI kernel can also
+be used, with the proper graphcap entries, to generate a bitmap raster of
+the plot which can be easily converted to various image formats. The SGI2GIF
+translator takes advantage of this latter feature to produce GIF images
+directly from the IRAF graphics metacode.
+
+ The translator has options for specifying the image size,
+foreground and background colors, GIF transparency, and can be used to
+convert multiple input bitmap files or a single file containing multiple
+graphics frames. It allows users to easily generate images suitable for
+presentation on the web, either manually or automatically.
+
+
+2. Installation
+---------------
+
+ The SGI translator is distributed in source form and to be used
+must be compiled and installed in the system hbin$ directory. To install
+the new SGI translator follow these steps while logged in through the iraf
+user account:
+
+ [1] Download the translator from the IRAF anonymous FTP archive or
+ one of it's mirror sites using:
+
+ % ftp iraf.noao.edu (140.252.1.1)
+ login: anonymous
+ password: [your email address]
+ ftp> cd /pub
+ ftp> mget sgi2gif.c
+ ftp> quit
+
+ [2] Compile the source using
+
+ % cc -o sgi2gif.e sgi2gif.c # compile the source
+ % mv sgi2gif.e $hbin # move to the $hbin
+
+ "$hbin" is defined in the iraf environment to be something like
+ $iraf/unix/bin.<arch>, where <arch> would be 'ssol' for Solaris,
+ 'sparc' for SunOS and so on.
+
+ [3] Optionally place the source in the directory $iraf/unix/gdev/sgidev.
+
+ [4] Edit the dev$graphcap file and add the following default entries
+ for the device near the top of the file:
+
+ g-gif|UNIX generic interface to multi-frame GIF file generator:\
+ :DD=ugif,tmp$sgk,!{ sgidispatch sgi2gif -w $(PX) -h $(PY) \
+ -bg 0 0 0 -fg 255 255 255 -root sgigif $F.[1-8] ; \
+ rm $F.[1-8]; }&:MF#8:NF:tc=sgi_image_format:
+
+ sgi_image_format|Generic raster file format specification:\
+ :kf=bin$x_sgikern.e:tn=sgikern:ar#.75:\
+ :xr#640:yr#480 :PX#640:PY#480 :XW#640:YW#480:\
+ :BI:MF#1:YF:NB#8:LO#1:LS#0:XO#0:YO#0:
+
+ The 'g-gif' entry takes one or more graphics file input and converts
+ each input frame to a redirected file on output called 'sgigifXXX.gif'
+ where the 'XXX' is frame number. See below for details one
+ configuring other graphcap entries.
+
+
+2. Translator Options
+---------------------
+ The SGI2GIF translator allows the following options:
+
+ -w N Set the width of input bitmap and output image. The
+ argument must be derived from the graphcap value since
+ that is what the SGI kernel will use when generating the
+ bitmap, e.g. "-w $(PX)" instead of "-w 640".
+
+ -h N Set the height of input bitmap and output image. The
+ argument must be derived from the graphcap value since
+ that is what the SGI kernel will use when generating the
+ bitmap, e.g. "-h $(PY)" instead of "-h 640".
+
+ -i Invert the bitmap before conversion. By default the
+ graphics are drawn using the foreground color, this
+ option inverts the bitmap before conversion meaning the
+ graphics are drawn using the background color.
+
+ -t Set background color as transparent. If enabled the
+ translator will produce a GIF89 format image with the
+ background color set as "transparent". When this image
+ is used with an HTML document the background color is
+ the HTML page color.
+
+ -root Set the root rame for output file. If defined this
+ root name will be combined with the frame number and
+ a ".gif" extension to form the output name. If not
+ defined and only one input image is present the default
+ action is to send the output to STDOUT.
+
+ -fg R G B Specify foreground color (default 'black'). Set the
+ foreground color as a triplet of RGB values in the
+ range 0-255. The -fg flag must have three arguments.
+
+ -bg R G B Specify background color (default 'white'). Set the
+ foreground color as a triplet of RGB values in the
+ range 0-255. The -bg flag must have three arguments.
+
+
+3. Configuring Alternate Graphcap Entries
+-----------------------------------------
+
+ Most of the work in a graphcap entry is done by the 'device
+dispose' (i.e. "DD") string. This string is composed of three comma
+delimited parts: a node/device name (which is normally ignored), a
+temporary filename, and a host dispose command. To configure a new entry
+it is only this last field that normally needs to be modified, perhaps in
+conjunction with another graphcap parameter. As an example let's look at
+the DD string used in the example graphcap above:
+
+ :DD=ugif,tmp$sgk,!{ sgidispatch sgi2gif -w $(PX) -h $(PY) \
+ -bg 0 0 0 -fg 255 255 255 -root sgigif $F.[1-8] ; rm $F.[1-8]; }&:
+
+where 'ugif' is the unused node/device name, 'tmp$sgk' is the temporary
+filename, and the remainder is a host dispose command. The 'sgidispatch'
+command is an iraf binary that launches the specified translator
+('sgi2gif' here) with any required arguments. Note that everything within
+the "!{...}&" curly braces is executed (as a background Bourne shell
+command) so any string of valid unix command separate by a semicolon will
+be executed. In this case the sgidispatch command launches the sgi2gif
+translator with all of it's arguments, it then deletes the input metacode
+file symbolized by the "$F".
+ You may notice that some arguments are specified as e.g. "-w
+$(PX)". When the DD string is executed any macro values beginning with a
+'$' such as '$(PX)' are replaced with values from the rest of the graphcap
+entry. In this case '$(PX)' is replaced by the value contained in the
+graphcap :PX (physical X size) field, the "$F.[1-8]" is expanded to
+include the unique root filename along with any extension 1 thru 8 which may
+be generated because of multiple plots in the input. In
+most cases all you may need to change in the DD string itself is the
+output file, or e.g. whether it gets piped to some other command.
+
+
+3.1 Changing Image Size
+-----------------------
+
+ Changing the image size is simply a matter of changing the graphcap
+parameters
+
+ :xr#640:yr#480: sets X,Y device resolution
+ :PX#640:PY#480: sets X,Y physical size of bitmap
+ :XW#640:YW#480: sets X,Y width of plotting window
+
+These are defined in the 'sgi_image_format' entry given above. Graphics
+are drawn using Normalized Device Coordinates ('NDC', values in the range
+0.0 to 1.0) and will be scaled appropriately for any specified output
+dimensions allowing users to configure graphcap entries for images which are
+larger/smaller than the default, or have square or elongated aspect ratios.
+
+3.2 Preserving Color Information
+--------------------------------
+
+ Colors such as those used for the axis labels and frame, and colors
+used in the plot itself for different line/marker types cannot be preserved
+by the SGI kernel directly. To do this you must use a full graphics kernel
+such as the PSIKERN postscript kernel found in STSDAS. The V2.11
+distribution contains graphcap entries suitable for this kernel but assumes
+you have STSDAS available. See the online help for more information about
+this kernel.
+ Using the '-fg' and '-bg' flags will allow you to specify foreground
+and background colors to be used for the plot as a whole. Note that these
+flags require three arguments to specify the RGB color components. The '-t'
+flag may be used to mark the background color as 'transparent' so only the
+foreground color is shown when the image is used in an HTML document.
+
+3.3 Generating Other Image Formats
+----------------------------------
+
+ GIF may be used as an intermediate format which can be converted to
+something else as part of the graphcap DD string. For example, to use the
+ImageMagick CONVERT task to produce a JPEG image the graphcap DD string
+could be written as
+
+ g-jpeg|UNIX generic interface to JPEG file generator:\
+ :DD=ugif,tmp$sgk,!{ sgidispatch sgi2gif -w $(PX) -h $(PY) \
+ -bg 0 0 0 -fg 255 255 255 -root sgi $F | \
+ convert sgi$$.gif sgi$$.jpg ; rm $F; }&: \
+ :MF#1:NF:tc=sgi_image_format:
+
+The DD string first uses the SGI2GIF translator to produce a 'sgi.gif'
+image, then calls the convert task (which is assumed to be in the user's
+path) to convert this to JPEG as a separate step. The :MF field is
+set to one meaning each frame will generate a new file. The '$$' used in
+the filenames (e.g. 'sgi$$.gif') is the process id created for the shell
+running the DD command meaning multiple filenames of the form 'sgi12345.gif'
+will be created, each with a unique id number so the images aren't over-
+written. In the past this form of DD string could be used with the standard
+sgi2uapl postscript translator and a host task such as 'gs' to convert
+postscript to some other format.
+
+4. Interfacing to Web CGI Scripts
+----------------------------------
+
+ It would be impossible to give complete details about interfacing
+IRAF programs to CGI scripts due to the variety of languages and tasks
+that may be used. To begin lets look at how to execute a task from the
+host level, which is essentially what we'll be doing from within a CGI
+script.
+ In principle this can be done in one of two ways: Either invoke
+the executable directly with the correct command line arguments, or run
+the CL with the input redirected to execute the task. In the first case
+you must know in which executable the task resides, core IRAF system tasks
+(e.g. things in the PLOT and IMAGES packages) have their executables in
+the main $iraf/bin.<arch> directory, NOAO package tasks have the
+executables in the $iraf/noao/bin.<arch> directory. There is usually a
+separate executable for each package and you can probably figure out which
+one goes for each package otherwise just look at the package cl file to
+find out, for example the PLOT package defines the task in the
+$iraf/pkg/plot/plot.cl file, if you look in their you'll see that is
+defines the tasks as (part of the file reads)
+
+task contour,
+ surface, hafton, velvect = "plot$x_ncar.e"
+
+which means that the CONTOUR, SURFACE, etc tasks are in the "x_ncar.e"
+executable.
+ Once you find the correct binary, you need to create a file with
+the task parameters: usually it's easiest to set the parameters and then
+dump the parameter file with 'dpar', e.g.
+
+ cl> dpar listpix > listpix.par
+
+It's likely that CGI scripts will need to set certain parameters itself so
+thought must be given to how to edit this list of default parameters with
+values given in the CGI script.
+
+To run the task you would then do something like:
+
+ % $iraf/bin.sparc/x_images.e listpix @listpix.par
+
+In this case you must be careful that ALL of the task parameters are
+defined, this is done by 'dpar' but empty string parameters will always
+be prompted for. On a host command line simply respond to the parameter
+prompts by hitting the return key, from with a CGI script these must
+be supplied automatically in some way (e.g. via redirection).
+ In the second case you create a command file and input it to the
+cl, for example
+
+ % cl < cl.input >& some_logfile
+
+where cl.input contains CL commands such as
+
+ wfits.scale=no # set a parameter wfits image*.imh
+ mta # call a task
+ logout # logout of the CL
+
+You must be careful about making sure you are in the right directory and
+that parameters are given explicitly if they're like to change, but with
+this approach you can call any iraf task.
+
+4.1 Graphics Tasks
+-------------------
+
+ Regardless of the method chosen, you need to be careful about
+redirecting any required input or text/graphics output. Graphics output
+can be redirected either by setting the "device" parameter to e.g. 'vdm'
+to create a file called 'vdm' in the uparm directory, or using the '>G' CL
+syntax as in
+
+ cl> surface dev$pix >G surf.plot # redirect metacode to a file
+ cl> surface dev$pix dev="vdm" # save metacode to uparm dir
+ cl> surface dev$pix dev="stdplot" # to print it out
+ cl> gflush # flush graphics buffer
+
+Which of these approaches works best for depends depends on the tasks you
+need and the method of execution chosen above. Note that the ">G" syntax
+will only work for tasks executed within the CL, setting a device
+parameter to something that creates a file will work with either method.
+ For non-interactive tasks like SURFACE or CONTOUR this file is
+created automatically, interactive tasks however may need to create
+metacode files explicitly or else the CGI script must take care to extract
+only those plots of interest from the metacode file (e.g. with a separate
+call to GKIEXTRACT).
+ Interactive tasks must also satisfy requests for cursor commands,
+including the usual 'q' keystroke needed to exit the task. Since cursor
+commands are in reality queries to the CL any binary run as a host task
+will generate a cursor prompt on the standard output the same as for any
+other parameter query. The response to a cursor query however is usually
+of the form
+ x y wcs key strval
+
+where 'x' and 'y' are the cursor position, 'wcs' is the WCS of those coords
+(usually not important), 'key' is the keystroke you would normally enter,
+and if 'key' is a color the 'strval' is the remainder of that color command.
+See section 3.7 of the "help cursors" help page for more details on alternate
+graphics input. Note however, that your CGI script must know in advance the
+order in which the prompts will occur to be able to satisfy them correctly,
+e.g. any parameter prompts generated by empty string values should be met
+with a newline, and cursor prompts with something as above. Since the tasks
+will be very narrowly defined as to how they are run this usually isn't
+difficult to set up.
+
+4.2 Example
+-----------
+
+ As an example let create a CGI script to execute the PCOL task
+from a web interface. All that we need to do this is the PLOT package
+binary to execute the task, a 'graphcap' file, and the SGIKERN binary in
+order to convert our graphics metacode to a GIF format using the specified
+graphcap entries and the newly installed SGI2GIF translator. In the
+following we detail the steps involved in creating this script on a system
+with IRAF installed, your application may vary somewhat. We use a
+C-shell script here but the same principles apply to all scripting
+languages, users should contact site support with questions.
+
+-----------------------------------------------------------------------------
+
+#!/bin/csh -f
+#
+# Sample CGI script demonstrating the using the PCOL graphics task to
+# produce an 'sgigif.gif' file of the resulting plot which can be shown
+# as an image of the output web page. The script does not show how to
+# parse arguments or format the resulting HTML page. All that is required
+# for IRAF execution is the binary for the task to be run, the SGIKERN
+# binary, and a graphcap file to produce the GIF (given below). The CGI
+# script can define the task parameters itself or use a predefined 'dpar'
+# dump to set defaults as we do below.
+
+# The REMOTE_ADDR variable is defined in the environment of the CGI
+# script automatically, we specify it here for demonstration purposes.
+set REMOTE_ADDR = 140.252.30.95
+
+# This would be defined as the graphcap file installed for the local web
+# server.
+
+# The only graphcap entries needed to output graphics to a GIF file using
+# the SGI translator is as follows:
+#
+# vdm|stdvdm|Virtual Device Metafile:\
+# :co#80:li#35:xr#1024:yr#1024:zr#256:ar#.77:ch#.0294:cw#.0125:\
+# :X1#0:X2#1023:Y1#0:Y2#1023:
+#
+# g-gif|UNIX generic interface to multi-frame GIF file generator:\
+# :DD=ugif,tmp$sgk,!{ /<path>/sgi2gif.e -w $(PX) -h $(PY) \
+# -bg 0 0 0 -fg 255 255 255 -root sgigif $F.[1-8] ; \
+# rm $F.[1-8]; }&:MF#8:NF:tc=sgi_image_format:
+#
+# sgi_image_format|Generic raster file format specification:\
+# :kf=bin$x_sgikern.e:tn=sgikern:ar#.75:\
+# :xr#640:yr#480:PX#640:PY#480:XW#640:YW#480:\
+# :BI:MF#1:YF:NB#8:LO#1:LS#0:XO#0:YO#0:
+#
+# Note that the path to the sgigif.e binary is specified explicitly, this
+# must be replaced by the path to the actual binary.
+#
+# On the web server this file would normally be installed in the cgi-bin
+# or some other directory, the cgi script itself needs to define this location
+# with the following variable:
+
+set graphcap = /tmp/graphcap
+
+# A uparm directory needs to be defined for saving the VDM file. This is
+# defined based on the REMOTE_ADDR so we can have multiple connections
+# running at the same time without concurrency problems.
+
+set uparm = /tmp/uparm-$REMOTE_ADDR/
+
+# Create the uparm directory we'll be using...
+mkdir $uparm
+
+# Execute the graphics task desired. In this example we're running the PCOL
+# task and assume we've saved the parameters to a 'pcol.dpar' file in the
+# current directory. In practice the parameters can be specified using a
+# dpar file in the cgi-bin dir or explicitly on the command line. To execute
+# the task we call the binary directly, direct output to /dev/null and
+# redirect input blank lines to respond to params that take no value. We
+# must set the uparm and graphcap values set above to handle the graphics.
+# The CGI script can insert values such as 'image' based on arguments, the
+# defaults come from a predefined dpar file.
+
+/iraf/iraf/bin.ssun/x_plot.e >>& /dev/null << EOF
+set uparm = $uparm
+set graphcap = $graphcap
+pcol @pcol.dpar pcol.device="vdm"
+
+EOF
+
+# At this point the GKI metacode is saved in the uparm$vdm file, where
+# 'uparm' is set above and is created by the custom graphcap file we're
+# using. To convert GKI metacode to the final GIF file we call the SGIKERN
+# directly and specify the device as 'g-gif' which produces an 'sgigif.gif'
+# file in the current directory. Graphcap entries can be created to name
+# the file anything desired, that filename is then used as a URL for the
+# web page returned.
+
+/iraf/iraf/bin.ssun/x_sgikern.e >>& /dev/null << EOF
+set uparm = $uparm
+set graphcap = $graphcap
+sgikern input=uparm\$vdm device=g-gif generic=yes
+EOF
+
+# Finally, clean up the temp files we've created.
+/bin/rm -rf $uparm
+
diff --git a/unix/gdev/sgidev/mkpkg b/unix/gdev/sgidev/mkpkg
new file mode 100644
index 00000000..e9dac3df
--- /dev/null
+++ b/unix/gdev/sgidev/mkpkg
@@ -0,0 +1,9 @@
+# Make the SGI device host level translation programs [MACHDEP].
+
+$call update
+$exit
+
+update:
+ ! sh -x mkpkg.sh
+ ! mv $hlib/sgi*.e $hbin
+ ;
diff --git a/unix/gdev/sgidev/mkpkg.sh b/unix/gdev/sgidev/mkpkg.sh
new file mode 100644
index 00000000..85d6c83a
--- /dev/null
+++ b/unix/gdev/sgidev/mkpkg.sh
@@ -0,0 +1,60 @@
+# Make the SGI translators and install them in hlib.
+
+$CC -c $HSI_CF sgiUtil.c
+
+$CC -c $HSI_CF sgidispatch.c
+$CC $HSI_LF sgidispatch.o ../../hlib/libos.a $HSI_LIBS -o sgidispatch.e
+mv -f sgidispatch.e ../../hlib
+rm sgidispatch.o
+
+$CC -c $HSI_CF sgi2uimp.c
+$CC $HSI_LF sgi2uimp.o sgiUtil.o $HSI_LIBS -o sgi2uimp.e
+mv -f sgi2uimp.e ../../hlib
+rm sgi2uimp.o
+
+$CC -c $HSI_CF sgi2uapl.c
+$CC $HSI_LF sgi2uapl.o sgiUtil.o $HSI_LIBS -o sgi2uapl.e
+mv -f sgi2uapl.e ../../hlib
+rm sgi2uapl.o
+
+$CC -c $HSI_CF sgi2uqms.c
+$CC $HSI_LF sgi2uqms.o sgiUtil.o $HSI_LIBS -o sgi2uqms.e
+mv -f sgi2uqms.e ../../hlib
+rm sgi2uqms.o
+
+$CC -c $HSI_CF sgi2uptx.c
+$CC $HSI_LF sgi2uptx.o sgiUtil.o $HSI_LIBS -o sgi2uptx.e
+mv -f sgi2uptx.e ../../hlib
+rm sgi2uptx.o
+
+$CC -c $HSI_CF sgi2uhplj.c
+$CC $HSI_LF sgi2uhplj.o sgiUtil.o $HSI_LIBS -o sgi2uhplj.e
+mv -f sgi2uhplj.e ../../hlib
+rm sgi2uhplj.o
+
+$CC -c $HSI_CF sgi2uhpgl.c
+$CC $HSI_LF sgi2uhpgl.o sgiUtil.o $HSI_LIBS -o sgi2uhpgl.e
+mv -f sgi2uhpgl.e ../../hlib
+rm sgi2uhpgl.o
+
+$CC -c $HSI_CF sgi2ueps.c
+$CC $HSI_LF sgi2ueps.o sgiUtil.o $HSI_LIBS -o sgi2ueps.e
+mv -f sgi2ueps.e ../../hlib
+rm sgi2ueps.o
+
+$CC -c $HSI_CF sgi2gif.c
+$CC $HSI_LF sgi2gif.o sgiUtil.o $HSI_LIBS -o sgi2gif.e
+mv -f sgi2gif.e ../../hlib
+rm sgi2gif.o
+
+$CC -c $HSI_CF sgi2xbm.c
+$CC $HSI_LF sgi2xbm.o sgiUtil.o $HSI_LIBS -o sgi2xbm.e
+mv -f sgi2xbm.e ../../hlib
+rm sgi2xbm.o
+
+$CC -c $HSI_CF sgi2svg.c
+$CC $HSI_LF sgi2svg.o sgiUtil.o $HSI_LIBS -o sgi2svg.e
+mv -f sgi2svg.e ../../hlib
+rm sgi2svg.o
+
+rm sgiUtil.o
diff --git a/unix/gdev/sgidev/sgi2gif.c b/unix/gdev/sgidev/sgi2gif.c
new file mode 100644
index 00000000..e46d4d28
--- /dev/null
+++ b/unix/gdev/sgidev/sgi2gif.c
@@ -0,0 +1,731 @@
+/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+ */
+
+#include <stdio.h>
+#include <ctype.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include "sgiUtil.h"
+
+
+/*
+ * SGI2GIF.C -- Read an IRAF SGI bitmap file on standard input and convert
+ * to a GIF format image on standard outout.
+ *
+ * Usage:
+ * sgi2gif.e [-params] [ [sgi_bitmap] [sgi_bitmap] ... ]
+ *
+ * -w N width of input bitmap and output image
+ * -h N height of input bitmap and output image
+ * -i invert the bitmap values before conversion
+ * -t set background color as transparent
+ * -root set the root rame for output file (default stdout)
+ * -fg R G B specify foreground color
+ * -bg R G B specify background color
+ *
+ * The input file name and the switches may occur in any order. The
+ * foreground/background flags require three arguments giving the values
+ * of the RGB components of the color as a decimal number in the range 0-255.
+ * Enabling the transparency flag will cause a GIF 89 image to be written,
+ * otherwise the default will be a GIF 87 format image. The transparent
+ * color will always be the backgrund color. The bitmap may be inverted
+ * here using the -i flag.
+ *
+ * Sample graphcaps for this translator might look like:
+ *
+ * g-gif|UNIX generic interface to multi-frame GIF file generator:\
+ * :DD=ugif,tmp$sgk,!{ sgidispatch sgi2gif -w $(PX) -h $(PY) \
+ * -bg 0 0 0 -fg 255 255 255 -root sgigif $F.[1-8] ; \
+ * rm $F.[1-8]; }&:MF#8:NF:tc=sgi_image_format:
+ *
+ * sgi_image_format|Generic raster file format specification:\
+ * :kf=bin$x_sgikern.e:tn=sgikern:ar#.75:\
+ * :xr#640:yr#480:PX#640:PY#480:XW#640:YW#480:\
+ * :BI:MF#1:YF:NB#8:LO#1:LS#0:XO#0:YO#0:
+ *
+ * The 'g-gif' entry takes one or more graphics file input and converts
+ * each input frame to a redirected file on output called 'sgigifXXX.gif'
+ * where the 'XXX' is frame number.
+ *
+ * To change the image size the graphcap :xr, :PX, :XW (X-dimension) and
+ * :yr, :PY, :XY (Y-dimension) fields all need to be changed. The -i
+ * or -t flags must be specified in the graphcap DD string along with the
+ * -fg/bg flags and their arguments.
+ */
+
+
+#define NBITS_CHAR 8 /* number of bits in a char */
+#define DEF_WIDTH 640 /* default image width */
+#define DEF_HEIGHT 480 /* default image height */
+#define DEF_BG 255 /* default background RGB */
+#define DEF_FG 0 /* default foreground RGB */
+#define MAX_INFILES 16 /* max number of input bitmaps */
+#define SZ_FNAME 64 /* size of a filename */
+
+typedef int code_int;
+typedef long int count_int;
+typedef unsigned char byte;
+
+static byte *pixels;
+
+static int px = DEF_WIDTH;
+static int py = DEF_HEIGHT;
+static int nrows = DEF_HEIGHT;
+static int ncols = DEF_WIDTH;
+static int transparent = 0;
+static int invert = 0;
+static int red[] = { DEF_BG, DEF_FG } ;
+static int green[] = { DEF_BG, DEF_FG } ;
+static int blue[] = { DEF_BG, DEF_FG } ;
+static char *infile[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static char *s_root = "sgigif_";
+
+static int GIFNextPixel();
+static void BumpPixel(), GIFEncode(), Putword(), compress();
+static void output(), cl_block(), cl_hash(), char_init();
+static void char_out(), flush_char(), unpack1to8();
+
+
+
+/* MAIN -- Main entry point for the task.
+ */
+int
+main (int argc, char *argv[])
+{
+ FILE *fdi, *fdo;
+ char fname[SZ_FNAME];
+ char *root = s_root;
+ byte *buffer, *ip;
+ int i, index, numin=0, len_buf;
+ int interlace, background, bpp;
+
+
+ /* Process the command line.
+ */
+ for (i=1; i < argc; i++) {
+ if (argv[i][0] == '-') {
+ if (strcmp (argv[i], "-w") == 0) {
+ ncols = px = atoi (argv[++i]);
+ } else if (strcmp (argv[i], "-h") == 0) {
+ nrows = py = atoi (argv[++i]);
+ } else if (strcmp (argv[i], "-i") == 0) {
+ invert++;
+ } else if (strcmp (argv[i], "-root") == 0) {
+ root = argv[++i];
+ } else if (strcmp (argv[i], "-t") == 0) {
+ transparent++;
+ } else if (strcmp (argv[i], "-bg") == 0) {
+ if (isdigit(argv[++i][0]))
+ red[0] = atoi (argv[i]);
+ else
+ fprintf (stderr,
+ "sgi2gif: invalid -bg arg '%s'\n", argv[i]);
+ if (isdigit(argv[++i][0]))
+ green[0] = atoi (argv[i]);
+ else
+ fprintf (stderr,
+ "sgi2gif: invalid -bg arg '%s'\n", argv[i]);
+ if (isdigit(argv[++i][0]))
+ blue[0] = atoi (argv[i]);
+ else
+ fprintf (stderr,
+ "sgi2gif: invalid -bg arg '%s'\n", argv[i]);
+ } else if (strcmp (argv[i], "-fg") == 0) {
+ if (isdigit(argv[++i][0]))
+ red[1] = atoi (argv[i]);
+ else
+ fprintf (stderr,
+ "sgi2gif: invalid -bg arg '%s'\n", argv[i]);
+ if (isdigit(argv[++i][0]))
+ green[1] = atoi (argv[i]);
+ else
+ fprintf (stderr,
+ "sgi2gif: invalid -bg arg '%s'\n", argv[i]);
+ if (isdigit(argv[++i][0]))
+ blue[1] = atoi (argv[i]);
+ else
+ fprintf (stderr,
+ "sgi2gif: invalid -bg arg '%s'\n", argv[i]);
+ } else {
+ fprintf (stderr, "sgi2gif: unknown switch '%s'\n", argv[i]);
+ }
+ } else {
+ /* input sgi-bitmap file specification */
+ if (numin < MAX_INFILES)
+ infile[numin++] = argv[i];
+ }
+ }
+
+ /* Allocate space for the images. */
+ len_buf = px / NBITS_CHAR;
+ buffer = (byte *) malloc (len_buf);
+ ip = pixels = (byte *) malloc (px * (py + 1));
+
+ /* Loop over the input bitmaps, writing the converted output to
+ * either stdout or a filename.
+ */
+ for (index = 0; index == 0 || index < numin; index++) {
+
+ /* Open the input file. */
+ fdi = (infile[index] ? fopen (infile[index], "r") : stdin);
+
+ /* Open the output file. For multiple input files force each
+ * output to a new image, when reading from stdin or only one
+ * bitmap write to stdout if we didn't set the rootname.
+ */
+ if (numin <= 1 && strcmp (root, s_root) == 0) {
+ fdo = stdout;
+ } else {
+ if (numin > 1)
+ sprintf (fname, "%s%d.gif", root, index);
+ else
+ sprintf (fname, "%s.gif", root);
+ fdo = fopen (fname, "w+");
+ }
+
+ /* Now unpack this bitmap to the output image as byte data. */
+ ip = pixels;
+ while (fread (buffer, len_buf, 1, fdi)) {
+ /* If we're on a MSB ordered machine wordswap the bitmap so
+ * it's in the correct order for unpacking to be interpreted
+ * as an LSB-ordered image.
+ */
+ if ( ! isSwapped ())
+ bswap4 (buffer, buffer, len_buf);
+
+ unpack1to8 ((ip+=px), buffer, px);
+ }
+
+ /* All set, write it out. */
+ GIFEncode (fdo, px, py, (interlace=0), (background=0), (bpp=1),
+ red, green, blue);
+
+ fflush (fdi);
+ fflush (fdo);
+ if (fdi != stdin)
+ fclose (fdi);
+ if (fdo != stdout)
+ fclose (fdo);
+ }
+
+ /* Clean up. */
+ free (buffer);
+ free (pixels);
+
+ return (0);
+}
+
+
+/* UNPACK1TO8 -- Unpack each bit in the bitmap to a byte on output.
+ */
+
+static void
+unpack1to8 (byte *dest, byte *src, int len)
+{
+ register int i, b;
+ byte c = 0;
+
+ for (i = 0, b = 0; i < len; i++) {
+ if (b > 7) {
+ b = 0;
+ c = (invert ? ~(*src++) : (*src++) );
+ }
+ *dest++ = (byte) ((c >> (b++)) & 1);
+ }
+}
+
+
+/* GIF Writing Procedures.
+ *
+ * Based on GIFENCOD by David Rowley <mgardi@watdscu.waterloo.edu>. A
+ * Lempel-Zim compression based on "compress". Original Copyright 1990,
+ * David Koblas, heavily modified since then....
+ */
+
+#define GIFBITS 12
+
+static int Width, Height;
+static int curx, cury;
+static long CountDown;
+static int Interlace;
+
+
+/* GIFENCODE -- GIF Image compression interface.
+ */
+
+static void
+GIFEncode (fp, GWidth, GHeight, GInterlace, Background, Bpp, Red, Green, Blue)
+FILE *fp;
+int GWidth, GHeight;
+int GInterlace;
+int Background;
+int Bpp;
+int Red[], Green[], Blue[];
+{
+ int B;
+ int RWidth, RHeight;
+ int LeftOfs, TopOfs;
+ int Resolution;
+ int ColorMapSize;
+ int InitCodeSize;
+ int i;
+
+ Interlace = GInterlace;
+
+ ColorMapSize = 1 << Bpp;
+
+ RWidth = Width = GWidth;
+ RHeight = Height = GHeight;
+ LeftOfs = TopOfs = 0;
+
+ Resolution = Bpp;
+
+ /* Calculate number of bits we are expecting */
+ CountDown = (long)Width * (long)Height;
+
+ /* The initial code size */
+ if (Bpp <= 1)
+ InitCodeSize = 2;
+ else
+ InitCodeSize = Bpp;
+
+ /* Set up the current x and y position */
+ curx = cury = 0;
+
+ /* Write the Magic header */
+ fwrite ((transparent ? "GIF89a" : "GIF87a"), 1, 6, fp);
+
+ /* Write out the screen width and height */
+ Putword (RWidth, fp);
+ Putword (RHeight, fp);
+
+ /* Indicate that there is a global colour map */
+ B = 0x80; /* Yes, there is a color map */
+
+ /* OR in the resolution */
+ B |= (Resolution - 1) << 5;
+
+ /* OR in the Bits per Pixel */
+ B |= (Bpp - 1);
+
+ /* Write it out */
+ fputc (B, fp);
+
+ /* Write out the Background colour */
+ fputc (Background, fp);
+
+ /* Byte of 0's (future expansion) */
+ fputc (0, fp);
+
+ /* Write out the Global Colour Map */
+ for (i = 0; i < ColorMapSize; ++i) {
+ fputc (Red[i], fp);
+ fputc (Green[i], fp);
+ fputc (Blue[i], fp);
+ }
+
+ /* If doing transparency, write the extension. */
+ if (transparent) {
+ fputc (0x21, fp); /* graphics extension... */
+ fputc (0xf9, fp); /* transparency... */
+ fputc (0x4, fp);
+ fputc (0x1, fp);
+ fputc (0x0, fp);
+ fputc (0x0, fp);
+ fputc ((char) 0, fp); /* background color index */
+ fputc (0x0, fp);
+ }
+
+ /* Write an Image separator */
+ fputc (',', fp);
+
+ /* Write the Image header */
+ Putword (LeftOfs, fp);
+ Putword (TopOfs, fp);
+ Putword (Width, fp);
+ Putword (Height, fp);
+
+ /* Write out whether or not the image is interlaced */
+ if (Interlace)
+ fputc (0x40, fp);
+ else
+ fputc (0x00, fp);
+
+ /* Write out the initial code size */
+ fputc (InitCodeSize, fp);
+
+ /* Go and actually compress the data */
+ compress (InitCodeSize + 1, fp);
+
+ /* Write out a Zero-length packet (to end the series) */
+ fputc (0, fp);
+
+ /* Write the GIF file terminator */
+ fputc (';', fp);
+}
+
+
+/* Bump the 'curx' and 'cury' to point to the next pixel
+ */
+static void
+BumpPixel()
+{
+ /* Bump the current X position */
+ ++curx;
+
+ /* If at the end of a scan line, set curx back to the beginning. */
+ if (curx == Width) {
+ curx = 0;
+ ++cury;
+ }
+}
+
+
+/* Return the next pixel from the image
+ */
+static int
+GIFNextPixel ()
+{
+ int r;
+
+ if (CountDown == 0)
+ return EOF;
+
+ --CountDown;
+ r = (int) pixels[ cury * ncols + curx ] ;
+ BumpPixel();
+ return r;
+}
+
+
+/* Write out a word to the GIF file
+ */
+static void
+Putword (w, fp)
+int w;
+FILE*fp;
+{
+ unsigned short val = w;
+
+ fputc (val & 0xff, fp);
+ fputc ((val / 256) & 0xff, fp);
+}
+
+
+/*
+ * GIF Image compression - modified 'compress'
+ *
+ * Based on: compress.c - File compression ala IEEE Computer, June 1984.
+ *
+ * By Authors: Spencer W. Thomas, Jim McKie, Steve Davies, Ken Turkowski,
+ * James A. Woods, Joe Orost
+ *
+ * Lempel-Ziv compression based on 'compress'. GIF modifications by
+ * David Rowley (mgardi@watdcsu.waterloo.edu)
+ */
+
+#define HSIZE 5003 /* 80% occupancy */
+
+static int n_bits; /* number of bits/code */
+static int maxbits = GIFBITS; /* user settable max # bits/code */
+static code_int maxcode; /* maximum code, given n_bits */
+ /* should NEVER generate this code */
+static code_int maxmaxcode = (code_int) 1 << GIFBITS;
+#define MAXCODE(n_bits) (((code_int) 1 << (n_bits)) - 1)
+
+static count_int htab[HSIZE];
+static unsigned short codetab [HSIZE];
+#define HashTabOf(i) htab[i]
+#define CodeTabOf(i) codetab[i]
+
+/* To save much memory, we overlay the table used by compress() with those
+ * used by decompress(). The tab_prefix table is the same size and type
+ * as the codetab. The tab_suffix table needs 2**GIFBITS characters. We
+ * get this from the beginning of htab. The output stack uses the rest
+ * of htab, and contains characters. There is plenty of room for any
+ * possible stack (stack used to be 8000 characters).
+ */
+
+#define tab_prefixof(i) CodeTabOf(i)
+#define tab_suffixof(i) ((unsigned char *)(htab))[i]
+
+static code_int free_ent = 0; /* first unused entry */
+static code_int hsize = HSIZE; /* for dynamic table sizing */
+
+
+/* block compression parameters -- after all codes are used up,
+ * and compression rate changes, start over.
+ */
+static int clear_flg = 0;
+
+/*
+ * compress stdin to stdout
+ *
+ * Algorithm: use open addressing double hashing (no chaining) on the
+ * prefix code / next character combination. We do a variant of Knuth's
+ * algorithm D (vol. 3, sec. 6.4) along with G. Knott's relatively-prime
+ * secondary probe. Here, the modular division first probe is gives way
+ * to a faster exclusive-or manipulation. Also do block compression with
+ * an adaptive reset, whereby the code table is cleared when the compression
+ * ratio decreases, but after the table fills. The variable-length output
+ * codes are re-sized at this point, and a special CLEAR code is generated
+ * for the decompressor. Late addition: construct the table according to
+ * file size for noticeable speed improvement on small files. Please direct
+ * questions about this implementation to ames!jaw.
+ */
+
+static FILE *g_outfile;
+static int g_init_bits;
+static int ClearCode;
+static int EOFCode;
+static int cur_bits = 0;
+
+static unsigned long cur_accum = 0;
+static unsigned long masks[] = {
+ 0x0000, 0x0001, 0x0003, 0x0007, 0x000F,
+ 0x001F, 0x003F, 0x007F, 0x00FF,
+ 0x01FF, 0x03FF, 0x07FF, 0x0FFF,
+ 0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF };
+
+static int a_count; /* Number of characters so far in this 'packet' */
+static char accum[256]; /* Define the storage for the packet accumulator */
+
+static void
+compress (init_bits, outfile)
+int init_bits;
+FILE *outfile;
+{
+ register long fcode;
+ register code_int i /* = 0 */;
+ register int c;
+ register code_int ent;
+ register code_int disp;
+ register code_int hsize_reg;
+ register int hshift;
+
+ /* Set up the globals: g_init_bits - initial number of bits
+ * g_outfile - pointer to output file
+ */
+ g_init_bits = init_bits;
+ g_outfile = outfile;
+
+ /* Set up the necessary values */
+ clear_flg = 0;
+ cur_accum = 0;
+ cur_bits = 0;
+ maxbits = GIFBITS;
+ maxcode = MAXCODE(n_bits = g_init_bits);
+
+ ClearCode = (1 << (init_bits - 1));
+ EOFCode = ClearCode + 1;
+ free_ent = ClearCode + 2;
+
+ char_init();
+ for (i=0; i<HSIZE; i++) {
+ htab[i] = 0;
+ codetab[i] = 0;
+ }
+
+ ent = GIFNextPixel ();
+
+ hshift = 0;
+ for (fcode = (long) hsize; fcode < 65536L; fcode *= 2L)
+ ++hshift;
+ hshift = 8 - hshift; /* set hash code range bound */
+
+ hsize_reg = hsize;
+ cl_hash ((count_int) hsize_reg); /* clear hash table */
+
+ output ((code_int)ClearCode);
+
+ while ((c = GIFNextPixel ()) != EOF) {
+
+ fcode = (long) (((long) c << maxbits) + ent);
+ i = (((code_int)c << hshift) ^ ent); /* xor hashing */
+
+ if (HashTabOf (i) == fcode) {
+ ent = CodeTabOf (i);
+ continue;
+ } else if ((long)HashTabOf (i) < 0) /* empty slot */
+ goto nomatch;
+ disp = hsize_reg - i; /* secondary hash (after G. Knott) */
+ if (i == 0)
+ disp = 1;
+probe:
+ if ((i -= disp) < 0)
+ i += hsize_reg;
+
+ if (HashTabOf (i) == fcode) {
+ ent = CodeTabOf (i);
+ continue;
+ }
+ if ((long)HashTabOf (i) > 0)
+ goto probe;
+nomatch:
+ output ((code_int) ent);
+ ent = c;
+ if (free_ent < maxmaxcode) { /* } */
+ CodeTabOf (i) = free_ent++; /* code -> hashtable */
+ HashTabOf (i) = fcode;
+ } else
+ cl_block();
+ }
+
+ /*
+ * Put out the final code.
+ */
+ output ((code_int)ent);
+ output ((code_int) EOFCode);
+}
+
+/*
+ * Output the given code.
+ * Inputs:
+ * code: A n_bits-bit integer. If == -1, then EOF. This assumes
+ * that n_bits =< (long)wordsize - 1.
+ * Outputs:
+ * Outputs code to the file.
+ * Assumptions:
+ * Chars are 8 bits long.
+ * Algorithm:
+ * Maintain a GIFBITS character long buffer (so that 8 codes will
+ * fit in it exactly). Use the VAX insv instruction to insert each
+ * code in turn. When the buffer fills up empty it and start over.
+ */
+
+static void
+output (code)
+code_int code;
+{
+ cur_accum &= masks[ cur_bits ];
+
+ if (cur_bits > 0)
+ cur_accum |= ((long)code << cur_bits);
+ else
+ cur_accum = code;
+
+ cur_bits += n_bits;
+
+ while (cur_bits >= 8) {
+ char_out ((unsigned int)(cur_accum & 0xff));
+ cur_accum >>= 8;
+ cur_bits -= 8;
+ }
+
+ /*
+ * If the next entry is going to be too big for the code size,
+ * then increase it, if possible.
+ */
+ if (free_ent > maxcode || clear_flg) {
+
+ if (clear_flg) {
+ maxcode = MAXCODE (n_bits = g_init_bits);
+ clear_flg = 0;
+ } else {
+ ++n_bits;
+ if (n_bits == maxbits)
+ maxcode = maxmaxcode;
+ else
+ maxcode = MAXCODE(n_bits);
+ }
+ }
+
+ if (code == EOFCode) {
+ /* At EOF, write the rest of the buffer. */
+ while (cur_bits > 0) {
+ char_out ((unsigned int)(cur_accum & 0xff));
+ cur_accum >>= 8;
+ cur_bits -= 8;
+ }
+ flush_char();
+ fflush (g_outfile);
+ if (ferror (g_outfile))
+ perror ("error writing output file");
+ }
+}
+
+/*
+ * Clear out the hash table
+ */
+static void
+cl_block () /* table clear for block compress */
+{
+
+ cl_hash ((count_int) hsize);
+ free_ent = ClearCode + 2;
+ clear_flg = 1;
+
+ output ((code_int)ClearCode);
+}
+
+static void
+cl_hash(hsize) /* reset code table */
+register count_int hsize;
+{
+
+ register count_int *htab_p = htab + hsize;
+
+ register long i;
+ register long m1 = -1;
+
+ i = hsize - 16;
+ do { /* might use Sys V memset(3) here */
+ *(htab_p - 16) = m1;
+ *(htab_p - 15) = m1;
+ *(htab_p - 14) = m1;
+ *(htab_p - 13) = m1;
+ *(htab_p - 12) = m1;
+ *(htab_p - 11) = m1;
+ *(htab_p - 10) = m1;
+ *(htab_p - 9) = m1;
+ *(htab_p - 8) = m1;
+ *(htab_p - 7) = m1;
+ *(htab_p - 6) = m1;
+ *(htab_p - 5) = m1;
+ *(htab_p - 4) = m1;
+ *(htab_p - 3) = m1;
+ *(htab_p - 2) = m1;
+ *(htab_p - 1) = m1;
+ htab_p -= 16;
+ } while ((i -= 16) >= 0);
+
+ for (i += 16; i > 0; --i)
+ *--htab_p = m1;
+}
+
+/* Set up the 'byte output' routine
+ */
+static void
+char_init()
+{
+ register int i;
+
+ a_count = 0;
+ for (i=0; i<256; i++)
+ accum[i] = 0;
+}
+
+/* Add a character to the end of the current packet, and if it is 254
+ * characters, flush the packet to disk.
+ */
+static void
+char_out (c)
+int c;
+{
+ accum[ a_count++ ] = c;
+ if (a_count >= 254)
+ flush_char();
+}
+
+/* Flush the packet to disk, and reset the accumulator */
+static void
+flush_char()
+{
+ if (a_count > 0) {
+ fputc (a_count, g_outfile);
+ fwrite (accum, 1, a_count, g_outfile);
+ a_count = 0;
+ }
+}
diff --git a/unix/gdev/sgidev/sgi2svg.c b/unix/gdev/sgidev/sgi2svg.c
new file mode 100644
index 00000000..be25a704
--- /dev/null
+++ b/unix/gdev/sgidev/sgi2svg.c
@@ -0,0 +1,245 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <string.h>
+
+#define import_spp
+#define import_error
+#include <iraf.h>
+
+#include "sgiUtil.h"
+
+
+/*
+** SGI2SVG.C -- Read IRAF SGI metacode from standard input, translate into
+** Scalable Vector Graphics (SVG) format.
+**
+** Usage
+** sgi2svg.e [-params] [sgi_metacode] [| lpr -Papple]
+**
+** -fg <N> FG color specified as RGB triplet (e.g. 'F00' is red)
+** -bg <N> BG color specified as RGB triplet (e.g. '0F0' is green)
+** -fill <N> fill color specified as RGB triplet (e.g. '00F' is blue)
+** -w <N> width of plot, device pixels starting from l
+** -h <N> height of plot, device pixels starting from b
+** -p <N> pen width
+**
+** Option values must be separated from their flags by a space; the input
+** file name and the switches may occur in any order.
+**
+** Sample Graphcap:
+**
+** g-svg|UNIX generic interface to SVG file generator:\
+** :DD=usvg,tmp$sgk,!{ sgidispatch sgi2svg -w $(PX) -h $(PY) \
+** -bg FFF -fg 000 -fill FFF $F > sgi$$.svg ; }&:PX#640:PY#480:\
+** :kf=bin$x_sgikern.e:tn=sgikern:tc=sgi_apl:
+*/
+
+#define OSOK 0 /* normal successful completion */
+#define LEN_MCBUF 1024 /* number of SGK instrs in buffer */
+#define SGK_FRAME 1 /* new frame instruction */
+#define SGK_MOVE 2 /* move pen */
+#define SGK_DRAW 3 /* draw pen */
+#define SGK_SETLW 4 /* set line width */
+#define GKI_MAXNDC 32767. /* SGK units */
+
+
+/* Device opcodes and parameters.
+ */
+#define DEF_LEFT 0 /* origin in device pixels in x */
+#define DEF_BOTTOM 0 /* origin in device pixels in y */
+#define DEF_WIDTH 640 /* width in x (240d/i, 11" paper) */
+#define DEF_HEIGHT 480 /* height in y (240d/i, 8.5" paper)*/
+#define DEF_PENWIDTH 1 /* origin in device pixels in x */
+
+
+/* Commands to setup SVG environment.
+*/
+static char *svg_prolog[] = {
+ "<?xml version=\"1.0\" standalone=\"no\"?>\n",
+ "<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\"\n",
+ " \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\n",
+ NULL
+};
+
+/* Opcode instruction.
+*/
+struct sgi_inst {
+ short opcode;
+ short x, y;
+};
+
+
+int pen_width = DEF_PENWIDTH; /* initial line width */
+int width = DEF_WIDTH; /* margins */
+int height = DEF_HEIGHT;
+char *bg = "#FFF"; /* BG/FG colors */
+char *fg = "#000";
+char *fill = "#FFF"; /* vector fill color */
+
+
+static void translate (FILE *in, FILE *out);
+
+
+
+/* MAIN -- Main entry point for SGI2UHPGL. Optional arguments are device
+** window parameters and name of input file.
+*/
+int
+main (int argc, char *argv[])
+{
+ FILE *in;
+ char *infile = "stdin", *argp;
+ int argno;
+ register char **lp;
+
+
+ /* Process the command line.
+ */
+ for (argno=1; (argp = argv[argno]) != NULL; argno++) {
+ if (argp[0] == '-') {
+ /* A window-control or pen width switch.
+ */
+ switch (argp[1]) {
+ case 'f':
+ if (argp[2] == 'g')
+ fg = argv[++argno];
+ else
+ fill = argv[++argno];
+ break;
+ case 'b':
+ bg = argv[++argno];
+ break;
+ case 'w': width = atoi (argv[++argno]); break;
+ case 'h': height = atoi (argv[++argno]); break;
+ case 'p': pen_width = atoi (argv[++argno]); break;
+ default:
+ break;
+ }
+
+ } else {
+ /* Input sgi-metacode file specification.
+ */
+ infile = argp;
+ }
+ }
+
+
+ /* Open the input file. */
+ if (strcmp (infile, "stdin") == 0)
+ in = stdin;
+ else
+ in = fopen (infile, "r");
+ if (in == NULL) {
+ fprintf (stderr, "Fatal error (sgi2svg): Cannot open `%s'\n",
+ infile);
+ fflush (stderr);
+ exit (OSOK+1);
+ }
+
+
+ /* Output the standard prolog.
+ */
+ for (lp=svg_prolog; *lp; lp++)
+ fputs (*lp, stdout);
+
+ fprintf (stdout,"<svg width=\"%dpx\" height=\"%dpx\" version=\"1.1\"\n",
+ width, height);
+ fprintf (stdout," xmlns=\"http://www.w3.org/2000/svg\">");
+ fprintf (stdout,
+ "<g id=\"g0\" fill=\"#%s\" stroke=\"#%s\" stroke-width=\"1\">\n",
+ bg, fg);
+ fprintf (stdout,
+ "<rect x=\"1\" y=\"1\" width=\"%d\" height=\"%d\"\n",
+ width, height);
+ fprintf (stdout,
+ " fill=\"#%s\" stroke=\"#%s\" stroke-width=\"1\"/>\n", fill, bg);
+
+
+
+ /* Process the metacode.
+ */
+ translate (in, stdout);
+
+
+ /* Clean up.
+ */
+ fprintf (stdout, "</g></svg>"); /* output the end of file */
+ if (in != stdin)
+ fclose (in);
+
+ return (0);
+}
+
+
+/* TRANSLATE -- Interpret input SGI metacode instructions into device
+** instructions and write to stdout.
+*/
+static void
+translate (FILE *in, FILE *out)
+{
+ register struct sgi_inst *sgip;
+ struct sgi_inst inbuf[LEN_MCBUF], *buftop;
+ int n, in_stroke=0, swap_bytes = isSwapped();
+ int x, y, gnum=1;
+
+
+ /* Process the metacode:
+ */
+ while ((n = fread ((char *)inbuf, sizeof(*sgip), LEN_MCBUF, in)) > 0) {
+ if (swap_bytes)
+ bswap2 ((unsigned char *)inbuf, (unsigned char *)inbuf,
+ sizeof(*sgip) * n);
+
+ buftop = inbuf + n;
+
+ for (sgip = inbuf; sgip < buftop; sgip++) {
+ switch (sgip->opcode) {
+ case SGK_FRAME:
+ fprintf (out, "\n");
+ break;
+
+ case SGK_MOVE:
+ x = (int) (((float)sgip->x / GKI_MAXNDC) * width);
+ y = (int) (((float)sgip->y / GKI_MAXNDC) * height);
+ y = height - y + 1;
+ if (in_stroke) /* end current stroke */
+ fprintf (out, "\"/>");
+
+ /* Begin a new output stroke.
+ */
+ fprintf (out, "<polyline points=\"%d,%d", x, y);
+ in_stroke = 1;
+ break;
+
+ case SGK_DRAW:
+ x = (int) (((float)sgip->x / GKI_MAXNDC) * width);
+ y = (int) (((float)sgip->y / GKI_MAXNDC) * height);
+ y = height - y + 1;
+ fprintf (out, " %d,%d", x, y);
+ in_stroke = 1;
+ break;
+
+ case SGK_SETLW:
+ /* Set pen width.
+ */
+ pen_width = sgip->x + 1;
+ if (in_stroke) /* end current stroke */
+ fprintf (out, "\"/></g>");
+ fprintf (out, "<g id=\"g%d\" stroke-width=\"%d\">",
+ gnum++, pen_width);
+ in_stroke = 0;
+ break;
+
+ default:
+ fprintf (stderr, "sgi2svg: unrecognized sgi opcode %d\n",
+ sgip->opcode);
+ break;
+ }
+ }
+ }
+
+ /* Terminate plotting and exit.
+ */
+ fprintf (out, " \"/></g>\n");
+}
diff --git a/unix/gdev/sgidev/sgi2uapl.c b/unix/gdev/sgidev/sgi2uapl.c
new file mode 100644
index 00000000..3c59d284
--- /dev/null
+++ b/unix/gdev/sgidev/sgi2uapl.c
@@ -0,0 +1,545 @@
+/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+ */
+
+#include <stdio.h>
+#include <ctype.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <time.h>
+#include <pwd.h>
+
+#ifdef SOLARIS
+#include <sys/systeminfo.h>
+#endif
+
+#define import_spp
+#define import_error
+#include <iraf.h>
+
+#include "sgiUtil.h"
+
+
+/*
+ * SGI2UAPL.C -- Read IRAF SGI metacode from standard input, translate into
+ * Postscript for the Apple Laserwriter and write to standard output.
+ *
+ * Usage:
+ *
+ * sgi2uapl.e [-params] [sgi_metacode] [| lpr -Plw]
+ *
+ * -4 use 4 byte point encoding scheme (default is 7 byte)
+ * -t omit the timestamp/logo normally written to corner of plot
+ * -l N left edge; x plot origin in device pixels
+ * -b N bottom edge; y plot origin in device pixels
+ * -w N width of plot, device pixels starting from l
+ * -h N height of plot, device pixels starting from b
+ * -p O.S pen width `origin' and `slope'
+ *
+ * Numeric values may be appended directly to their flags or separated by a
+ * space; the input file name and the switches may occur in any order.
+ * Note that you can arrange for the Postscript output to be saved in a file
+ * as well as directed to the printer by calling the translator as
+ *
+ * sgi2uapl.e [params] | tee -a file | lpr -Plw
+ */
+
+#define OSOK 0 /* normal successful completion */
+#define LEN_MCBUF 1024 /* number of SGK instrs in buffer */
+#define SGK_FRAME 1 /* new frame instruction */
+#define SGK_MOVE 2 /* move pen */
+#define SGK_DRAW 3 /* draw pen */
+#define SGK_SETLW 4 /* set line width */
+#define SGK_MAXNDC 32767 /* SGK units */
+
+/* Device opcodes and parameters. The default edge and width parameters (DEF_)
+ * are given in Apple Laserwriter pixels, at 300 dots/inch. Although bypassing
+ * the device-independence of Postscript, this achieves greater efficiency
+ * both in translator performance and in transmission rate to the plotter.
+ * The device y-origin is at the lower left corner of the page, but we take
+ * care of this with a Postscript coordinate transformation. Thus the maximum
+ * page `width' is 11*300 pixels, `height' is 8.5*300 pixels.
+ */
+#define DEV_FRAME "showpage setcoords setjoins\n" /* newframe */
+#define DEV_SETLW "setlinewidth\n" /* linewidth */
+
+#define MAX_POINTS 512 /* maximum points on stack before a STROKE */
+#define DEF_LEFT 30 /* origin in device pixels in x */
+#define DEF_WIDTH 3180 /* width in x (300d/i, 11" paper) */
+#define DEF_BOTTOM 60 /* origin in device pixels in y */
+#define DEF_HEIGHT 2415 /* height in y (300d/i, 8.5" paper) */
+#define DEF_PENBASE 3 /* base pen width (LW 1->2) */
+#define DEF_PENSLOPE 4 /* pen width slope (LW 2->4, 3->6 etc.) */
+#define SZ_PENCMD 16 /* total no. of chars in penwidth instruction */
+#define SZ_PENVAL 2 /* no. of chars in penwidth value */
+#define SZ_VCODE 7 /* no. of chars in MOVE or DRAW opcode */
+#define SZ_VECT 17 /* total no. chars in a MOVE or DRAW inst. */
+#define SZ_COORD 4 /* no. of chars in device coordinate */
+#define XY_MOVE 0
+#define XY_DRAW 1
+
+struct sgi_inst {
+ short opcode;
+ short x;
+ short y;
+};
+
+/* Commands to setup Postscript environment.
+ */
+static char *ps_init[] = {
+ "%!PS-Adobe-2.0",
+ "/devppi 300 def",
+ "/userppi 72 def",
+ "/pagewidth 8.5 def",
+ "/devpixtouser { userppi mul devppi div } def",
+ "/pagetolandscape 90 def",
+ "/setcoords { pagewidth userppi mul 0 translate",
+ " pagetolandscape rotate 1 devpixtouser 1 devpixtouser scale } def",
+ "/setjoins { 1 setlinejoin 1 setlinecap } def",
+ "erasepage initgraphics setcoords setjoins",
+ NULL };
+
+/* 7BYTE -- Postscript procedures to move or draw, with the X,Y coordinates
+ * encoded as a 4 byte sequence (7 bytes including the command name and spaces)
+ * following the command name. This is the fastest encoding, since it
+ * minimizes the Postscript interpreter execution time.
+ *
+ * bit 76543210
+ * ------------------------------------------
+ * 0 01XXXXXX hi 6 X bits
+ * 1 01XXXXXX li 6 X bits
+ * 2 01YYYYYY hi 6 Y bits
+ * 3 01YYYYYY lo 6 Y bits
+ */
+static char *ps_7byte[] = {
+ "/getpoint {",
+ " currentfile read pop 8#77 and 6 bitshift",
+ " currentfile read pop 8#77 and or",
+ " currentfile read pop 8#77 and 6 bitshift",
+ " currentfile read pop 8#77 and or",
+ " } def",
+ "/m { getpoint moveto } def",
+ "/d { getpoint lineto } def",
+ NULL };
+
+/* 4BYTE -- Postscript procedure to draw an arbitrary series of vectors,
+ * encoded 4 bytes per point. This is the most space efficient encoding,
+ * but the runtime may be somewhat longer than for the 7byte encoding,
+ * due to the Postscript interpreter overhead.
+ *
+ * Optional Flag byte:
+ * > move instruction
+ * + draw instruction
+ * $ terminate plotting
+ * other ignored (e.g., whitespace)
+ *
+ * Point Encoding:
+ * bit 76543210
+ * ------------------------------------------
+ * 1 01XXXXXX hi 6 X bits
+ * 2 01XXXXXX lo 6 X bits
+ * 3 01YYYYYY hi 6 Y bits
+ * 4 01YYYYYY lo 6 Y bits
+ *
+ * Data points are encoded 12 bits (0-4095) per X,Y coordinate. The flag byte
+ * is used as the terminator, to toggle the move/draw state, and to permit
+ * whitespace to be ignored. A high bit is set in each byte to ensure a
+ * printable character, as control codes would interfere with the operation of
+ * the Postscript interpreter.
+ */
+#define CH_MOVE '>'
+#define CH_DRAW '+'
+#define CH_EXITPLOT '$'
+
+static char *ps_4byte[] = {
+ "/plot { /movepen { moveto } def",
+ " { currentfile read not { exit } if",
+ " { dup 8#100 ge",
+ " { exit }",
+ " { dup 8#076 eq",
+ " { pop /movepen { moveto } def",
+ " currentfile read not { exit } if }",
+ " { dup 8#053 eq",
+ " { pop /movepen { lineto } def",
+ " currentfile read not { exit } if }",
+ " { dup 8#044 eq",
+ " { exit }",
+ " { pop currentfile read not { exit } if }",
+ " ifelse }",
+ " ifelse }",
+ " ifelse }",
+ " ifelse",
+ " } loop",
+ " dup 8#044 eq { pop exit } { 8#77 and 6 bitshift } ifelse",
+ " currentfile read pop 8#77 and or",
+ " currentfile read pop 8#77 and 6 bitshift",
+ " currentfile read pop 8#77 and or",
+ " movepen",
+ " } loop",
+ " } def",
+ NULL };
+
+static int fourbyte = 0;
+static int penmode = -1;
+static int omit_logo = 0;
+static int dev_left;
+static int dev_bottom;
+static int dev_width;
+static int dev_height;
+static int dev_penbase = DEF_PENBASE;
+static int dev_penslope = DEF_PENSLOPE;
+static int npts = 0;
+
+
+static void translate (FILE *in, FILE *out);
+static char *make_label (void);
+static void textout (FILE *out, char *text[]);
+static char *penencode (int val, char *code);
+static void xy_flush (FILE *out);
+static void xy_point (FILE *out, register int x, register int y, int flag);
+
+
+
+/* MAIN -- Main entry point for SGI2UAPL. Optional arguments are device
+ * window parameters and name of input file.
+ */
+int
+main (int argc, char *argv[])
+{
+ FILE *in;
+ char *infile;
+ char *argp;
+ int argno;
+ int np;
+ char penparam[SZ_PENCMD];
+
+
+ infile = "stdin";
+
+ /* Process the command line.
+ */
+ for (argno=1; (argp = argv[argno]) != NULL; argno++) {
+ if (argp[0] == '-') {
+ /* A window-control or pen width switch.
+ */
+ switch (argp[1]) {
+ case '4':
+ fourbyte++;
+ break;
+ case 't':
+ omit_logo++;
+ break;
+ case 'l':
+ dev_left = get_iarg (argp[2], argv, argno, DEF_LEFT);
+ break;
+ case 'b':
+ dev_bottom = get_iarg (argp[2], argv, argno, DEF_BOTTOM);
+ break;
+ case 'w':
+ dev_width = get_iarg (argp[2], argv, argno, DEF_WIDTH);
+ break;
+ case 'h':
+ dev_height = get_iarg (argp[2], argv, argno, DEF_HEIGHT);
+ break;
+ case 'p':
+ if (argp[2] == (char) 0)
+ if (argv[argno+1] == NULL) {
+ fprintf (stderr, "missing arg to switch `%s';",
+ argp);
+ fprintf (stderr, " reset to %d.%d\n", dev_penbase,
+ dev_penslope);
+ } else
+ strcpy (penparam, argv[++argno]);
+ else
+ strcpy (penparam, argv[argno]+2);
+
+ np = sscanf (penparam, "%d . %d", &dev_penbase,
+ &dev_penslope);
+ if (np == 1) {
+ dev_penslope = dev_penbase;
+ } else if (np < 1) {
+ dev_penbase = DEF_PENBASE;
+ dev_penslope = DEF_PENSLOPE;
+ }
+
+ break;
+ default:
+ fprintf (stderr, "sgi2uapl: unknown switch '%s'\n", argp);
+ }
+
+ } else {
+ /* Input sgi-metacode file specification.
+ */
+ infile = argp;
+ }
+ }
+
+ if (strcmp (infile, "stdin") == 0)
+ in = stdin;
+ else
+ in = fopen (infile, "r");
+
+ if (in == NULL) {
+ fprintf (stderr, "Fatal error (sgi2uapl): Cannot open `%s'\n",
+ infile);
+ fflush (stderr);
+ exit (OSOK+1);
+ }
+
+ /* Process the metacode.
+ */
+ translate (in, stdout);
+
+ if (in != stdin)
+ fclose (in);
+
+ return (0);
+}
+
+
+/* TRANSLATE -- Interpret input SGI metacode instructions into device
+ * instructions and write to stdout.
+ */
+static void
+translate (FILE *in, FILE *out)
+{
+ register struct sgi_inst *sgip;
+ struct sgi_inst inbuf[LEN_MCBUF], *buftop;
+ int n, x, y, curpoints = 0, swap_bytes;
+ float xscale, yscale;
+
+
+ swap_bytes = isSwapped();
+
+ xscale = (float) dev_width / (float) SGK_MAXNDC;
+ yscale = (float) dev_height / (float) SGK_MAXNDC;
+
+ /* Output device initialization. */
+ textout (out, ps_init);
+
+ /* Define the Postscript plotting procedures. */
+ if (fourbyte)
+ textout (out, ps_4byte);
+ else
+ textout (out, ps_7byte);
+
+ /* Initialize pen width. */
+ fwrite (penencode (dev_penbase, DEV_SETLW), SZ_PENCMD, 1, out);
+
+ /* Process the metacode:
+ */
+ while ((n = fread ((char *)inbuf, sizeof(*sgip), LEN_MCBUF, in)) > 0) {
+ if (swap_bytes)
+ bswap2 ((unsigned char *)inbuf, (unsigned char *)inbuf,
+ sizeof(*sgip) * n);
+
+ buftop = inbuf + n;
+
+ for (sgip = inbuf; sgip < buftop; sgip++) {
+ switch (sgip->opcode) {
+ case SGK_FRAME:
+ xy_flush (out);
+ fprintf (out, DEV_FRAME);
+ break;
+
+ case SGK_MOVE:
+ x = dev_left + sgip->x * xscale;
+ y = dev_bottom + sgip->y * yscale;
+ xy_point (out, x, y, XY_MOVE);
+ break;
+
+ case SGK_DRAW:
+ x = dev_left + sgip->x * xscale;
+ y = dev_bottom + sgip->y * yscale;
+ xy_point (out, x, y, XY_DRAW);
+
+ /* Limit number of points passed to Postscript between
+ * 'stroke' commands to draw the buffered points.
+ */
+ curpoints = curpoints + 1;
+ if (curpoints > MAX_POINTS) {
+ xy_flush (out);
+ xy_point (out, x, y, XY_MOVE);
+ curpoints = 0;
+ }
+ break;
+
+ case SGK_SETLW: {
+ /* Set pen width.
+ */
+ int x = max (0, sgip->x - 1);
+
+ xy_flush (out);
+ curpoints = 0;
+ fwrite (penencode (
+ max (1, dev_penbase + x * dev_penslope), DEV_SETLW),
+ SZ_PENCMD, 1, out);
+ }
+ break;
+
+ default:
+ fprintf (stderr, "sgi2uapl: unrecognized sgi opcode %d\n",
+ sgip->opcode);
+ break;
+ }
+ }
+ }
+
+ /* Terminate plotting and exit.
+ */
+ xy_flush (out);
+
+ /* Add the NOAO logo and timestamp at the bottom of the page and
+ * output the page.
+ */
+ if (!omit_logo) {
+ fprintf (out, "/Times-Roman findfont 24 scalefont setfont\n");
+
+ /* fprintf (out, "[-1 0 0 -1 2350 3180] setmatrix\n"); */
+ fprintf (out, "initmatrix\n");
+ fprintf (out, "-1 72 mul 300 div 1 72 mul 300 div scale\n");
+ fprintf (out, "-2409 88 translate\n");
+
+ fprintf (out, "%d %d moveto\n", 1600, 3150);
+ fprintf (out, "[1 0 0 -1 0 0] concat\n");
+ fprintf (out, "(%s) show\n", make_label());
+ }
+
+ fprintf (out, "showpage\n");
+}
+
+
+/* XY_POINT -- Output a move or draw instruction, using either the 4 byte or
+ * 7 byte encoding scheme.
+ */
+static void
+xy_point (
+ FILE *out, /* output file */
+ register int x, /* coords to move to */
+ register int y, /* coords to move to */
+ int flag /* move or draw? */
+)
+{
+ static char o[] = "m XXXX";
+ register char *op = o;
+ register int n;
+
+ if (fourbyte) {
+ if (npts == 0) {
+ fputs ("plot\n", out);
+ penmode = XY_MOVE;
+ }
+
+ if (flag != penmode)
+ *op++ = ((penmode = flag) == XY_MOVE) ? CH_MOVE : CH_DRAW;
+
+ *op++ = ((n = ((x >> 6) & 077)) == 077) ? n : (0100 | n);
+ *op++ = ((n = (x & 077)) == 077) ? n : (0100 | n);
+ *op++ = ((n = ((y >> 6) & 077)) == 077) ? n : (0100 | n);
+ *op++ = ((n = (y & 077)) == 077) ? n : (0100 | n);
+
+ fwrite (o, op-o, 1, out);
+ if (!(++npts % 15))
+ fputc ('\n', out);
+
+ } else {
+ o[0] = (flag == XY_MOVE) ? 'm' : 'd';
+ o[2] = ((n = ((x >> 6) & 077)) == 077) ? n : (0100 | n);
+ o[3] = ((n = (x & 077)) == 077) ? n : (0100 | n);
+ o[4] = ((n = ((y >> 6) & 077)) == 077) ? n : (0100 | n);
+ o[5] = ((n = (y & 077)) == 077) ? n : (0100 | n);
+
+ fwrite (o, 6, 1, out);
+ if (!(++npts % 10))
+ fputc ('\n', out);
+ else
+ fputc (' ', out);
+ }
+}
+
+
+/* XY_FLUSH -- Terminate the current drawing sequence, if any, and issue the
+ * stroke command to Postscript to draw the buffered points.
+ */
+static void
+xy_flush (FILE *out)
+{
+ if (npts > 0) {
+ if (fourbyte)
+ fputs ("$\n", out);
+ else if (npts % 10)
+ fputc ('\n', out);
+ fputs ("stroke\n", out);
+ npts = 0;
+ }
+}
+
+
+/* PENENCODE -- Encode base, slope into a character string formatted for the
+ * device set-pen command.
+ */
+static char *
+penencode (
+ int val, /* device line width */
+ char *code /* device set-linewidth command */
+)
+{
+ static char obuf[SZ_PENCMD+1];
+ register int digit, n;
+ register char *op, *ip;
+
+ for (op = &obuf[SZ_PENVAL-1], digit = SZ_PENVAL, n=val; --digit >= 0;
+ n = n / 10)
+ *op-- = n % 10 + '0';
+ obuf[SZ_PENVAL] = ' ';
+ for (op = &obuf[SZ_PENVAL+1], ip = code, n = SZ_PENCMD; --n >= 0; )
+ *op++ = *ip++;
+
+ return (obuf);
+}
+
+
+/* TEXTOUT -- Output lines of text to a file.
+ */
+static void
+textout (
+ FILE *out, /* output file */
+ char *text[] /* array of lines of text */
+)
+{
+ register char **lp;
+
+ for (lp=text; *lp; lp++) {
+ fputs (*lp, out);
+ fputc ('\n', out);
+ }
+}
+
+
+/* MAKE_LABEL -- Generate the label for the output printer page.
+ */
+static char *
+make_label (void)
+{
+ static char buf[128];
+ char hostname[32];
+ char username[32];
+ struct passwd *pw;
+ time_t clock;
+
+#ifdef SOLARIS
+ sysinfo (SI_HOSTNAME, hostname, 32);
+#else
+ gethostname (hostname, 32);
+#endif
+
+ clock = time(0);
+ pw = getpwuid (getuid());
+ strcpy (username, pw->pw_name);
+ endpwent();
+
+ sprintf (buf, "NOAO/IRAF %s@%s %s",
+ username, hostname, asctime(localtime(&clock)));
+
+ return (buf);
+}
diff --git a/unix/gdev/sgidev/sgi2ueps.c b/unix/gdev/sgidev/sgi2ueps.c
new file mode 100644
index 00000000..345eb702
--- /dev/null
+++ b/unix/gdev/sgidev/sgi2ueps.c
@@ -0,0 +1,530 @@
+/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+ */
+
+#include <stdio.h>
+#include <ctype.h>
+#include <time.h>
+#include <pwd.h>
+#include <string.h>
+#include <stdlib.h>
+
+#define import_spp
+#define import_error
+#include <iraf.h>
+
+#include "sgiUtil.h"
+
+
+/*
+ * SGI2UEPS.C -- Read IRAF SGI metacode from standard input, translate into
+ * Encapsulated Postscript and write to standard output.
+ *
+ * Usage:
+ *
+ * sgi2ueps.e [-params] [sgi_metacode] [| lpr -Plw]
+ *
+ * -4 use 4 byte point encoding scheme (default is 7 byte)
+ * -l N left edge; x plot origin in device pixels
+ * -b N bottom edge; y plot origin in device pixels
+ * -w N width of plot, device pixels starting from l
+ * -h N height of plot, device pixels starting from b
+ * -p O.S pen width `origin' and `slope'
+ *
+ * Numeric values may be appended directly to their flags or separated by a
+ * space; the input file name and the switches may occur in any order.
+ * Note that you can arrange for the Postscript output to be saved in a file
+ * as well as directed to the printer by calling the translator as
+ *
+ * sgi2ueps.e [params] | tee -a file | lpr -Plw
+ */
+
+#define OSOK 0 /* normal successful completion */
+#define LEN_MCBUF 1024 /* number of SGK instrs in buffer */
+#define SGK_FRAME 1 /* new frame instruction */
+#define SGK_MOVE 2 /* move pen */
+#define SGK_DRAW 3 /* draw pen */
+#define SGK_SETLW 4 /* set line width */
+#define SGK_MAXNDC 32767 /* SGK units */
+
+/* Device opcodes and parameters. The default edge and width parameters (DEF_)
+ * are given in pixels at 300 dots/inch. Although bypassing the
+ * device-independence of Postscript, this achieves greater efficiency
+ * both in translator performance and in transmission rate to the plotter.
+ * The device y-origin is at the lower left corner of the page, but we take
+ * care of this with a Postscript coordinate transformation. Thus the maximum
+ * page `width' is 11*300 pixels, `height' is 8.5*300 pixels.
+ */
+#define DEV_FRAME "showpage setcoords setjoins\n" /* newframe */
+#define DEV_SETLW "setlinewidth\n" /* linewidth */
+
+#define MAX_POINTS 512 /* maximum points on stack before a STROKE */
+#define DEF_LEFT 30 /* origin in device pixels in x */
+#define DEF_WIDTH 3180 /* width in x (300d/i, 11" paper) */
+#define DEF_BOTTOM 60 /* origin in device pixels in y */
+#define DEF_HEIGHT 2415 /* height in y (300d/i, 8.5" paper) */
+#define DEV_UNITS 300 /* EPS translator units: N per inch */
+#define EPS_UNITS 72 /* PostScript units (points) */
+#define DEF_PENBASE 3 /* base pen width (LW 1->2) */
+#define DEF_PENSLOPE 4 /* pen width slope (LW 2->4, 3->6 etc.) */
+#define SZ_PENCMD 16 /* total no. of chars in penwidth instruction */
+#define SZ_PENVAL 2 /* no. of chars in penwidth value */
+#define SZ_VCODE 7 /* no. of chars in MOVE or DRAW opcode */
+#define SZ_VECT 17 /* total no. chars in a MOVE or DRAW inst. */
+#define SZ_COORD 4 /* no. of chars in device coordinate */
+#define XY_MOVE 0
+#define XY_DRAW 1
+
+struct sgi_inst {
+ short opcode;
+ short x;
+ short y;
+};
+
+/* Commands to setup Postscript environment.
+ */
+static char *ps_init[] = {
+ "/devppi 300 def",
+ "/userppi 72 def",
+ "/pagewidth 8.5 def",
+ "/devpixtouser { userppi mul devppi div } def",
+ "/setscale { 1 devpixtouser 1 devpixtouser scale } def",
+ "/pagetolandscape 90 def",
+ "/setcoords { pagewidth userppi mul 0 translate",
+ " pagetolandscape rotate setscale } def",
+ "/setjoins { 1 setlinejoin 1 setlinecap } def",
+ NULL };
+
+static char *ps_endprolog[] = {
+ "%%EndProlog",
+ "%%Page: 1 1",
+ "gsave setscale setjoins",
+ NULL };
+
+/* 7BYTE -- Postscript procedures to move or draw, with the X,Y coordinates
+ * encoded as a 4 byte sequence (7 bytes including the command name and spaces)
+ * following the command name. This is the fastest encoding, since it
+ * minimizes the Postscript interpreter execution time.
+ *
+ * bit 76543210
+ * ------------------------------------------
+ * 0 01XXXXXX hi 6 X bits
+ * 1 01XXXXXX li 6 X bits
+ * 2 01YYYYYY hi 6 Y bits
+ * 3 01YYYYYY lo 6 Y bits
+ */
+static char *ps_7byte[] = {
+ "/getpoint {",
+ " currentfile read pop 8#77 and 6 bitshift",
+ " currentfile read pop 8#77 and or",
+ " currentfile read pop 8#77 and 6 bitshift",
+ " currentfile read pop 8#77 and or",
+ " } def",
+ "/m { getpoint moveto } def",
+ "/d { getpoint lineto } def",
+ NULL };
+
+/* 4BYTE -- Postscript procedure to draw an arbitrary series of vectors,
+ * encoded 4 bytes per point. This is the most space efficient encoding,
+ * but the runtime may be somewhat longer than for the 7byte encoding,
+ * due to the Postscript interpreter overhead.
+ *
+ * Optional Flag byte:
+ * > move instruction
+ * + draw instruction
+ * $ terminate plotting
+ * other ignored (e.g., whitespace)
+ *
+ * Point Encoding:
+ * bit 76543210
+ * ------------------------------------------
+ * 1 01XXXXXX hi 6 X bits
+ * 2 01XXXXXX lo 6 X bits
+ * 3 01YYYYYY hi 6 Y bits
+ * 4 01YYYYYY lo 6 Y bits
+ *
+ * Data points are encoded 12 bits (0-4095) per X,Y coordinate. The flag byte
+ * is used as the terminator, to toggle the move/draw state, and to permit
+ * whitespace to be ignored. A high bit is set in each byte to ensure a
+ * printable character, as control codes would interfere with the operation of
+ * the Postscript interpreter.
+ */
+#define CH_MOVE '>'
+#define CH_DRAW '+'
+#define CH_EXITPLOT '$'
+
+static char *ps_4byte[] = {
+ "/plot { /movepen { moveto } def",
+ " { currentfile read not { exit } if",
+ " { dup 8#100 ge",
+ " { exit }",
+ " { dup 8#076 eq",
+ " { pop /movepen { moveto } def",
+ " currentfile read not { exit } if }",
+ " { dup 8#053 eq",
+ " { pop /movepen { lineto } def",
+ " currentfile read not { exit } if }",
+ " { dup 8#044 eq",
+ " { exit }",
+ " { pop currentfile read not { exit } if }",
+ " ifelse }",
+ " ifelse }",
+ " ifelse }",
+ " ifelse",
+ " } loop",
+ " dup 8#044 eq { pop exit } { 8#77 and 6 bitshift } ifelse",
+ " currentfile read pop 8#77 and or",
+ " currentfile read pop 8#77 and 6 bitshift",
+ " currentfile read pop 8#77 and or",
+ " movepen",
+ " } loop",
+ " } def",
+ NULL };
+
+static int npts = 0;
+static int fourbyte = 0;
+static int penmode = -1;
+static int dev_left;
+static int dev_bottom;
+static int dev_width;
+static int dev_height;
+static int dev_penbase = DEF_PENBASE;
+static int dev_penslope = DEF_PENSLOPE;
+static char progname[SZ_LINE+1];
+
+static void translate (FILE *in, FILE *out);
+static void xy_point (FILE *out, register int x, register int y, int flag);
+static void xy_flush (FILE *out);
+static char *penencode (int val, char *code);
+static void textout (FILE *out, char *text[]);
+static void eps_comments (FILE *out);
+
+
+
+/* MAIN -- Main entry point for SGI2UAPL. Optional arguments are device
+ * window parameters and name of input file.
+ */
+int
+main (int argc, char *argv[])
+{
+ FILE *in;
+ char *infile;
+ char *argp;
+ int argno;
+ int np;
+ char penparam[SZ_PENCMD];
+
+
+ strcpy (progname, argv[0]);
+ infile = "stdin";
+
+ /* Process the command line.
+ */
+ for (argno=1; (argp = argv[argno]) != NULL; argno++) {
+ if (argp[0] == '-') {
+ /* A window-control or pen width switch.
+ */
+ switch (argp[1]) {
+ case '4':
+ fourbyte++;
+ break;
+ case 'l':
+ dev_left = get_iarg (argp[2], argv, argno, DEF_LEFT);
+ break;
+ case 'b':
+ dev_bottom = get_iarg (argp[2], argv, argno, DEF_BOTTOM);
+ break;
+ case 'w':
+ dev_width = get_iarg (argp[2], argv, argno, DEF_WIDTH);
+ break;
+ case 'h':
+ dev_height = get_iarg (argp[2], argv, argno, DEF_HEIGHT);
+ break;
+ case 'p':
+ if (argp[2] == (char) 0)
+ if (argv[argno+1] == NULL) {
+ fprintf (stderr, "missing arg to switch `%s';",
+ argp);
+ fprintf (stderr, " reset to %d.%d\n", dev_penbase,
+ dev_penslope);
+ } else
+ strcpy (penparam, argv[++argno]);
+ else
+ strcpy (penparam, argv[argno]+2);
+
+ np = sscanf (penparam, "%d . %d", &dev_penbase,
+ &dev_penslope);
+ if (np == 1) {
+ dev_penslope = dev_penbase;
+ } else if (np < 1) {
+ dev_penbase = DEF_PENBASE;
+ dev_penslope = DEF_PENSLOPE;
+ }
+
+ break;
+ default:
+ fprintf (stderr, "sgi2ueps: unknown switch '%s'\n", argp);
+ }
+
+ } else {
+ /* Input sgi-metacode file specification.
+ */
+ infile = argp;
+ }
+ }
+
+ if (strcmp (infile, "stdin") == 0)
+ in = stdin;
+ else
+ in = fopen (infile, "r");
+
+ if (in == NULL) {
+ fprintf (stderr, "Fatal error (sgi2ueps): Cannot open `%s'\n",
+ infile);
+ fflush (stderr);
+ exit (OSOK+1);
+ }
+
+ /* Process the metacode.
+ */
+ translate (in, stdout);
+
+ if (in != stdin)
+ fclose (in);
+
+ return (0);
+}
+
+
+/* TRANSLATE -- Interpret input SGI metacode instructions into device
+ * instructions and write to stdout.
+ */
+static void
+translate (FILE *in, FILE *out)
+{
+ register struct sgi_inst *sgip;
+ struct sgi_inst inbuf[LEN_MCBUF], *buftop;
+ int n, x, y, curpoints = 0, swap_bytes;
+ float xscale, yscale;
+
+
+ swap_bytes = isSwapped();
+
+ xscale = (float) dev_width / (float) SGK_MAXNDC;
+ yscale = (float) dev_height / (float) SGK_MAXNDC;
+
+ /* Output device initialization. */
+ eps_comments (out);
+ textout (out, ps_init);
+
+ /* Define the Postscript plotting procedures. */
+ if (fourbyte)
+ textout (out, ps_4byte);
+ else
+ textout (out, ps_7byte);
+
+ textout (out, ps_endprolog);
+
+ /* Initialize pen width. */
+ fwrite (penencode (dev_penbase, DEV_SETLW), SZ_PENCMD, 1, out);
+
+ /* Process the metacode:
+ */
+ while ((n = fread ((char *)inbuf, sizeof(*sgip), LEN_MCBUF, in)) > 0) {
+ if (swap_bytes)
+ bswap2 ((unsigned char *)inbuf, (unsigned char *)inbuf,
+ sizeof(*sgip) * n);
+
+ buftop = inbuf + n;
+
+ for (sgip = inbuf; sgip < buftop; sgip++) {
+ switch (sgip->opcode) {
+ case SGK_FRAME:
+ xy_flush (out);
+ fprintf (out, DEV_FRAME);
+ break;
+
+ case SGK_MOVE:
+ x = dev_left + sgip->x * xscale;
+ y = dev_bottom + sgip->y * yscale;
+ xy_point (out, x, y, XY_MOVE);
+ break;
+
+ case SGK_DRAW:
+ x = dev_left + sgip->x * xscale;
+ y = dev_bottom + sgip->y * yscale;
+ xy_point (out, x, y, XY_DRAW);
+
+ /* Limit number of points passed to Postscript between
+ * 'stroke' commands to draw the buffered points.
+ */
+ curpoints = curpoints + 1;
+ if (curpoints > MAX_POINTS) {
+ xy_flush (out);
+ xy_point (out, x, y, XY_MOVE);
+ curpoints = 0;
+ }
+ break;
+
+ case SGK_SETLW: {
+ /* Set pen width.
+ */
+ int x = max (0, sgip->x - 1);
+
+ xy_flush (out);
+ curpoints = 0;
+ fwrite (penencode (
+ max (1, dev_penbase + x * dev_penslope), DEV_SETLW),
+ SZ_PENCMD, 1, out);
+ }
+ break;
+
+ default:
+ fprintf (stderr, "sgi2ueps: unrecognized sgi opcode %d\n",
+ sgip->opcode);
+ break;
+ }
+ }
+ }
+
+ /* Terminate plotting and exit.
+ */
+ xy_flush (out);
+
+ fprintf (out, "grestore showpage\n");
+}
+
+
+/* XY_POINT -- Output a move or draw instruction, using either the 4 byte or
+ * 7 byte encoding scheme.
+ */
+static void
+xy_point (
+ FILE *out, /* output file */
+ register int x, /* coords to move to */
+ register int y, /* coords to move to */
+ int flag /* move or draw? */
+)
+{
+ static char o[] = "m XXXX";
+ register char *op = o;
+ register int n;
+
+ if (fourbyte) {
+ if (npts == 0) {
+ fputs ("plot\n", out);
+ penmode = XY_MOVE;
+ }
+
+ if (flag != penmode)
+ *op++ = ((penmode = flag) == XY_MOVE) ? CH_MOVE : CH_DRAW;
+
+ *op++ = ((n = ((x >> 6) & 077)) == 077) ? n : (0100 | n);
+ *op++ = ((n = (x & 077)) == 077) ? n : (0100 | n);
+ *op++ = ((n = ((y >> 6) & 077)) == 077) ? n : (0100 | n);
+ *op++ = ((n = (y & 077)) == 077) ? n : (0100 | n);
+
+ fwrite (o, op-o, 1, out);
+ if (!(++npts % 15))
+ fputc ('\n', out);
+
+ } else {
+ o[0] = (flag == XY_MOVE) ? 'm' : 'd';
+ o[2] = ((n = ((x >> 6) & 077)) == 077) ? n : (0100 | n);
+ o[3] = ((n = (x & 077)) == 077) ? n : (0100 | n);
+ o[4] = ((n = ((y >> 6) & 077)) == 077) ? n : (0100 | n);
+ o[5] = ((n = (y & 077)) == 077) ? n : (0100 | n);
+
+ fwrite (o, 6, 1, out);
+ if (!(++npts % 10))
+ fputc ('\n', out);
+ else
+ fputc (' ', out);
+ }
+}
+
+
+/* XY_FLUSH -- Terminate the current drawing sequence, if any, and issue the
+ * stroke command to Postscript to draw the buffered points.
+ */
+static void
+xy_flush (FILE *out)
+{
+ if (npts > 0) {
+ if (fourbyte)
+ fputs ("$\n", out);
+ else if (npts % 10)
+ fputc ('\n', out);
+ fputs ("stroke\n", out);
+ npts = 0;
+ }
+}
+
+
+/* PENENCODE -- Encode base, slope into a character string formatted for the
+ * device set-pen command.
+ */
+static char *
+penencode (
+ int val, /* device line width */
+ char *code /* device set-linewidth command */
+)
+{
+ static char obuf[SZ_PENCMD+1];
+ register int digit, n;
+ register char *op, *ip;
+
+ for (op = &obuf[SZ_PENVAL-1], digit = SZ_PENVAL, n=val; --digit >= 0;
+ n = n / 10)
+ *op-- = n % 10 + '0';
+ obuf[SZ_PENVAL] = ' ';
+ for (op = &obuf[SZ_PENVAL+1], ip = code, n = SZ_PENCMD; --n >= 0; )
+ *op++ = *ip++;
+
+ return (obuf);
+}
+
+
+/* TEXTOUT -- Output lines of text to a file.
+ */
+static void
+textout (
+ FILE *out, /* output file */
+ char *text[] /* array of lines of text */
+)
+{
+ register char **lp;
+
+ for (lp=text; *lp; lp++) {
+ fputs (*lp, out);
+ fputc ('\n', out);
+ }
+}
+
+
+/* EPS_COMMENTS -- Set identifying comments for EPS conformance.
+ */
+static void
+eps_comments (FILE *out)
+{
+ time_t clock;
+ int llx, lly, urx, ury;
+
+ clock = time(0);
+
+ fprintf (out, "%%!PS-Adobe-3.0 EPSF-3.0\n");
+ fprintf (out, "%%%%Title: IRAF SGI plot\n");
+ fprintf (out, "%%%%Creator: %s\n", progname);
+ fprintf (out, "%%%%CreationDate: %s", asctime(localtime(&clock)));
+
+ /* Compute bounding box in PostScript coordinates. */
+ llx = ((float) dev_left / (float) DEV_UNITS) * (float) EPS_UNITS;
+ lly = ((float) dev_bottom / (float) DEV_UNITS) * (float) EPS_UNITS;
+ urx = ((float) (dev_left + dev_width) / (float) DEV_UNITS)
+ * (float) EPS_UNITS;
+ ury = ((float) (dev_bottom + dev_height) / (float) DEV_UNITS)
+ * (float) EPS_UNITS;
+
+ fprintf (out, "%%%%BoundingBox: %d %d %d %d\n", llx, lly, urx, ury);
+ fprintf (out, "%%%%Pages: 1\n");
+ fprintf (out, "%%%%EndComments\n");
+}
diff --git a/unix/gdev/sgidev/sgi2uhpgl.c b/unix/gdev/sgidev/sgi2uhpgl.c
new file mode 100644
index 00000000..2e952446
--- /dev/null
+++ b/unix/gdev/sgidev/sgi2uhpgl.c
@@ -0,0 +1,160 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+
+#define import_spp
+#define import_error
+#include <iraf.h>
+
+#include "sgiUtil.h"
+
+
+/*
+ * SGI2UHPGL.C -- Read IRAF SGI metacode from standard input, translate into
+ * HP graphics language call for HP 7550A plotter
+ *
+ * Usage
+ * sgi2uhpgl.e [sgi_metacode] [| lpr -Papple]
+ *
+ */
+
+#define OSOK 0 /* normal successful completion */
+#define LEN_MCBUF 1024 /* number of SGK instrs in buffer */
+#define SGK_FRAME 1 /* new frame instruction */
+#define SGK_MOVE 2 /* move pen */
+#define SGK_DRAW 3 /* draw pen */
+#define SGK_SETLW 4 /* set line width */
+#define GKI_MAXNDC 32767 /* SGK units */
+
+/* Device opcodes and parameters.
+ */
+#define DEV_INIT "IN;DF;SP1;" /* initialize */
+#define DEV_END "SP0;PG:" /* terminate */
+#define DEV_FRAME "PG;" /* newframe */
+#define DEV_MOVE "PU" /* move */
+#define DEV_DRAW "PD" /* draw */
+#define PRES 1016 /* plotter resolution per inch */
+#define XLEN_INCHES 10.0 /* width of plot (x) in inches */
+#define YLEN_INCHES 8.0 /* height of plot (y) in inches */
+#define XSCALE PRES * XLEN_INCHES / GKI_MAXNDC
+#define YSCALE PRES * YLEN_INCHES / GKI_MAXNDC
+
+
+#define SZ_COORD 4 /* no. of chars in device coordinate */
+
+struct sgi_inst {
+ short opcode;
+ short x;
+ short y;
+};
+
+static void translate (FILE *in, FILE *out);
+
+
+/* MAIN -- Main entry point for SGI2UHPGL. Optional arguments are device
+ * window parameters and name of input file.
+ */
+int
+main (int argc, char *argv[])
+{
+ FILE *in;
+ char *infile;
+
+
+ infile = "stdin";
+
+ /* Process the command line.
+ */
+ infile = argv[1];
+
+ if (strcmp (infile, "stdin") == 0)
+ in = stdin;
+ else
+ in = fopen (infile, "r");
+
+ if (in == NULL) {
+ fprintf (stderr, "Fatal error (sgi2uhpp): Cannot open `%s'\n",
+ infile);
+ fflush (stderr);
+ exit (OSOK+1);
+ }
+
+ /* Process the metacode.
+ */
+ translate (in, stdout);
+
+ if (in != stdin)
+ fclose (in);
+
+ return (0);
+}
+
+
+/* TRANSLATE -- Interpret input SGI metacode instructions into device
+ * instructions and write to stdout.
+ */
+static void
+translate (FILE *in, FILE *out)
+{
+ register struct sgi_inst *sgip;
+ struct sgi_inst inbuf[LEN_MCBUF], *buftop;
+ int n, swap_bytes;
+ float x, y;
+
+
+ swap_bytes = isSwapped();
+
+ /* Output device initialization.
+ */
+ fprintf (out, "%s\n", DEV_INIT);
+
+ /* Initialize pen width. Not implemented.
+ */
+
+ /* Process the metacode:
+ */
+ while ((n = fread ((char *)inbuf, sizeof(*sgip), LEN_MCBUF, in)) > 0) {
+ if (swap_bytes)
+ bswap2 ((unsigned char *)inbuf, (unsigned char *)inbuf,
+ sizeof(*sgip) * n);
+
+ buftop = inbuf + n;
+
+ for (sgip = inbuf; sgip < buftop; sgip++) {
+ switch (sgip->opcode) {
+ case SGK_FRAME:
+ fprintf (out, "%s\n", DEV_FRAME);
+ break;
+
+ case SGK_MOVE:
+ x = sgip->x * XSCALE;
+ y = sgip->y * YSCALE;
+ fprintf (out,
+ "%s%06.0f%s%06.0f%s\n", DEV_MOVE, x, ",", y, ";");
+ break;
+
+ case SGK_DRAW:
+ x = sgip->x * XSCALE;
+ y = sgip->y * YSCALE;
+ fprintf (out,
+ "%s%06.0f%s%06.0f%s\n", DEV_DRAW, x, ",", y, ";");
+ break;
+
+ case SGK_SETLW:
+ /* Set pen width.
+ */
+ break;
+ default:
+ fprintf (stderr, "sgi2uhpp: unrecognized sgi opcode %d\n",
+ sgip->opcode);
+ break;
+ }
+ }
+ }
+
+ /* Terminate plotting and exit.
+ */
+ fwrite (DEV_END, strlen(DEV_END), 1, out);
+ fprintf (out, "\n");
+}
diff --git a/unix/gdev/sgidev/sgi2uhplj.c b/unix/gdev/sgidev/sgi2uhplj.c
new file mode 100644
index 00000000..7c8956ce
--- /dev/null
+++ b/unix/gdev/sgidev/sgi2uhplj.c
@@ -0,0 +1,223 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+
+#define import_spp
+#define import_error
+#include <iraf.h>
+
+#include "sgiUtil.h"
+
+
+/*
+ * SGI2UHPLJ.C -- Read IRAF SGI rasterfile from standard input, translate into
+ * the Hewlett Packard Printer Command Language (HP Laserjet Series) and
+ * write to standard output.
+ *
+ * Warning
+ * The output of this is for 150 dpi. At this resolution it will take
+ * some 200 seconds to plot an simple "prow".
+ *
+ * Usage
+ * sgi2uhplj.e [-params] [sgi_] [| lpr -Phpraw]
+ *
+ * -l N left edge; x plot origin in device pixels def DEF_LEFT
+ * -b N bottom edge; y plot origin in device pixels def DEF_BOTTOM
+ * -w N width of plot, device pixels starting from l def DEF_WIDTH
+ * -h N height of plot, device pixels starting from b def DEF_HEIGHT
+ *
+ * Numeric values may be appended directly to their flags or separated by a
+ * space; the input file name and the switches may occur in any order.
+ */
+
+#define OSOK 0 /* normal successful completion */
+#define NBITS_CHAR 8 /* number of bits in a char */
+
+/* Device opcodes and parameters. The default edge and width parameters (DEF_)
+ * are given in HP pixels, at 150 dots/inch. The HP plots in portrait mode
+ * by default so RO must be set in GRAPHCAP. Thus the maximum page `width' is
+ * 11*150pixels, `height' is 8.5*150 pixels.
+ */
+
+#define DEV_INIT "\033*t150R\033*r1A" /* Enter graph. */
+#define DEV_END "\033*rB\014" /* Exit graph. */
+#define DEV_VECT "\033*p%03dX\033*p%03dY"/* x,y cursor posn in dots */
+#define DEV_RAST "\033*b%03dW" /* transfer raster graphics */
+
+#define DEF_LEFT 15 /* origin in device pixels in x */
+#define DEF_WIDTH 1216 /* width in x (150d/i, 8.5" paper) */
+#define DEF_BOTTOM 30 /* origin in device pixels in y */
+#define DEF_HEIGHT 1590 /* height in y (150d/i, 11" paper) */
+
+#define SZ_VECT 14 /* total chars in cursor position command */
+#define SZ_RAST 7 /* total chars in transfer graphics command */
+
+/* graphcap entry for uhplj and sgi_hplaserjet. one problem with current
+ * entry is that graph comes out slightly to the right of center on the page
+ * The printer used, "hpraw", is site dependent.
+ *
+ * uhplj|UNIX generic interface to Hewlett-Packard LaserJet II:\
+ * :BF:WS:XO#0:YO#0:LO#2:LS#2:\
+ * :DD=plnode!hpii,tmp$sgk,!{ sgidispatch sgi2uhpii $F \
+ * -l$(XO) -b$(YO) -w$(PX) -h$(PY) $F | lpr -Phpraw; rm $F; }&:\
+ * :tc=sgi_hplaserjet:
+ *
+ * sgi_hplaserjet|Hewlett Packard LaserJet Plus at 150 dpi:\
+ * :kf=bin$x_sgikern.e:tn=sgikern:cw#.0125:ch#.0294:\
+ * :ar#1.325:xs#.2032:ys#.2692:xr#1200:yr#1590:\
+ * :XO#8:YO#0:XW#1200:YW#1590:PX#1216:PY#1590:LO#1:LS#0:\
+ * :BI:MF#8:RO:NB#8:
+ */
+
+int dev_left;
+int dev_bottom;
+int dev_width;
+int dev_height;
+
+static void translate (FILE *in, FILE *out);
+static char *xyencode (int x, int y);
+
+
+/* MAIN -- Main entry point for SGI2UHPII. Optional arguments are device
+ * window parameters and name of input file.
+ */
+int
+main (int argc, char *argv[])
+{
+ FILE *in;
+ char *infile;
+ char *argp;
+ int argno;
+
+
+ infile = "stdin";
+
+ /* Process the command line.
+ */
+ for (argno=1; (argp = argv[argno]) != NULL; argno++) {
+ if (argp[0] == '-') {
+ /* A window-control or pen width switch.
+ */
+ switch (argp[1]) {
+ case 'l':
+ dev_left = get_iarg (argp[2], argv, argno, DEF_LEFT);
+ break;
+ case 'b':
+ dev_bottom = get_iarg (argp[2], argv, argno, DEF_BOTTOM);
+ break;
+ case 'w':
+ dev_width = get_iarg (argp[2], argv, argno, DEF_WIDTH);
+ break;
+ case 'h':
+ dev_height = get_iarg (argp[2], argv, argno, DEF_HEIGHT);
+ break;
+ default:
+ break;
+ }
+
+ } else {
+ /* Input sgi-raster file specification.
+ */
+ infile = argp;
+ }
+ }
+
+ if (strcmp (infile, "stdin") == 0)
+ in = stdin;
+ else
+ in = fopen (infile, "r");
+
+ if (in == NULL) {
+ fprintf (stderr, "Fatal error (sgi2uhpii): Cannot open `%s'\n",
+ infile);
+ fflush (stderr);
+ exit (OSOK+1);
+ }
+
+ /* Process the rasterfile.
+ */
+ translate (in, stdout);
+
+ if (in != stdin)
+ fclose (in);
+
+ return (0);
+}
+
+
+/* TRANSLATE -- Interpret input SGI Raster File format into Hewlett Packard
+ * Raster graphics instructions and write to stdout.
+ */
+static void
+translate (FILE *in, FILE *out)
+{
+ int n1, swap_bytes;
+ int n, nlines, length, len_buf;
+ register unsigned char *bp1, *buffer1;
+ char buf_rast [SZ_RAST];
+
+
+ swap_bytes = isSwapped ();
+
+ len_buf = dev_width / NBITS_CHAR;
+ buffer1 = (unsigned char *)malloc (len_buf);
+
+ /* Output device initialization.
+ */
+ fwrite (xyencode (dev_left, dev_bottom), SZ_VECT, 1, out);
+ fwrite (DEV_INIT, strlen(DEV_INIT), 1, out);
+
+ /* Process the raster file
+ */
+ nlines = dev_height;
+ while ((n = fread (buffer1, len_buf, 1, in)) > 0) {
+
+ if (swap_bytes)
+ bswap2 (buffer1, buffer1, len_buf);
+
+ /* Keep track of number of lines left on the page.
+ */
+ if (!(nlines--)) {
+ nlines += dev_height;
+ fwrite (DEV_END, strlen (DEV_END), 1, out);
+ fwrite (xyencode (dev_left, dev_bottom), SZ_VECT, 1, out);
+ fwrite (DEV_INIT, strlen (DEV_INIT), 1, out);
+ }
+
+ /* Search for trailing null bytes to trim them off.
+ */
+ length = len_buf;
+ for (bp1 = buffer1+length; length && *(--bp1) == 0; length--)
+ ;
+
+ n1 = length;
+ if (n1 == 0) {
+ n1 = 1;
+ *buffer1 = 0;
+ }
+
+ /* Now copy out this line and prefix it with the control codes.
+ */
+ sprintf (buf_rast, DEV_RAST, n1);
+ fwrite (buf_rast, SZ_RAST, 1, out);
+ fwrite (buffer1, n1, 1, out);
+ }
+
+ /* Terminate plotting and exit.
+ */
+ fwrite (DEV_END, strlen(DEV_END), 1, out);
+}
+
+
+/* XYENCODE -- Encode x, y into a character string formatted for the device.
+ */
+static char *
+xyencode (int x, int y)
+{
+ static char obuf [SZ_VECT];
+
+ memset (obuf, 0, SZ_VECT);
+ sprintf (obuf, DEV_VECT, x, y);
+ return (obuf);
+}
diff --git a/unix/gdev/sgidev/sgi2uimp.c b/unix/gdev/sgidev/sgi2uimp.c
new file mode 100644
index 00000000..a8f566ed
--- /dev/null
+++ b/unix/gdev/sgidev/sgi2uimp.c
@@ -0,0 +1,341 @@
+/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+
+#define import_spp
+#define import_error
+#include <iraf.h>
+
+#include "sgiUtil.h"
+
+
+/*
+ * SGI2UIMP.C -- Read IRAF SGI metacode from standard input, translate into
+ * the Impress language and write to standard output.
+ *
+ * Usage
+ * sgi2uimp.e [-params] [sgi_metacode] [| lpr -v -Pimagen]
+ *
+ * -l N left edge; x plot origin in device pixels def DEF_LEFT
+ * -b N bottom edge; y plot origin in device pixels def DEF_BOTTOM
+ * -w N width of plot, device pixels starting from l def DEF_WIDTH
+ * -h N height of plot, device pixels starting from b def DEF_HEIGHT
+ * -p O.S pen width `origin' and `slope' def DEF_PENBASE
+ * .DEF_PENSLOPE
+ *
+ * Numeric values may be appended directly to their flags or separated by a
+ * space; the input file name and the switches may occur in any order.
+ * The windowing parameters are specified explicitly rather than using the
+ * plotter resolution and paper size due to differences in exactly where
+ * each different Imagen begins and ends plotting within the paper window.
+ *
+ */
+
+#define OSOK 0 /* normal successful completion */
+#define LEN_MCBUF 1024 /* number of SGK instrs in buffer */
+#define SGK_FRAME 1 /* new frame instruction */
+#define SGK_MOVE 2 /* move pen */
+#define SGK_DRAW 3 /* draw pen */
+#define SGK_SETLW 4 /* set line width */
+#define GKI_MAXNDC 32767 /* SGK units */
+
+/* Device opcodes and parameters. The default edge and width parameters
+ * (DEF_), given in device pixels for a 240 dot/inch Imagen with 8 1/2" x 11"
+ * paper, should be modified to fit the local plotter.
+ */
+#define DEF_LEFT 85 /* origin in device pixels in x */
+#define DEF_WIDTH 2490 /* width in x (240d/i, 11" paper) */
+#define DEF_BOTTOM 50 /* origin in device pixels in y */
+#define DEF_HEIGHT 1905 /* height in y (240d/i, 8.5" paper)*/
+#define DEF_PENBASE 2 /* base pen width */
+#define DEF_PENSLOPE 2 /* pen slope (b.s=3.2 ==> 3,5,7,9) */
+#define SZ_PENPARAM 5 /* max chars in penwidth parameter */
+#define BLACK_LINE 15 /* draw solid line */
+#define CREATE_PATH 230 /* set up set of vertices */
+#define DRAW_PATH 234 /* draw that set of vertices */
+#define END_DOCUMENT 255 /* end of document */
+#define END_PAGE 219 /* formfeed */
+#define HV_VALUE 125 /* 0 11 11 101 (orig, axes, orient)*/
+#define SET_ABS_H 135 /* move absolute in h */
+#define SET_ABS_V 137 /* move absolute in v */
+#define SET_HV_SYSTEM 205 /* establish coordinate system */
+#define SET_PEN 232 /* set pen width */
+#define SZ_HEAD 3 /* # header opcode bytes in obuf */
+#define SZ_TAIL 2 /* # trailing opcode bytes in obuf */
+#define COUNT_OFFSET 1 /* byte offset to npoints in obuf */
+
+/* Output macros -- watch out for SZ_OBUF; some Imagens have a limited amount
+ * of memory for the DRAW buffer:
+ */
+#define SZ_OBUF (1024)
+#define DECL_OBUF register char *op; char *np; char obuf[SZ_OBUF+1];
+#define o_clear (op=obuf)
+#define o_flush(o) fwrite(obuf,op-obuf,1,o)
+#define putbyte(v) (*op++ = (v))
+#define putword(v) ((*op++ = (v)/256), (*op++ = (v)%256))
+#define setcount(b,v) ((np = obuf+b), (*np++ = (v)/256), (*np = (v)%256))
+#define npoints ((op-obuf - SZ_HEAD)/4)
+#define obuf_full ((op-obuf + SZ_TAIL) >= SZ_OBUF)
+
+struct sgi_inst {
+ short opcode;
+ short x;
+ short y;
+};
+
+int imp_left;
+int imp_bottom;
+int imp_width;
+int imp_height;
+int imp_penbase = DEF_PENBASE;
+int imp_penslope = DEF_PENSLOPE;
+
+static void translate (FILE *in, FILE *out);
+
+
+/* MAIN -- Main entry point for SGI2UIMP. Optional arguments are device
+ * window parameters and name of input file.
+ */
+int
+main (int argc, char *argv[])
+{
+ FILE *in;
+ char *infile;
+ char *argp;
+ int argno;
+ int np;
+ char penparam[SZ_PENPARAM];
+
+
+ infile = "stdin";
+
+ /* Process the command line.
+ */
+ for (argno=1; (argp = argv[argno]) != NULL; argno++) {
+ if (argp[0] == '-') {
+ /* A window-control or pen width switch.
+ */
+ switch (argp[1]) {
+ case 'l':
+ imp_left = get_iarg (argp[2], argv, argno, DEF_LEFT);
+ break;
+ case 'b':
+ imp_bottom = get_iarg (argp[2], argv, argno, DEF_BOTTOM);
+ break;
+ case 'w':
+ imp_width = get_iarg (argp[2], argv, argno, DEF_WIDTH);
+ break;
+ case 'h':
+ imp_height = get_iarg (argp[2], argv, argno, DEF_HEIGHT);
+ break;
+ case 'p':
+ if (argp[2] == (char) 0)
+ if (argv[argno+1] == NULL) {
+ fprintf (stderr, "missing arg to switch `%s';",
+ argp);
+ fprintf (stderr, " reset to %d.%d\n", imp_penbase,
+ imp_penslope);
+ } else
+ strcpy (penparam, argv[++argno]);
+ else
+ strcpy (penparam, argv[argno]+2);
+
+ np = sscanf (penparam, "%d . %d", &imp_penbase,
+ &imp_penslope);
+ if (np == 1) {
+ imp_penslope = imp_penbase;
+ } else if (np < 1) {
+ imp_penbase = DEF_PENBASE;
+ imp_penslope = DEF_PENSLOPE;
+ }
+
+ break;
+ default:
+ break;
+ }
+
+ } else {
+ /* Input sgi-metacode file specification.
+ */
+ infile = argp;
+ }
+ }
+
+ if (strcmp (infile, "stdin") == 0)
+ in = stdin;
+ else
+ in = fopen (infile, "r");
+
+ if (in == NULL) {
+ fprintf (stderr, "Fatal error (sgi2uimp): Cannot open `%s'\n",
+ infile);
+ fflush (stderr);
+ exit (OSOK+1);
+ }
+
+ /* Process the metacode.
+ */
+ translate (in, stdout);
+
+ if (in != stdin)
+ fclose (in);
+
+ return (0);
+}
+
+
+/* TRANSLATE -- Interpret input SGI metacode instructions into the device
+ * language and write to stdout.
+ */
+static void
+translate (FILE *in, FILE *out)
+{
+ int n, x, y, swap_bytes;
+ float xscale, yscale;
+ register struct sgi_inst *sgip;
+ struct sgi_inst inbuf[LEN_MCBUF], *buftop;
+ DECL_OBUF;
+
+ swap_bytes = isSwapped();
+
+ xscale = (float) imp_width / (float) GKI_MAXNDC;
+ yscale = (float) imp_height / (float) GKI_MAXNDC;
+
+ /* Output device header instructions.
+ */
+ fprintf (out, "@Document(%s, %s, %s, %s, %s, %s)",
+ "language impress", "pagecollation on", "jamresistance on",
+ "name \"IRAF SGI plot\"", "prerasterization on", "jobheader off");
+
+ /* Output page orientation and coordinate system initialization.
+ */
+ putc (SET_HV_SYSTEM, out);
+ putc (HV_VALUE, out);
+
+ /* Initialize pen width.
+ */
+ putc (SET_PEN, out);
+ putc (1 * imp_penbase, out);
+
+ o_clear;
+
+ /* Process the metacode:
+ */
+ while ((n = fread ((char *)inbuf, sizeof(*sgip), LEN_MCBUF, in)) > 0) {
+
+ if (swap_bytes)
+ bswap2 ((unsigned char *)inbuf, (unsigned char *)inbuf,
+ sizeof(*sgip) * n);
+
+ buftop = inbuf + n;
+
+ for (sgip = inbuf; sgip < buftop; sgip++) {
+ switch (sgip->opcode) {
+ case SGK_FRAME:
+ /* Terminate and output any DRAW buffer contents.
+ */
+ if (npoints > 1) {
+ setcount (COUNT_OFFSET, npoints);
+ putbyte (DRAW_PATH);
+ putbyte (BLACK_LINE);
+ o_flush (out);
+ }
+
+ o_clear;
+ putbyte (END_PAGE);
+ putbyte (SET_ABS_H);
+ putword (0);
+ putbyte (SET_ABS_V);
+ putword (0);
+ o_flush (out);
+ break;
+
+ case SGK_MOVE:
+ /* Terminate and output any DRAW buffer contents.
+ */
+ if (npoints > 1) {
+ setcount (COUNT_OFFSET, npoints);
+ putbyte (DRAW_PATH);
+ putbyte (BLACK_LINE);
+ o_flush (out);
+ }
+
+ x = imp_left + sgip->x * xscale;
+ y = imp_bottom + sgip->y * yscale;
+
+ /* Initialize output buffer for start of draw instruction.
+ */
+ o_clear;
+ putbyte (CREATE_PATH);
+ putword (1);
+ putword (x); putword (y);
+
+ break;
+
+ case SGK_DRAW:
+ x = imp_left + sgip->x * xscale;
+ y = imp_bottom + sgip->y * yscale;
+ putword (x); putword (y);
+
+ /* If we are about to exceed output buffer, flush and re-
+ * initialize starting with current point.
+ */
+ if (obuf_full) {
+ setcount (COUNT_OFFSET, npoints);
+ putbyte (DRAW_PATH);
+ putbyte (BLACK_LINE);
+ o_flush (out);
+
+ /* Reinitialize DRAW buffer.
+ */
+ o_clear;
+ putbyte (CREATE_PATH);
+ putword (1);
+ putword (x); putword (y);
+ }
+
+ break;
+
+ case SGK_SETLW:
+ /* Terminate and output any DRAW buffer contents.
+ */
+ if (npoints > 1) {
+ setcount (COUNT_OFFSET, npoints);
+ putbyte (DRAW_PATH);
+ putbyte (BLACK_LINE);
+ o_flush (out);
+ o_clear;
+ }
+
+ /* Set pen width.
+ */
+ putc (SET_PEN, out);
+ putc ((imp_penbase + ((sgip->x) - 1) * imp_penslope), out);
+ break;
+
+ default:
+ fprintf (stderr, "sgi2uimp: unrecognized sgi opcode %d\n",
+ sgip->opcode);
+ break;
+ }
+ }
+ }
+
+ /* Flush any remaining buffered points.
+ */
+ if (npoints > 1) {
+ setcount (COUNT_OFFSET, npoints);
+ putbyte (DRAW_PATH);
+ putbyte (BLACK_LINE);
+ o_flush (out);
+ }
+
+ /* Signal end of page and end of document.
+ */
+ putc (END_PAGE, out);
+ putc (END_DOCUMENT, out);
+}
diff --git a/unix/gdev/sgidev/sgi2uptx.c b/unix/gdev/sgidev/sgi2uptx.c
new file mode 100644
index 00000000..6c44f334
--- /dev/null
+++ b/unix/gdev/sgidev/sgi2uptx.c
@@ -0,0 +1,61 @@
+/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+
+#define NBITS_CHAR 8 /* number of bits in a char */
+#define MASK 64 /* printronix raster flag */
+#define START_LINE "\005" /* start of raster line control code */
+#define END_LINE "\012" /* end of raster line control code */
+#define START_PAGE "\014" /* form feed */
+
+/* PRINTRONIX translator from the SGI bitmap file to the STDOUT */
+
+int
+main (int argc, char *argv[])
+{
+
+ FILE *fpi;
+ char *buffer;
+ int n, len_buf, nlines;
+ int index; /* goes through all 8 files */
+ int px, py;
+
+ px = atoi (argv[1]);
+ py = atoi (argv[2]);
+ len_buf = px/NBITS_CHAR;
+ buffer = (char *) malloc (len_buf);
+
+ for (index=3; index<argc; index++) {
+
+ if (index != 3) fwrite (START_PAGE, 1, 1, stdout);
+ fpi = fopen (argv[index], "r");
+ nlines = py;
+
+ while (fread (buffer, len_buf, 1, fpi)) {
+
+ /* Keep track of number of lines left on the page. */
+ if (!(nlines--)) {
+ nlines += py;
+ fwrite (START_PAGE, 1, 1, stdout);
+ }
+
+ /* Turn on the raster flag on every data byte */
+ for (n = 0; n < len_buf; n++) buffer[n] |= MASK;
+
+ /* Now copy out this line and bracket it with the control codes. */
+ fwrite (START_LINE, 1, 1, stdout);
+ fwrite (buffer, len_buf, 1, stdout);
+ fwrite (END_LINE, 1, 1, stdout);
+
+ }
+
+ fclose (fpi);
+
+ }
+
+ return (0);
+}
diff --git a/unix/gdev/sgidev/sgi2uqms.c b/unix/gdev/sgidev/sgi2uqms.c
new file mode 100644
index 00000000..e91d7e38
--- /dev/null
+++ b/unix/gdev/sgidev/sgi2uqms.c
@@ -0,0 +1,296 @@
+/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+
+#define import_spp
+#define import_error
+#include <iraf.h>
+
+#include "sgiUtil.h"
+
+
+/*
+ * SGI2UQMS.C -- Read IRAF SGI metacode from standard input, translate into
+ * the QMS Vector Graphics Mode (Talaris Lasergrafix, QUIC Command Mode) and
+ * write to standard output.
+ *
+ * Usage
+ * sgi2uqms.e [-params] [sgi_metacode] [| lpr -Pqms]
+ *
+ * -l N left edge; x plot origin in device pixels def DEF_LEFT
+ * -b N bottom edge; y plot origin in device pixels def DEF_BOTTOM
+ * -w N width of plot, device pixels starting from l def DEF_WIDTH
+ * -h N height of plot, device pixels starting from b def DEF_HEIGHT
+ * -p O.S pen width `origin' and `slope' def DEF_PENBASE
+ * .DEF_PENSLOPE
+ *
+ * Numeric values may be appended directly to their flags or separated by a
+ * space; the input file name and the switches may occur in any order.
+ */
+
+#define OSOK 0 /* normal successful completion */
+#define LEN_MCBUF 1024 /* number of SGK instrs in buffer */
+#define SGK_FRAME 1 /* new frame instruction */
+#define SGK_MOVE 2 /* move pen */
+#define SGK_DRAW 3 /* draw pen */
+#define SGK_SETLW 4 /* set line width */
+#define GKI_MAXNDC 32767 /* SGK units */
+
+/* Device opcodes and parameters. The default edge and width parameters (DEF_)
+ * are given in QMS pixels, at 300 dots/inch. The QMS y-origin is at the
+ * top of the page, so in GRAPHCAP, YF must be set, and Landscape Orientation
+ * used in the QMS. Thus the maximum page `width' is 11*300 pixels, `height'
+ * is 8.5*300 pixels.
+ */
+#define DEV_INIT "\012^PY^-\012^ISYNTAX00010^IOL^F^IGV" /* Enter graph.*/
+#define DEV_END "^IGE^ISYNTAX00000^IOP^O\012^PN^-\012" /* Exit graph. */
+#define DEV_FRAME "^," /* QMS Vector Graphics Mode form feed instr */
+#define DEV_MOVE "^U" /* QMS (VGM) pen-up instruction */
+#define DEV_DRAW "^D" /* QMS (VGM) pen-down instruction */
+#define DEV_SETLW "^PW" /* QMS (VGM) Set Line Width (follow w/ nn) */
+
+#define DEF_LEFT 30 /* origin in device pixels in x */
+#define DEF_WIDTH 3180 /* width in x (300d/i, 11" paper) */
+#define DEF_BOTTOM 60 /* origin in device pixels in y */
+#define DEF_HEIGHT 2415 /* height in y (300d/i, 8.5" paper) */
+#define DEF_PENBASE 3 /* base pen width (LW 1->2) */
+#define DEF_PENSLOPE 4 /* pen width slope (LW 2->4, 3->6 etc.) */
+#define SZ_PENCMD 5 /* total no. of chars in penwidth instruction */
+#define SZ_PENVAL 2 /* no. of chars in penwidth value */
+#define SZ_VECT 11 /* total no. chars in a MOVE or DRAW inst. */
+#define SZ_COORD 4 /* no. of chars in device coordinate */
+
+struct sgi_inst {
+ short opcode;
+ short x;
+ short y;
+};
+
+int dev_left;
+int dev_bottom;
+int dev_width;
+int dev_height;
+int dev_penbase = DEF_PENBASE;
+int dev_penslope = DEF_PENSLOPE;
+
+static void translate (FILE *in, FILE *out);
+static char *xyencode (int opcode, int x, int y);
+static char *penencode (char *opcode, int val);
+
+
+
+/* MAIN -- Main entry point for SGI2UQMS. Optional arguments are device
+ * window parameters and name of input file.
+ */
+int
+main (int argc, char *argv[])
+{
+ FILE *in;
+ char *infile;
+ char *argp;
+ int argno;
+ int np;
+ char penparam[SZ_PENCMD];
+
+
+ infile = "stdin";
+
+ /* Process the command line.
+ */
+ for (argno=1; (argp = argv[argno]) != NULL; argno++) {
+ if (argp[0] == '-') {
+ /* A window-control or pen width switch.
+ */
+ switch (argp[1]) {
+ case 'l':
+ dev_left = get_iarg (argp[2], argv, argno, DEF_LEFT);
+ break;
+ case 'b':
+ dev_bottom = get_iarg (argp[2], argv, argno, DEF_BOTTOM);
+ break;
+ case 'w':
+ dev_width = get_iarg (argp[2], argv, argno, DEF_WIDTH);
+ break;
+ case 'h':
+ dev_height = get_iarg (argp[2], argv, argno, DEF_HEIGHT);
+ break;
+ case 'p':
+ if (argp[2] == (char) 0)
+ if (argv[argno+1] == NULL) {
+ fprintf (stderr, "missing arg to switch `%s';",
+ argp);
+ fprintf (stderr, " reset to %d.%d\n", dev_penbase,
+ dev_penslope);
+ } else
+ strcpy (penparam, argv[++argno]);
+ else
+ strcpy (penparam, argv[argno]+2);
+
+ np = sscanf (penparam, "%d . %d", &dev_penbase,
+ &dev_penslope);
+ if (np == 1) {
+ dev_penslope = dev_penbase;
+ } else if (np < 1) {
+ dev_penbase = DEF_PENBASE;
+ dev_penslope = DEF_PENSLOPE;
+ }
+
+ break;
+ default:
+ break;
+ }
+
+ } else {
+ /* Input sgi-metacode file specification.
+ */
+ infile = argp;
+ }
+ }
+
+ if (strcmp (infile, "stdin") == 0)
+ in = stdin;
+ else
+ in = fopen (infile, "r");
+
+ if (in == NULL) {
+ fprintf (stderr, "Fatal error (sgi2uqms): Cannot open `%s'\n",
+ infile);
+ fflush (stderr);
+ exit (OSOK+1);
+ }
+
+ /* Process the metacode.
+ */
+ translate (in, stdout);
+
+ if (in != stdin)
+ fclose (in);
+
+ return (0);
+}
+
+
+/* TRANSLATE -- Interpret input SGI metacode instructions into device
+ * instructions and write to stdout.
+ */
+static void
+translate (FILE *in, FILE *out)
+{
+ int n, x, y, swap_bytes;
+ float xscale, yscale;
+ register struct sgi_inst *sgip;
+ struct sgi_inst inbuf[LEN_MCBUF], *buftop;
+
+
+ swap_bytes = isSwapped();
+
+ xscale = (float) dev_width / (float) GKI_MAXNDC;
+ yscale = (float) dev_height / (float) GKI_MAXNDC;
+
+ /* Output device initialization.
+ */
+ fwrite (DEV_INIT, strlen(DEV_INIT), 1, out);
+
+ /* Initialize pen width.
+ */
+ fwrite (penencode (DEV_SETLW, dev_penbase), SZ_PENCMD, 1, out);
+
+ /* Process the metacode:
+ */
+ while ((n = fread ((char *)inbuf, sizeof(*sgip), LEN_MCBUF, in)) > 0) {
+
+ if (swap_bytes)
+ bswap2 ((unsigned char *)inbuf, (unsigned char *)inbuf,
+ sizeof(*sgip) * n);
+
+ buftop = inbuf + n;
+
+ for (sgip = inbuf; sgip < buftop; sgip++) {
+ switch (sgip->opcode) {
+ case SGK_FRAME:
+ fwrite (DEV_FRAME, strlen(DEV_FRAME), 1, out);
+ break;
+
+ case SGK_MOVE:
+ x = dev_left + sgip->x * xscale;
+ y = dev_bottom + sgip->y * yscale;
+ fwrite (xyencode ('U', x, y), SZ_VECT, 1, out);
+ break;
+
+ case SGK_DRAW:
+ x = dev_left + sgip->x * xscale;
+ y = dev_bottom + sgip->y * yscale;
+ fwrite (xyencode ('D', x, y), SZ_VECT, 1, out);
+ break;
+
+ case SGK_SETLW:
+ /* Set pen width.
+ */
+ fwrite (penencode (DEV_SETLW, dev_penbase +
+ ((sgip->x) - 1) * dev_penslope), SZ_PENCMD, 1, out);
+ break;
+
+ default:
+ fprintf (stderr, "sgi2uqms: unrecognized sgi opcode %d\n",
+ sgip->opcode);
+ break;
+ }
+ }
+ }
+
+ /* Terminate plotting and exit.
+ */
+ fwrite (DEV_END, strlen(DEV_END), 1, out);
+}
+
+
+/* XYENCODE -- Encode x, y into a character string formatted for the device.
+ */
+static char *
+xyencode (
+ int opcode, /* draw or move */
+ int x, /* must be positive */
+ int y /* must be positive */
+)
+{
+ static char obuf[] = "^X0000:0000";
+ register int digit, n;
+ register char *op;
+ int i;
+
+ obuf[1] = opcode;
+ i = SZ_VECT - 1 - SZ_COORD - 1;
+ for (op = &obuf[i], digit = SZ_COORD, n=x; --digit >= 0; n = n / 10)
+ *op-- = n % 10 + '0';
+ i = SZ_VECT - 1;
+ for (op = &obuf[i], digit = SZ_COORD, n=y; --digit >= 0; n = n / 10)
+ *op-- = n % 10 + '0';
+
+ return (obuf);
+}
+
+
+/* PENENCODE -- Encode base, slope into a character string formatted for the
+ * device set-pen command.
+ */
+static char *
+penencode (
+ char *opcode, /* device set-linewidth command */
+ int val /* device line width */
+)
+{
+ static char obuf[SZ_PENCMD+1];
+ register int digit, n;
+ register char *op;
+
+ strcpy (obuf, opcode);
+ for (op = &obuf[SZ_PENCMD-1], digit = SZ_PENVAL, n=val; --digit >= 0;
+ n = n / 10)
+ *op-- = n % 10 + '0';
+
+ return (obuf);
+}
diff --git a/unix/gdev/sgidev/sgi2xbm.c b/unix/gdev/sgidev/sgi2xbm.c
new file mode 100644
index 00000000..6d4c230a
--- /dev/null
+++ b/unix/gdev/sgidev/sgi2xbm.c
@@ -0,0 +1,135 @@
+/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+
+#include "sgiUtil.h"
+
+
+/* SGI2XBM.C -- Read an IRAF SGI bitmap file on standard input and convert
+ * to a GIF format image on standard outout.
+ *
+ * Usage:
+ * sgi2xbm.e [-w N] [-h NY] [-i] [ [sgi_bitmap] [sgi_bitmap] ... ]
+ *
+ * -w N width of input bitmap and output image
+ * -h N height of input bitmap and output image
+ * -i invert the bitmap values before conversion
+ *
+ * The input file name and the switches may occur in any order. The bitmap
+ * may be inverted here using the -i flag.
+ *
+ * Sample graphcaps for this translator might look like:
+ *
+ * g-xbm|UNIX generic interface to multi-frame XBM file generator:\
+ * :DD=ugif,tmp$sgk,!{ sgidispatch sgi2xbm -w $(PX) -h $(PY) \
+ * $F.[1-8] > sgixbm$$; rm $F.[1-8]; }&:\
+ * :MF#8:NF:tc=sgi_image_format:
+ *
+ * sgi_image_format|Generic raster file format specification:\
+ * :kf=bin$x_sgikern.e:tn=sgikern:ar#.75:\
+ * :xr#640:yr#480:PX#640:PY#480:XW#640:YW#480:\
+ * :BI:MF#1:YF:NB#8:LO#1:LS#0:XO#0:YO#0:
+ *
+ * All bitmaps will be dumped to the file 'sgixbmXXX' in the local directory
+ * where XXX is a pid.
+ *
+ * To change the image size the graphcap :xr, :PX, :XW (X-dimension) and
+ * :yr, :PY, :XY (Y-dimension) fields all need to be changed. The -i
+ * flag must be specified in the graphcap DD string.
+ *
+ */
+
+#define NBITS_CHAR 8 /* number of bits in a char */
+#define DEF_WIDTH 640 /* default image width */
+#define DEF_HEIGHT 480 /* default image height */
+#define MAX_INFILES 16 /* max number of input bitmaps */
+#define SZ_FNAME 64 /* size of a filename */
+
+typedef unsigned char byte;
+
+static int px = DEF_WIDTH;
+static int py = DEF_HEIGHT;
+static int invert = 0;
+static char *infile[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+
+
+int
+main (int argc, char *argv[])
+{
+ FILE *fd;
+ byte *buffer;
+ int i, n, len_buf, numin = 0, cnt = 0;
+ int index; /* goes through all files */
+
+
+ /* Process the command line.
+ */
+ for (i=1; i < argc; i++) {
+ if (argv[i][0] == '-') {
+ if (strcmp (argv[i], "-w") == 0)
+ px = atoi (argv[++i]);
+ else if (strcmp (argv[i], "-h") == 0)
+ py = atoi (argv[++i]);
+ else if (strcmp (argv[i], "-i") == 0)
+ invert++;
+ } else {
+ /* input sgi-bitmap file specification */
+ if (numin < MAX_INFILES)
+ infile[numin++] = argv[i];
+ }
+
+ }
+
+ /* Allocate some space for the working buffer. */
+ len_buf = px / NBITS_CHAR;
+ buffer = (byte *) malloc (len_buf);
+
+ /* Loop over the input bitmaps, writing the converted output to
+ * the stdout.
+ */
+ for (index = 0; index == 0 || index < numin; index++) {
+
+ /* Open the input file. */
+ fd = (infile[index] ? fopen (infile[index], "r") : stdin);
+
+ if (index > 0) printf ("\n");
+
+ printf ("#define xbm%03d_width %d\n", index, px);
+ printf ("#define xbm%03d_height %d\n", index, py);
+ printf ("static char xbm%03d_bits[] = {\n ", index);
+
+ n = 0;
+ cnt = 0;
+ while (fread (buffer, len_buf, 1, fd)) {
+ /* If we're on a MSB ordered machine wordswap the bitmap so
+ * it's in the correct order for unpacking to be interpreted
+ * as an LSB-ordered image.
+ */
+ if (!isSwapped ())
+ bswap4 (buffer, buffer, len_buf);
+
+ /* Write out the pixels. */
+ for (i=0; i < len_buf; i++, cnt++) {
+ printf ("0x%.2x",
+ (byte) (invert ? ~buffer[i]: buffer[i])), n += 4;
+ if (cnt < (len_buf * py - 1))
+ printf (","), n++;
+ else
+ printf ("};\n");
+ if (n > 70)
+ printf ("\n "), n=0;
+ }
+ }
+
+ if (fd != stdin)
+ fclose (fd);
+ fflush (fd);
+ }
+ free (buffer);
+
+ return (0);
+}
diff --git a/unix/gdev/sgidev/sgiUtil.c b/unix/gdev/sgidev/sgiUtil.c
new file mode 100644
index 00000000..25214450
--- /dev/null
+++ b/unix/gdev/sgidev/sgiUtil.c
@@ -0,0 +1,132 @@
+/**
+ * SGIUTIL.C -- Shared utility procedures for the SGI translators.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <string.h>
+
+#define import_spp
+#define import_error
+#include <iraf.h>
+
+
+/**
+ * BSWAP2 -- Move bytes from array "a" to array "b", swapping successive
+ * pairs of bytes. The two arrays may be the same but may not be offset
+ * and overlapping.
+ */
+void
+bswap2 (
+ unsigned char *a, /* input array */
+ unsigned char *b, /* output array */
+ int nbytes /* number of bytes to swap */
+)
+{
+ register unsigned char *ip, *op, *otop;
+ register unsigned int temp;
+
+ ip = a;
+ op = b;
+ otop = op + (nbytes & ~1);
+
+ /* Swap successive pairs of bytes.
+ */
+ while (op < otop) {
+ temp = *ip++;
+ *op++ = *ip++;
+ *op++ = temp;
+ }
+
+ /* If there is an odd byte left, move it to the output array.
+ */
+ if (nbytes & 1)
+ *op = *ip;
+}
+
+
+/* BSWAP4 - Move bytes from array "a" to array "b", swapping the four bytes
+ * in each successive 4 byte group, i.e., 12345678 becomes 43218765.
+ * The input and output arrays may be the same but may not partially overlap.
+*/
+void
+bswap4 (
+ unsigned char *a, /* input array */
+ unsigned char *b, /* output array */
+ int nbytes /* number of bytes to swap */
+)
+{
+ register int n;
+ register unsigned char *ip, *op, *tp;
+ static unsigned char temp[4];
+
+ tp = temp;
+ ip = (unsigned char *)a;
+ op = (unsigned char *)b;
+
+ /* Swap successive four byte groups.
+ */
+ for (n = nbytes >> 2; --n >= 0; ) {
+ *tp++ = *ip++;
+ *tp++ = *ip++;
+ *tp++ = *ip++;
+ *tp++ = *ip++;
+ *op++ = *--tp;
+ *op++ = *--tp;
+ *op++ = *--tp;
+ *op++ = *--tp;
+ }
+
+ /* If there are any odd bytes left, move them to the output array.
+ * Do not bother to swap as it is unclear how to swap a partial
+ * group, and really incorrect if the data is not modulus 4.
+ */
+ for (n = nbytes & 03; --n >= 0; )
+ *op++ = *ip++;
+}
+
+
+/**
+ * ISSWAPPED -- Test whether we are running on a byte-swapped machine.
+ */
+int
+isSwapped (void)
+{
+ union {
+ short tswap;
+ char b[2];
+ } test;
+
+ test.tswap = 1;
+ return ((int) test.b[0]);
+}
+
+
+/**
+ * GET_IARG -- Get an integer argument, whether appended directly to flag
+ * or separated by a whitespace character; if error, report and assign
+ * default.
+ */
+int
+get_iarg (
+ char argp,
+ char **argv,
+ int argno,
+ int def_val
+)
+{
+ int temp_val;
+
+ if (argp == (char) 0) {
+ if (argv[argno+1] == NULL) {
+ fprintf (stderr, "missing arg to switch `%c';", argp);
+ fprintf (stderr, " reset to %d\n", def_val);
+ temp_val = def_val;
+ } else
+ temp_val = atoi (argv[++argno]);
+ } else
+ temp_val = atoi (argv[argno]+2);
+
+ return (temp_val);
+}
diff --git a/unix/gdev/sgidev/sgiUtil.h b/unix/gdev/sgidev/sgiUtil.h
new file mode 100644
index 00000000..9630a03e
--- /dev/null
+++ b/unix/gdev/sgidev/sgiUtil.h
@@ -0,0 +1,10 @@
+/**
+ * SGIUTIL.H -- Declarations for the SGI utility routines.
+ */
+
+void bswap2 (unsigned char *a, unsigned char *b, int nbytes);
+void bswap4 (unsigned char *a, unsigned char *b, int nbytes);
+
+int isSwapped (void);
+
+int get_iarg (char argp, char **argv, int argno, int def_val);
diff --git a/unix/gdev/sgidev/sgidispatch.c b/unix/gdev/sgidev/sgidispatch.c
new file mode 100644
index 00000000..90201460
--- /dev/null
+++ b/unix/gdev/sgidev/sgidispatch.c
@@ -0,0 +1,70 @@
+/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+
+#define import_spp
+#define import_error
+#define import_kernel
+#define import_knames
+#include <iraf.h>
+
+
+/*
+ * SGIDISPATCH.C -- Determine pathname to the executable for the named SGI
+ * translator, and execute the translator. Pass all command line arguments
+ * to the child, which also inherits stdin, stdout, and stderr.
+ *
+ * Usage: sgidispatch translator [args]
+ */
+
+#define DEF_HOST "unix" /* default host system */
+#define F_OK 0 /* access mode `file exists' */
+#ifndef X_OK
+#define X_OK 1 /* access mode `executable' */
+#endif
+
+char *irafpath();
+
+
+/* MAIN -- Main entry point for SGIDISPATCH.
+ */
+int
+main (int argc, char *argv[])
+{
+ char tpath[SZ_PATHNAME+1];
+ char translator[SZ_PATHNAME+1];
+ int ip;
+
+ /* Do nothing if called with no arguments.
+ */
+ if (argc < 2)
+ exit (OSOK);
+
+ /* Construct pathname to translator.
+ */
+ strcpy (translator, argv[1]);
+ ip = strlen (translator);
+ if (strcmp (&translator[ip], ".e") != 0)
+ strcat (translator, ".e");
+ sprintf (tpath, "%s", irafpath(translator));
+
+ if (access (tpath, X_OK) == ERR) {
+ fprintf (stderr, "Fatal (sgidispatch): unable to access SGI");
+ fprintf (stderr, " translator `%s'\n", tpath);
+ fflush (stderr);
+ exit (OSOK+1);
+ }
+
+ /* Set up i/o for translator and attempt to fork.
+ */
+ argv[argc] = 0;
+ execv (tpath, &argv[1]);
+ fprintf (stderr, "Fatal (sgidispatch): unable to execv(%s, ...)\n",
+ tpath);
+ fflush (stderr);
+ exit (OSOK+1);
+}