v06i071: Scantool -- Read from a scanner, Part01/03

Rich Burridge richb at Aus
Thu Apr 12 19:12:46 AEST 1990


Submitted-by: richb at Aus (Rich Burridge)
Posting-number: Volume 6, Issue 71
Archive-name: xscan/part01


This is version 1.4 of the scantool program. It can interface to a Microtek
MS300A scanner, scan the document, and turn the image into a Sun rasterfile,
which can be read by dtp programs such as Frame Maker.

There are grtaphical interfaces for XView and SunView, and it would be fairly
easy to "knock up" an interface to other X11 toolkits that supported frames,
drawing canvases and popup menus.

The software is now divided into two programs; scantool a frontend window
based program for setting the scanning options, and scan, the program that
will actually perform the scan. It should also be possible to run this
scan program on it's own, but there are several command line options to
setup, so it's probably easier through scantool.

**IMPORTANT NOTE**

I no longer have access to a Microtek MS300A scanner. If you find problems
in this area, then you are on your own. I will be very happy to incorporate
any fixes you make, so other people can enjoy them as well.

Suggestions for furthur improvement would be most welcome, plus bugs,
comments and flames.

Rich Burridge,          DOMAIN: richb at Aus.Sun.COM
PHONE: +61 2 413 2666   ACSNET: richb at sunaus.sun.oz
                        UUCP:   {uunet,mcvax,ukc}!munnari!sunaus.oz!richb

   File Name		Archive #	Description
----------------------------------------------------------
 scantool                   1	
 scantool/CHANGES           3	
 scantool/Imakefile         3	
 scantool/Makefile          2	
 scantool/README            3	
 scantool/black.codes       3	
 scantool/button.invert.icon  3	
 scantool/button.normal.icon  3	
 scantool/exclaim.icon      3	
 scantool/frame.cursor      3	
 scantool/graphics.c        2	
 scantool/help.cursor       3	
 scantool/images.h          3	
 scantool/main.cursor       3	
 scantool/misc.c            2	
 scantool/patchlevel.h      3	
 scantool/scan.1            3	
 scantool/scan.c            1	
 scantool/scan.h            3	
 scantool/scan_compress.c   2	
 scantool/scan_extern.h     2	
 scantool/scantool.1        2	
 scantool/scantool.c        2	
 scantool/scantool.h        3	
 scantool/scantool.help     3	
 scantool/scantool.icon     3	
 scantool/scantool_extern.h  3	
 scantool/sunview.c         1	
 scantool/switch.invert.cursor  3	
 scantool/switch.normal.cursor  1	
 scantool/white.codes       3	
 scantool/xview.c           1	
------CUT HERE------Part1of3------CUT HERE------

#! /bin/sh
# This is a shell archive.  Remove anything before this line, then feed it
# into a shell via "sh file" or similar.  To overwrite existing files,
# type "sh file -c".
# The tool that generated this appeared in the comp.sources.unix newsgroup;
# send mail to comp-sources-unix at uunet.uu.net if you want that tool.
# If this archive is complete, you will see the following message at the end:
#		"End of archive 1 (of 3)."
# Contents:  scantool scantool/scan.c scantool/sunview.c
#   scantool/switch.normal.cursor scantool/xview.c
# Wrapped by argv at turnpike on Thu Apr 12 02:08:22 1990
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test ! -d 'scantool' ; then
    echo shar: Creating directory \"'scantool'\"
    mkdir 'scantool'
fi
if test -f 'scantool/scan.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'scantool/scan.c'\"
else
echo shar: Extracting \"'scantool/scan.c'\" \(19805 characters\)
sed "s/^X//" >'scantool/scan.c' <<'END_OF_FILE'
X
X/*  @(#)scan.c 1.4 90/04/04
X *
X *  Program which will read a scanned image from a Microtek
X *  MS-300A scanner and convert it to a Sun rasterfile.
X *
X *  Copyright (c) Rich Burridge.
X *                Sun Microsystems, Australia - All rights reserved.
X *
X *  Permission is given to distribute these sources, as long as the
X *  copyright messages are not removed, and no monies are exchanged.
X *
X *  No responsibility is taken for any errors or inaccuracies inherent
X *  either to the comments or the code of this program, but if
X *  reported to me, then an attempt will be made to fix them.
X */
X
X#include <stdio.h>
X#include <strings.h>
X#include <signal.h>
X#include <sgtty.h>
X#include <rasterfile.h>
X#include <sys/time.h>
X#include <sys/types.h>
X#include "patchlevel.h"
X#include "scan.h"
X
Xchar cksum ;               /* Packets checksum. */
Xchar cntbytes ;            /* Number of count bytes received. */
Xchar finalimage[MAXLINE] ; /* Name of uncompressed image file. */
Xchar from_rs[BUFSIZE] ;    /* Data received from the RS232. */
Xchar line[MAXLINE] ;
Xchar picname[MAXLINE] ;    /* Picture name for rasterfile output. */
Xchar progname[MAXLINE] ;   /* Name of this program. */
Xchar rscksum ;             /* RS232 read packet checksum. */
Xchar rsdata[BUFSIZE] ;     /* Latest packet to/from the scanner. */
Xchar rsrhold = XON ;       /* RS232 host hand shaking state. */
Xchar rsrstate = RSSOR ;    /* State of RS232 read automation. */
Xchar rsrtype ;             /* Record type received. */
Xchar rswstate ;            /* RS232 write acknowledgement state. */
Xchar scantype[MAXLINE] ;   /* Scanner details. */
Xchar temphead[MAXLINE] ;   /* Temporary filename for header file. */
Xchar tempimage[MAXLINE] ;  /* Temporary filename for saved scanned data. */
X
Xint brightness ;           /* Brightness value. */
Xint cancel ;               /* Indicates if should cancel current scan. */
Xint complete ;             /* Indicates if scanning is completed. */
Xint contrast ;             /* Contrast value. */
Xint error ;                /* Has an error report has been received? */
Xint fd = -1 ;              /* File descriptor for RS232 line. */
Xint finished ;             /* Indicates if we have finished uncompressing. */
Xint fwidth ;               /* Final width of rasterfile. */
Xint height ;               /* Height in scan lines of raster file image. */
Xint pic_compressed = 0 ;   /* Whether any picture data was compressed. */
Xint pkt_started = 0 ;      /* Is a data packet coming from the scanner? */
Xint pktdone ;              /* Indicates if a complete packet received. */
Xint rc ;                   /* Current character from scanned file. */
Xint rcount ;               /* Count of bit position within read character. */
Xint rscnt ;                /* Number of data bytes to read. */
Xint rsptr ;                /* Character buffer pointer. */
Xint wc ;                   /* Current character to write to final image file. */
Xint wcount ;               /* Count of bit position within write character. */
Xint width ;                /* Width in pixels of rasterfile image. */
Xint grain ;                /* Grain value. */
Xint resolution ;           /* Resolution value. */
Xint retval ;               /* This programs exit status. */
Xint rf ;                   /* File descriptor for raster image. */
X
Xint switches[4] =
X      {
X        0,                 /* Mode (Line Art). */
X        1,                 /* Data Transfer (Compressed). */
X        0,                 /* Serial Port (A). */
X        1                  /* Baud Rate (19200). */
X      } ;
X
Xint framevals[4] =            /* Initial frame in 1/8th inch intervals. */
X      {
X        16,                /* X1. */
X        16,                /* Y1. */
X        48,                /* X2. */
X        48,                /* Y2. */
X     } ;
X
XFILE *rd ;                 /* File descriptor for input files. */
XFILE *wd ;                 /* File descriptor for final image. */
X
X#ifdef NO_4.3SELECT
Xint readmask ;                /* File descriptors with outstanding reads. */
X#else
Xfd_set readmask ;             /* Readmask used in select call. */
X#endif NO_4.3SELECT
X
Xstruct timeval timeout = { MAXTIME, 0 } ;
X
Xstruct code *whites[16] ;   /* White initial starting pointers. */
Xstruct code *blacks[4] ;    /* Black initial starting pointers. */
X
X
X/*  The scan program can exit is a variety of ways. These are:
X *
X *  0          - successful   - image saved in picname.
X *  1          - unsuccessful - cannot open ttyline.
X *  2          - unsuccessful - cannot open temporary image file.
X *  3          - unsuccessful - cannot open raster header file.
X *  4          - unsuccessful - scanner not responding. Aborting this scan.
X *  5          - unsuccessful - invalid command line argument.
X *  100 + 0xnn - unsuccessful - scanning error 0xnn received. Scan aborted.
X *  200 + n    - unsuccessful - scan program terminated with signal n.
X *
X *  It is upto the calling program or shell script to display the
X *  appropriate message back to the user.
X */
X
Xmain(argc, argv)
Xint argc ;
Xchar *argv[] ;
X{
X  retval = 0 ;
X  set_signals() ;              /* Set up a signal handler. */
X  STRCPY(progname, argv[0]) ;  /* Save program name. */
X  get_options(argc, argv) ;    /* Extract scanning parameters. */
X  do_scan() ;                  /* Perform a scan using given parameters. */
X  exit(retval) ;
X}
X
X
XSIGRET
Xdo_exit(sig)   /* Signal received; exit gracefully. */
Xint sig ;
X{
X  char outval ;
X
X  if (fd != -1)     /* Terminate the scan properly, if started. */
X    {
X      outval = ETX ;
X      WRITE(fd, &outval, 1) ;
X      CLOSE(fd) ;
X    }
X  exit(200 + sig) ;
X}
X
X
Xdo_handshake(value)            /* Send RS232 handshake XON/XOFF. */
Xchar value ;
X{
X  WRITE(fd, &value, 1) ;
X  rsrhold = value ;
X}
X
X
Xdo_scan()                      /* Perform a scan using given parameters. */
X{
X  char c ;                     /* Next character for RS232 output. */
X
X  pic_compressed = 0 ;
X  height = 0 ;
X  error = 0 ;                           /* Set to 1 on error. */
X  if (open_temp_file() < 0) return ;    /* Open file for raster image. */
X  if (init_rs_port(SERIAL_PORT, BAUD_RATE) < 0) return ;
X 
X/* Set scanning parameters. */
X  if (make_packet('!', 1, 0) < 0) return ;    /* Get scanner model number. */
X  if (make_packet('X', 1, 0) < 0) return ; ;  /* Reset scanning parameters. */
X  if (make_packet('C', 2, DATA_TRANSFER) < 0) return ;
X  if (MODE)
X    {
X      if (make_packet('H', 2, 0) < 0) return ;
X    }
X  else if (make_packet('T', 2, 0) < 0) return ;
X  if (make_packet('G', 2, grain) < 0) return ;         /* Set up grain. */
X  if (make_packet('B', 2, brightness) < 0) return ;    /* Set up brightness. */
X  if (make_packet('K', 2, contrast) < 0) return ;      /* Set up contrast. */
X  if (make_packet('R', 2, resolution+16) < 0) return ; /* Set up resolution. */
X  if (make_frame_packet() < 0) return ;
X  if (make_packet('S', 1, 0) < 0) return ;     /* Send a start scan packet. */ 
X  complete = 0 ;
X  cancel = 0 ;
X  for (;;)
X    {
X 
X#ifdef NO_4.3SELECT
X      readmask = 1 << fd ;
X      SELECT(32, &readmask, (int *) 0,(int *) 0, &timeout) ;
X      if (readmask & (1 << fd))
X#else
X      FD_ZERO(&readmask) ;
X      FD_SET(fd, &readmask) ;
X      SELECT(FD_SETSIZE, &readmask, (fd_set *) 0, (fd_set *) 0, &timeout) ;
X      if (FD_ISSET(fd, &readmask))
X#endif NO_4.3SELECT
X
X        read_rs232() ;
X      else
X        { 
X          if (rsrhold == XOFF) do_handshake(XON) ;
X          if (pkt_started)
X            {
X              c = NAK ;
X              WRITE(fd, &c, 1) ;
X              rsrstate = RSSOR ;
X              pkt_started = 0 ;
X            }
X        }    
X      if (complete || error || cancel) break ;
X    }
X  CLOSE(rf) ;                     /* Close temporary image file. */
X  if (!error)
X    {
X      save_picture() ;            /* Create Sun rasterfile picture. */
X      retval = 0 ;                /* Successful exit - image saved. */
X    }
X  else UNLINK(tempimage) ;
X  CLOSE(fd) ;
X}
X
X
Xget_options(argc, argv)        /* Extract command line options. */
Xint argc ;
Xchar *argv[] ;
X{
X  char next[MAXLINE] ;    /* The next command line parameter. */
X
X  INC ;
X  while (argc > 0)
X    {
X      if (argv[0][0] == '-')
X        switch (argv[0][1])
X          {
X            case 'b' : INC ;                         /* Brightness. */
X                       getparam(next, argv, "-b needs brightness value") ;
X                       brightness = atoi(next) ;
X                       break ;
X            case 'c' : INC ;                         /* Contrast. */
X                       getparam(next, argv, "-c needs contrast value") ;
X                       contrast = atoi(next) ;
X                       break ;
X            case 'd' : INC ;                         /* Data transfer. */
X                       getparam(next, argv, "-d needs data transfer value") ;
X                       switches[DATA_TRANSFER] = atoi(next) ;
X                       break ;
X            case 'f' : INC ;                         /* Frame. */
X                       getparam(next, argv, "-f needs X1 coordinate") ;
X                       framevals[X1] = atoi(next) ;
X                       INC ;
X                       getparam(next, argv, "-f needs Y1 coordinate") ;
X                       framevals[Y1] = atoi(next) ;
X                       INC ;
X                       getparam(next, argv, "-f needs X2 coordinate") ;
X                       framevals[X2] = atoi(next) ;
X                       INC ;
X                       getparam(next, argv, "-f needs Y2 coordinate") ;
X                       framevals[Y2] = atoi(next) ;
X                       break ;
X            case 'g' : INC ;                         /* Grain. */
X                       getparam(next, argv, "-g needs grain value") ;
X                       grain = atoi(next) ;
X                       break ;
X            case 'm' : INC ;                         /* Mode. */
X                       getparam(next, argv, "-m needs mode value") ;
X                       switches[MODE] = atoi(next) ;
X                       break ;
X            case 'p' : INC ;                         /* Picture name. */
X                       getparam(picname, argv, "-p needs picture name") ;
X                       break ;
X            case 'r' : INC ;                         /* Resolution. */
X                       getparam(next, argv, "-r needs resolution value") ;
X                       break ;
X            case 's' : INC ;              /* Speed of RS232 connection. */
X                       getparam(next, argv, "-s needs speed value") ;
X                       switches[BAUD_RATE] = atoi(next) ;
X                       break ;
X            case 't' : INC ;                         /* Tty port. */
X                       getparam(next, argv, "-t needs tty port") ;
X                       switches[SERIAL_PORT] = atoi(next) ;
X                       break ;
X            case 'v' : FPRINTF(stderr, "%s version 1.4.%1d\n",
X                                       progname, PATCHLEVEL) ;
X                       break ;
X            case '?' : usage() ;
X          }
X      INC ;
X    }
X}
X
X
Xgetparam(s, argv, errmes)
Xchar *s, *argv[], *errmes ;
X{
X  if (*argv != NULL && argv[0][0] != '-') STRCPY(s, *argv) ;
X  else
X    { 
X      FPRINTF(stderr,"%s: %s as next argument.\n", progname, errmes) ;
X      exit(5) ;
X    }
X}
X
X
Xinit_rs_port(port, speed)              /* Initialise RS232 port. */
Xint port, speed ;
X{
X  char ttyline[MAXLINE] ;
X  struct sgttyb sgttyb ;
X 
X  if (port) STRCPY(ttyline, "/dev/ttyb") ;
X  else      STRCPY(ttyline, "/dev/ttya") ;
X  if ((fd = open(ttyline,2)) < 0)
X    {
X      retval = 1 ;      /* Cannot open ttyline. */
X      return(-1) ;
X    }
X  GTTY(fd, &sgttyb) ;
X  sgttyb.sg_flags |= RAW ;
X  sgttyb.sg_flags &= ~(ECHO | CRMOD) ;
X  if (speed) sgttyb.sg_ispeed = sgttyb.sg_ospeed = EXTA ;
X  else       sgttyb.sg_ispeed = sgttyb.sg_ospeed = B9600 ;
X  STTY(fd, &sgttyb) ;             /* Implement tty line setup changes. */
X  return(0) ;
X}
X
X
Xmake_frame_packet()        /* Construct and send scanning frame packet. */
X{
X  char cksum ;             /* For creating the packet checksum. */
X  int i ;
X
X  rsdata[0] = '\\' ;       /* Construct packet. */
X  rsdata[1] = 0x80 ;
X  rsdata[2] = 0x00 ;
X  rsdata[3] = 5 ;
X  rsdata[4] = 'F' ;
X  rsdata[5] = framevals[X1] ;
X  rsdata[6] = framevals[Y1] ;
X  rsdata[7] = framevals[X2] ;
X  rsdata[8] = framevals[Y2] ;
X  cksum = 0 ;
X  for (i = 1; i < 9; i++) cksum += rsdata[i] ;
X  rsdata[9] = (~cksum) + 1 ;
X  return(send_packet('F', 10)) ;
X}
X
X
Xmake_header(width, height)       /* Make Sun rasterfile header. */
Xint width, height ;
X{
X  struct rasterfile header ;
X  FILE *hd ;                    /* File descriptor for header file. */
X
X  SPRINTF(temphead, "/usr/tmp/%s.header", mktemp("XXXXXX")) ;
X  if ((hd = fopen(temphead,"w")) == NULL)
X    {
X      retval = 3 ;              /* Can't open raster header file. */
X      return(-1) ;
X    }
X  header.ras_magic = 0x59a66a95 ;        /* Generate rasterfile header. */
X  header.ras_width = width ;
X  header.ras_height = height ;
X  header.ras_depth = 1 ;
X  header.ras_length = width * height ;
X  header.ras_type = RT_STANDARD ;
X  header.ras_maptype = RMT_RAW ;
X  header.ras_maplength = 0 ;
X  FWRITE((char *) &header, sizeof(struct rasterfile), 1, hd) ;
X  FCLOSE(hd) ;
X  return(0) ;
X}
X
X
Xmake_packet(ptype, count, value)   /* Sent a packet to the scanner. */
Xchar ptype, count, value ;
X{
X  char cksum ;                     /* For creating the packet checksum. */
X  int i ;
X  int len ;                        /* Length of this scanner packet. */
X
X  len = count + 5 ;
X  rsdata[0] = '\\' ;               /* Construct packet. */
X  rsdata[1] = 0x80 ;
X  rsdata[2] = 0x00 ;
X  rsdata[3] = count ;
X  rsdata[4] = ptype ;
X  if (count == 2) rsdata[5] = value ;
X  cksum = 0 ;
X  for (i = 1; i < len-1; i++) cksum += rsdata[i] ;
X  rsdata[len-1] = (~cksum) + 1 ;
X  return(send_packet(ptype, len)) ;
X}
X
X
Xopen_temp_file()          /* Open a temporary file for the scanned image. */
X{
X  SPRINTF(tempimage, "/usr/tmp/%s.image", mktemp("XXXXXX")) ;
X  if ((rf = open(tempimage, 2)) < 0)
X    if ((rf = creat(tempimage, 0777)) < 0)
X      {
X        retval = 2 ;   /* Can't open temporary image file. */
X        return(-1) ;
X      }
X  return(0) ;
X}
X
X
Xprocess_packet(ptype)     /* Process RS232 packet received. */
Xchar ptype ;
X{
X  int errorval ;          /* To extract error value. */
X  char outval ;           /* ACK or NAK value to be sent. */
X
X  if (rscksum == cksum)
X    {
X      outval = ACK ;
X      switch (ptype)
X        {
X          case 'D' : if ((rsrtype >> 5) & 1) pic_compressed++ ;
X                     height++ ;
X                     if (!((rsrtype >> 5) & 1)) rsptr = ((rsptr >> 2) << 2) ;
X                     WRITE(rf, from_rs, rsptr) ;
X                     width = rsptr * 8 ;
X                     break ;
X          case 'E' : outval = ETX ;    /* Complete scanning and eject paper. */
X                     WRITE(fd, &outval, 1) ;
X                     complete = 1 ;
X                     break ;
X          case '!' : STRNCPY(scantype, from_rs, rsptr) ;
X                     break ;
X          case '?' : errorval = (from_rs[1] & 0xFF) ;
X                     retval = 100 + errorval ;  /* Scanning error received. */
X                     outval = ETX ;
X                     WRITE(fd, &outval, 1) ;
X                     error = 1 ;
X        }
X    }    
X  else outval = NAK ;
X  WRITE(fd, &outval, 1) ;        /* Send ACK or NAK. */
X  pktdone = 1 ;
X}
X
X
Xread_rs232()      /* Read upto end of next packet. */
X{
X  char c ;        /* Next character read from RS232. */
X  int count ;     /* Number of RS232 characters to read. */
X  int i ;
X
X  IOCTL(fd,(int) FIONREAD,(char *) &count) ;   /* Any data to read. */
X  if (count > MAXREAD) do_handshake(XOFF) ;
X  else if (count < 20 && rsrhold == XOFF) do_handshake(XON) ;
X  if (!count) return ;                         /* NO: exit routine. */
X  for (i = 0; i < count; i++)
X    {
X      READ(fd, &c, 1) ;                        /* Read next character. */
X      if (rsrstate == RSSOR && (c == ACK || c == NAK)) rswstate = c ;
X      else
X        switch (rsrstate)
X          {
X            case RSSOR   : rscksum = 0 ;
X                           if (c == SOR) rsrstate = RSRTYPE ;
X                           break ;
X            case RSRTYPE : rsrtype = c ;
X                           rscksum += c ;
X                           cntbytes = 0 ;
X                           rscnt = 0 ;
X                           rsrstate = RSCOUNT ;
X                           break ;
X            case RSCOUNT : rscksum += c ;
X                           rscnt = rscnt*256 + c ;
X                           if (++cntbytes == 2)
X                             {
X                               rsrstate = RSDATA ;
X                               rsptr = 0 ;
X                             }
X                           pkt_started = 1 ;
X                           break ;
X            case RSDATA  : from_rs[rsptr++] = c ;  /* Save data character. */
X                           rscksum += c ;
X                           if (!--rscnt) rsrstate = RSCKSUM ;
X                           break ;
X            case RSCKSUM : rscksum = (~rscksum) + 1 ;
X                           cksum = c ;
X                           if (rsrtype >> 7) process_packet(from_rs[0]) ;
X                           else process_packet('D') ;
X                           pkt_started = 0 ;
X                           rsrstate = RSSOR ;
X                           return ;
X          }
X    }
X}
X
X
Xsave_picture()    /* Combine header file and image to make a Sun rasterfile. */
X{
X  char line[MAXLINE] ;          /* For constructing the system command. */
X
X  if (pic_compressed)
X    {
X      initialise_white("white.codes") ;
X      initialise_black("black.codes") ;
X      uncompress(tempimage) ;
X    }
X  else
X    { 
X      if (!make_header(width, height))   /* Write out Sun rasterfile header. */
X        {
X          SPRINTF(line, "cat %s %s > %s", temphead, tempimage, picname) ;
X          SYSTEM(line) ;                 /* Create Sun rasterfile. */
X          UNLINK(temphead) ;             /* Remove header file. */
X        }
X      UNLINK(tempimage) ;                /* Remove image file. */
X    }
X}
X
X
Xsend_packet(ptype, len)
Xchar ptype,len ;
X{
X  int done ;        /* Packet read or ACK/NAK found. */
X  int i ;
X
X  for (i = 0; i < MAXRETRIES; i++)
X    {
X      WRITE(fd, rsdata, len) ;
X      rswstate = NOANSWER ;
X      pktdone = 0 ;
X      done = 0 ;
X      do
X        {
X#ifdef NO_4.3SELECT
X          readmask = 1 << fd ;
X          SELECT(32, &readmask, (int *) 0, (int *) 0, &timeout) ;
X          if (readmask & (1 << fd))
X#else
X          FD_ZERO(&readmask) ;
X          FD_SET(fd, &readmask) ;
X          SELECT(FD_SETSIZE, &readmask, (fd_set *) 0, (fd_set *) 0, &timeout) ;
X          if (FD_ISSET(fd, &readmask))
X#endif NO_4.3SELECT
X            {
X              read_rs232() ;
X              switch (ptype)
X                {
X                  case '!' : if (pktdone) done = 1 ;
X                             break ;
X                  default  : if (rswstate == ACK || rswstate == NAK) done = 1 ;
X                }
X              if (done) break ;
X            }
X          else break ;
X        }
X      while (!done) ;
X      if (rswstate == ACK) return(0) ;
X    }
X  retval = 4 ;   /* Scanner not responding. Aborting this scan. */
X  CLOSE(rf) ;
X  return(-1) ;
X}
X
X
Xset_signals()   /* Setup a signal handler for a range of signals. */
X{
X  SIGNAL(SIGHUP,  do_exit) ;
X  SIGNAL(SIGQUIT, do_exit) ;
X  SIGNAL(SIGILL,  do_exit) ;
X  SIGNAL(SIGTRAP, do_exit) ;
X  SIGNAL(SIGIOT,  do_exit) ;
X  SIGNAL(SIGEMT,  do_exit) ;
X  SIGNAL(SIGFPE,  do_exit) ;
X  SIGNAL(SIGBUS,  do_exit) ;
X  SIGNAL(SIGSEGV, do_exit) ;
X}
X
X
Xusage()
X{
X  FPRINTF(stderr, "Usage: %s: [-b brightness] [-c contrast] ", progname) ;
X  FPRINTF(stderr, "[-d] [-f x1 y1 x2 y2] [-g grain] [-m] [-p picname]\n") ;
X  FPRINTF(stderr, "[-s] [-t] [-v] [-?] [-Wi] [-Wp x y] [-WP x y]\n") ;
X  exit(5) ;
X}
END_OF_FILE
if test 19805 -ne `wc -c <'scantool/scan.c'`; then
    echo shar: \"'scantool/scan.c'\" unpacked with wrong size!
fi
# end of 'scantool/scan.c'
fi
if test -f 'scantool/sunview.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'scantool/sunview.c'\"
else
echo shar: Extracting \"'scantool/sunview.c'\" \(13868 characters\)
sed "s/^X//" >'scantool/sunview.c' <<'END_OF_FILE'
X 
X/*  @(#)sunview.c 1.4 90/04/04
X *
X *  SunView dependent graphics routines used by scantool.
X *
X *  Copyright (c) Rich Burridge.
X *                Sun Microsystems, Australia - All rights reserved.
X *
X *  Permission is given to distribute these sources, as long as the
X *  copyright messages are not removed, and no monies are exchanged.
X *
X *  No responsibility is taken for any errors or inaccuracies inherent
X *  either to the comments or the code of this program, but if
X *  reported to me, then an attempt will be made to fix them.
X */
X
X#include <stdio.h>
X#include <sys/fcntl.h>
X#include <sys/wait.h>
X#include <sys/time.h>
X#include <sys/resource.h>
X#include "scantool.h"
X#include "images.h"
X#include "scantool_extern.h"
X#include <suntool/sunview.h>
X#include <suntool/canvas.h>
X
X#define  MENU_SET                       (void) menu_set
X#define  NOTIFY_DISPATCH                (void) notify_dispatch
X#define  NOTIFY_INTERPOSE_DESTROY_FUNC  (void) notify_interpose_destroy_func
X#define  NOTIFY_INTERPOSE_EVENT_FUNC    (void) notify_interpose_event_func
X#define  NOTIFY_SET_WAIT3_FUNC          (void) notify_set_wait3_func
X#define  PR_DESTROY                     (void) pr_destroy
X#define  PW_REPLROP                     (void) pw_replrop
X#define  PW_ROP                         (void) pw_rop
X#define  PW_TEXT                        (void) pw_text
X#define  PW_TTEXT                       (void) pw_ttext
X#define  PW_VECTOR                      (void) pw_vector
X#define  PW_WRITEBACKGROUND             (void) pw_writebackground
X#define  WINDOW_READ_EVENT              (void) window_read_event
X#define  WINDOW_SET                     (void) window_set
X
X/* Fonts used by scantool. */
X#define  BOLD_FONT      "/usr/lib/fonts/fixedwidthfonts/screen.b.14"
X#define  NORMAL_FONT    "/usr/lib/fonts/fixedwidthfonts/screen.r.14"
X
Xstruct pixfont *open_font() ;
Xvoid repaint_show_canvas() ;
X
XCanvas canvas, show_canvas ;
XCursor cursor[MAXCURSORS] ;
XEvent *cur_event ;
XFrame base_frame, show_frame ;
XIcon scantool_icon ;
XMenu menus[MAXMENUS] ;
XNotify_value destroy(), handle_resize() ;
XPixfont *font[MAXFONTS] ;
XPixrect *images[MAXIMAGES] ;
XPixrect *spr ;
XPixwin *spw, *wpw ;
X
Xint firsttime ;      /* Set if we haven't resized the window yet. */
Xint init_height ;    /* Initial height of the scantool window. */
Xint init_width ;     /* Initial width of the scantool window. */
X
Xstruct rasterfile hdr ;
X
Xmpr_static(grey_pr,          16, 16, 1, grey_image) ;
Xmpr_static(icon_pr,          64, 64, 1, icon_image) ;
Xmpr_static(exclaim_pr,       64, 64, 1, exclaim_image) ;
Xmpr_static(button_normal_pr, 64, 64, 1, button_normal_image) ;
Xmpr_static(button_invert_pr, 64, 64, 1, button_invert_image) ;
Xmpr_static(switch_normal_pr, 16, 16, 1, switch_normal_image) ;
Xmpr_static(switch_invert_pr, 16, 16, 1, switch_invert_image) ;
Xmpr_static(main_cursor_pr,   16, 16, 1, main_cursor_array) ;
Xmpr_static(hour_cursor_pr,   16, 16, 1, hour_cursor_array) ;
Xmpr_static(help_cursor_pr,   16, 16, 1, help_cursor_array) ;
Xmpr_static(frame_cursor_pr,  16, 16, 1, frame_cursor_array) ;
X 
X
X/*ARGSUSED*/
Xvoid
Xcanvas_proc(canvas, event)
XCanvas canvas ;
XEvent *event ;
X{
X  cur_event = event ;
X  handle_event() ;       /* Determine what kind of event it is. */
X  process_event() ;      /* And process it. */
X}
X
Xcreate_menu(mtype, title, values)    /* Create popup menus for cycle items. */
Xenum menu_type mtype ;
Xchar *title, *values[] ;
X{
X  int i = 0 ;
X  int more = 1 ;   /* Cleared when current menu is complete.*/
X
X  menus[(int) mtype] = menu_create(MENU_TITLE_ITEM, title,
X                                   MENU_FONT,       font[(int) NFONT],
X                                   0) ;
X  do
X    {
X      if (values[i] != NULL)
X        MENU_SET(menus[(int) mtype], MENU_STRING_ITEM, values[i], i+1, 0) ;
X      else more = 0 ;
X      i++ ;
X    }
X  while (more) ;
X}
X
X/*ARGSUSED*/
XNotify_value
Xdestroy(client, status)
XNotify_client client ;
XDestroy_status status ;
X{
X  stop_scan() ;        /* Stop the current scan (if there is one). */
X  exit(0) ;
X}
X
Xdisplay_menu(menuno)
Xenum menu_type menuno ;
X{
X  return((int) menu_show(menus[(int) menuno], canvas,
X                         canvas_window_event(canvas, cur_event), 0)) ;
X}
X
Xdraw_area(x, y, width, height, op)
Xint x, y, width, height ;
Xenum op_type op ;
X{
X  PW_WRITEBACKGROUND(wpw, x, y, width, height, ops[(int) op]) ;
X}
X
Xdraw_image(x, y, width, height, image)
Xint x, y, width, height ;
Xenum image_type image ;
X{
X  PW_ROP(wpw, x, y, width, height, PIX_SRC, images[(int) image], 0, 0) ;
X}
X
Xdraw_line(x1, y1, x2, y2, op)
Xint x1, y1, x2, y2 ;
Xenum op_type op ;
X{
X  PW_VECTOR(wpw, x1, y1, x2, y2, ops[(int) op], 1) ;
X}
X
Xdraw_text(x, y, stencil, ftype, str)
Xint x, y ;
Xenum sten_type stencil ;
Xenum font_type ftype ;
Xchar *str ;
X{
X  switch (stencil)
X    {
X      case STEN_OFF : PW_TEXT(wpw,  x, y, PIX_SRC, font[(int) ftype], str) ;
X                      break ;
X      case STEN_ON  : PW_TTEXT(wpw, x, y, PIX_SET, font[(int) ftype], str) ;
X                      break ;
X      case STEN_INV : PW_TTEXT(wpw, x, y, PIX_CLR, font[(int) ftype], str) ;
X    }
X}
X
Xget_event()       /* Get the next SunView event. */
X{
X  WINDOW_READ_EVENT(canvas, cur_event) ;
X}
X
Xget_strwidth(ftype, str)    /* Get width in pixels of string value. */
Xenum font_type ftype ;
Xchar *str ;
X{
X  struct pr_size size ;
X
X  size = pf_textwidth(strlen(str), font[(int) ftype], str) ;
X  return(size.x) ;
X}
X
Xgrey_area(x, y, width, height)
X{
X  PW_REPLROP(wpw, x, y, width, height, PIX_SRC, &grey_pr, 0, 0) ;
X}
X
Xhandle_event()        /* Work out what kind of event this is. */
X{
X  curx = event_x(cur_event) ;
X  cury = event_y(cur_event) ;
X  cur_ch = event_id(cur_event) ;
X
X  if (event_is_button(cur_event) && event_is_down(cur_event))
X    {
X           if (cur_ch == MS_LEFT)     type = LEFT_DOWN ;
X      else if (cur_ch == MS_MIDDLE)   type = MIDDLE_DOWN ;
X      else if (cur_ch == MS_RIGHT)    type = RIGHT_DOWN ;
X    }
X  else if (event_is_button(cur_event) && event_is_up(cur_event))
X    {
X           if (cur_ch == MS_LEFT)     type = LEFT_UP ;
X      else if (cur_ch == MS_MIDDLE)   type = MIDDLE_UP ;
X      else if (cur_ch == MS_RIGHT)    type = RIGHT_UP ;
X    }
X  else if (event_is_ascii(cur_event)) type = KEYBOARD ;
X  else if (cur_ch == LOC_MOVE)        type = MOUSE_MOVE ;
X  else if (cur_ch == LOC_DRAG)        type = MOUSE_DRAG ;
X  else if (cur_ch == WIN_REPAINT)     type = REPAINT ;
X  else                                type = IGNORE ;
X}
X
XNotify_value
Xhandle_resize(frame, event, arg, type)
XFrame frame ;
XEvent *event ;
XNotify_arg arg ;
XNotify_event_type type ;
X{
X  Notify_value value ;
X  Rect *r ;
X
X  value = notify_next_event_func(frame, (Notify_event) event, arg, type) ;
X  if (event_id(event) == WIN_RESIZE)
X    if (firsttime)
X      {
X        init_width = (int) window_get(base_frame, WIN_WIDTH) ;
X        init_height = (int) window_get(base_frame, WIN_HEIGHT) ;
X        firsttime = 0 ;
X      }
X    else
X      {
X        r = (Rect *) LINT_CAST(window_get(frame, WIN_RECT)) ;
X        r->r_width  = init_width ;
X        r->r_height = init_height ;
X        WINDOW_SET(frame, FRAME_OPEN_RECT, r, 0) ;
X        do_repaint() ;
X      }   
X  return(value) ;
X}
X
Xinit_fonts()
X{
X  font[(int) NFONT] = open_font(NORMAL_FONT) ;
X  font_width = font[(int) NFONT]->pf_defaultsize.x ;
X  font[(int) BFONT] = open_font(BOLD_FONT) ;
X}
X
Xinit_ws_type()
X{
X  ops[(int) GSET] = PIX_SET ;
X  ops[(int) GCLR] = PIX_CLR ;
X  ops[(int) GXOR] = PIX_SRC ^ PIX_DST ;
X  ops[(int) GSRC] = PIX_SRC ;
X  ops[(int) GOR]  = PIX_SRC | PIX_DST ;
X  ops[(int) GNOT] = PIX_NOT(PIX_DST) ;
X
X  firsttime = 1 ;
X}
X
Xmake_frames(argc, argv)
Xint argc ;
Xchar *argv[] ;
X{
X  scantool_icon = icon_create(ICON_IMAGE, &icon_pr, 0) ;
X  base_frame = window_create((Window) 0,           FRAME,
X                             FRAME_ICON,           scantool_icon,
X                             FRAME_LABEL,          progname,
X                             FRAME_EMBOLDEN_LABEL, TRUE,
X                             FRAME_ARGS,           argc,argv,
X                             0) ;
X
X  show_frame = window_create(base_frame,       FRAME,
X                             FRAME_SHOW_LABEL, TRUE,
X                             WIN_WIDTH,        650,
X                             WIN_HEIGHT,       900,
X                             WIN_X,            0,
X                             WIN_Y,            0,
X                             WIN_SHOW,         FALSE,
X                             0) ;
X  NOTIFY_INTERPOSE_EVENT_FUNC(base_frame, handle_resize, NOTIFY_SAFE) ;
X}
X
Xmake_subframes()
X{
X  cursor[(int) FRAME_CUR] = cursor_create(CURSOR_IMAGE, &frame_cursor_pr,
X                                          CURSOR_XHOT,  7,
X                                          CURSOR_YHOT,  7,
X                                          0) ;
X  cursor[(int) HELP_CUR]  = cursor_create(CURSOR_IMAGE, &help_cursor_pr, 0) ;
X  cursor[(int) HOUR_CUR]  = cursor_create(CURSOR_IMAGE, &hour_cursor_pr, 0) ;
X  cursor[(int) MAIN_CUR]  = cursor_create(CURSOR_IMAGE, &main_cursor_pr, 0) ;
X 
X  canvas = window_create(base_frame, CANVAS,
X                         WIN_EVENT_PROC,      canvas_proc,
X                         WIN_CURSOR,          cursor[(int) MAIN_CUR],
X                         WIN_WIDTH,           SCAN_WIDTH,
X                         WIN_HEIGHT,          SCAN_HEIGHT,
X                         CANVAS_RETAINED,     FALSE,
X                         CANVAS_FIXED_IMAGE,  FALSE,
X                         0) ;
X  WINDOW_SET(canvas, WIN_CONSUME_KBD_EVENTS, WIN_ASCII_EVENTS,
X                     WIN_UP_EVENTS, 0, 0) ;
X  WINDOW_SET(canvas, WIN_CONSUME_PICK_EVENTS, LOC_DRAG, LOC_MOVE, 0, 0) ;
X  wpw = canvas_pixwin(canvas) ;
X
X  show_canvas = window_create(show_frame, CANVAS,
X                              CANVAS_REPAINT_PROC, repaint_show_canvas,
X                              0) ;
X  spw = canvas_pixwin(show_canvas) ;
X  spr = NULL ;
X
X  images[(int) B_NORMAL]      = &button_normal_pr ;
X  images[(int) B_INVERT]      = &button_invert_pr ;
X  images[(int) S_NORMAL]      = &switch_normal_pr ;
X  images[(int) S_INVERT]      = &switch_invert_pr ;
X  images[(int) EXCLAIM_IMAGE] = &exclaim_pr ;
X}
X
XPixfont *
Xopen_font(fontname)
Xchar *fontname ;
X{
X  Pixfont *f ;
X
X  if ((f = pf_open(fontname)) == NULL)
X    if ((f = pf_default()) == NULL)
X      {
X        perror("couldn't get the default font.") ;
X        exit(1) ;
X      }
X  return(f) ;
X}
X
X/*ARGSUSED*/
Xvoid
Xrepaint_show_canvas(canvas, pw, repaint_area)     /* Show current picture. */
XCanvas canvas ;
XPixwin *pw ;
XRectlist *repaint_area ;
X{
X  PW_ROP(pw, 0, 0, hdr.ras_width, hdr.ras_height, PIX_SRC, spr, 0, 0) ;
X}
X
Xset_cursor(ctype)
Xenum cur_type ctype ;
X{
X  WINDOW_SET(canvas, WIN_CURSOR, cursor[(int) ctype], 0) ;
X}
X
Xshow()      /* Display scanned image. */
X{
X  Rect *temprect ;
X  char errmes[MAXLINE] ;
X  int fd ;
X
X  showing = 1 ;
X  make_button(SCAN_WIDTH-150, 4*SWITCH_HEIGHT+100, "Show", B_INVERT) ;
X  if (spr) PR_DESTROY(spr) ;
X  if ((fd = open(picname, O_RDONLY | O_NDELAY, 0644)) == -1)
X    {
X      SPRINTF(errmes, "Cannot open %s.", picname) ;
X      make_display(errmes) ;
X    }
X  else
X    { 
X      READ(fd, (char *) &hdr, sizeof(struct rasterfile)) ;
X      if (hdr.ras_maplength)
X        {
X          make_display("Color rasterfiles currently not supported.") ;
X          return ;
X        }
X      spr = mem_create(hdr.ras_width, hdr.ras_height, hdr.ras_depth) ;
X      READ(fd, (char *) (mpr_d(spr)->md_image),
X           hdr.ras_width * hdr.ras_height) ;
X      CLOSE(fd) ;
X      temprect = (Rect *) LINT_CAST(window_get(show_frame, FRAME_OPEN_RECT)) ;
X      temprect->r_left = temprect->r_top = 0 ;
X      temprect->r_height = hdr.ras_height ;
X      temprect->r_width = hdr.ras_width ;
X      WINDOW_SET(show_frame, FRAME_OPEN_RECT, temprect, 0) ;
X      WINDOW_SET(show_frame, FRAME_LABEL, picname, 0) ;
X      WINDOW_SET(show_frame, WIN_SHOW, TRUE, 0) ;
X    }
X  make_button(SCAN_WIDTH-150, 4*SWITCH_HEIGHT+100, "Show", B_NORMAL) ;
X  showing = 0 ;
X}
X
Xstart_tool()
X{
X  window_fit(base_frame) ;
X  NOTIFY_INTERPOSE_DESTROY_FUNC(base_frame, destroy) ;
X  window_main_loop(base_frame) ;
X}
X
X/*ARGSUSED*/
XNotify_value
Xwait_child(frame, pid, status, rusage)
XWindow frame ;
Xint pid ;
Xunion wait *status ;
Xstruct rusage *rusage ;
X{
X  char output[MAXLINE] ;
X  int high, low ;
X
X  if (WIFSTOPPED(*status)) return (NOTIFY_IGNORED) ;
X
X  high = (status->w_status & 0xFF00) >> 8 ;
X  low = status->w_status & 0xFF ;
X  if (low) SPRINTF(output, "Scan: terminated with signal %1d", (low & 0x3F)) ;
X  else
X    {
X      switch (high)
X        {
X          case 0  : SPRINTF(output, "Scan: successful. %s saved",
X                                     picname) ;
X                    break ;
X          case 1  : SPRINTF(output, "Scan: cannot open tty port %c",
X                                     switches[SERIAL_PORT] + 'A') ;
X                    break ;
X          case 2  : SPRINTF(output, "Scan: cannot open temporary image file") ;
X                    break ;
X          case 3  : SPRINTF(output, "Scan: cannot open raster header file") ;
X                    break ;
X          case 4  : SPRINTF(output, "Scan: scanner not responding; aborting") ;
X                    break ;
X          case 5  : SPRINTF(output, "Scan: invalid command line argument") ;
X                    break ;
X          default : if (high >= 100 && high < 200)
X                      SPRINTF(output, "Scan: scanner error %1d; aborting",
X                                       high - 100) ;
X                    else
X                      SPRINTF(output, "Scan: terminated with signal %1d",
X                                       high - 200) ;
X        }
X    }
X  make_display(output) ;
X  make_button(SCAN_WIDTH-150, 4*SWITCH_HEIGHT+20, "Scan",   B_NORMAL) ;
X  make_button(SCAN_WIDTH-150, 4*SWITCH_HEIGHT+60, "Cancel", B_NORMAL) ;
X  scanning = 0 ;
X  return (NOTIFY_DONE) ;
X}
X
Xwait_on_child(pid)      /* Wait on child scan process. */
Xint pid ;
X{
X  NOTIFY_SET_WAIT3_FUNC(base_frame, wait_child, pid) ;
X}
END_OF_FILE
if test 13868 -ne `wc -c <'scantool/sunview.c'`; then
    echo shar: \"'scantool/sunview.c'\" unpacked with wrong size!
fi
# end of 'scantool/sunview.c'
fi
if test -f 'scantool/switch.normal.cursor' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'scantool/switch.normal.cursor'\"
else
echo shar: Extracting \"'scantool/switch.normal.cursor'\" \(193 characters\)
sed "s/^X//" >'scantool/switch.normal.cursor' <<'END_OF_FILE'
X/* Format_version=1, Width=16, Height=16, Depth=1, Valid_bits_per_item=16
X */
X	0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0xFFE0,0x8020,
X	0x8020,0x8020,0x8020,0x8020,0x8020,0x8020,0x8020,0xFFE0
END_OF_FILE
if test 193 -ne `wc -c <'scantool/switch.normal.cursor'`; then
    echo shar: \"'scantool/switch.normal.cursor'\" unpacked with wrong size!
fi
# end of 'scantool/switch.normal.cursor'
fi
if test -f 'scantool/xview.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'scantool/xview.c'\"
else
echo shar: Extracting \"'scantool/xview.c'\" \(16921 characters\)
sed "s/^X//" >'scantool/xview.c' <<'END_OF_FILE'
X
X/*  @(#)xview.c 1.5 90/04/10
X *
X *  XView dependent graphics routines used by scantool.
X *
X *  Copyright (c) Rich Burridge.
X *                Sun Microsystems, Australia - All rights reserved.
X *
X *  Permission is given to distribute these sources, as long as the
X *  copyright messages are not removed, and no monies are exchanged.
X *
X *  No responsibility is taken for any errors or inaccuracies inherent
X *  either to the comments or the code of this program, but if
X *  reported to me, then an attempt will be made to fix them.
X */
X
X#include <stdio.h>
X#include <sys/fcntl.h>
X#include <sys/wait.h>
X#include <sys/time.h>
X#include <sys/resource.h>
X#include "scantool.h"
X#include "scantool_extern.h"
X#include "images.h"
X#include <rasterfile.h>
X#include <xview/xview.h>
X#include <xview/canvas.h>
X#include <xview/font.h>
X#include <xview/fullscreen.h>
X#include <xview/cursor.h>
X#include <xview/svrimage.h>
X#include <X11/Xlib.h>
X
X#define  NOTIFY_INTERPOSE_DESTROY_FUNC  (void) notify_interpose_destroy_func
X#define  NOTIFY_SET_SIGNAL_FUNC         (void) notify_set_signal_func
X#define  NOTIFY_SET_WAIT3_FUNC          (void) notify_set_wait3_func
X#define  PR_DESTROY                     (void) pr_destroy
X#define  PW_WRITE                       (void) pw_write
X#define  XV_INPUT_READEVENT             (void) xv_input_readevent
X#define  XV_SET                         (void) xv_set
X
X#define  BOLDFONT    "lucidasanstypewriter-bold-12"
X#define  DEFFONT     "fixed"
X#define  NORMALFONT  "lucidasanstypewriter-12"
X
Xint menu_proc() ;
Xvoid repaint_show_canvas() ;
X
XCanvas canvas, show_canvas ;
XCanvas_paint_window spw, wpw ;
XEvent *cur_event ;
XFrame base_frame, show_frame ;
XFullscreen fs ;
XIcon scantool_icon ;
XMenu menus[MAXMENUS] ;
XNotify_value destroy() ;
XPixrect *spr ;
XServer_image frame_cursor_pr, help_cursor_pr, hour_cursor_pr, main_cursor_pr ;
XServer_image make_server_image() ;
X
XXv_cursor cursor[MAXCURSORS] ;
X
XDisplay *dpy ;                  /* Display id of scantool frame. */
XDrawable xid ;                  /* Xid for scantool canvas. */
XDrawable grey_pr ;
XDrawable images[MAXIMAGES] ;    /* Xids for various graphical images. */
XGC backgc ;                     /* Graphics context for pw_writebackground. */
XGC gc ;                         /* Graphics context for text and lines. */
XGC ropgc ;                      /* Graphics context for rops. */
XWindow root ;
XXFontStruct *font[MAXFONTS] ;   /* Xlib handles to the fonts. */
XXGCValues gc_val ;              /* Used to setup graphics context values. */
Xint gc_flags ;                  /* Used to set up graphics context flags. */
Xint screen ;                    /* Default graphics display screen. */
Xunsigned long backgnd ;         /* Default background color. */
Xunsigned long foregnd ;         /* Default foreground color. */
Xunsigned long gc_mask ;         /* Mask for setting graphic context values. */
X
Xenum menu_type cur_menu ;     /* Current menu type being processed. */
X
Xint init_height ;             /* Initial height of the scantool window. */
Xint init_width ;              /* Initial width of the scantool window. */
Xint started ;                 /* Kludge to correct handle repaints. */
X
Xstruct rasterfile hdr ;
X
Xmpr_static(icon_pr, 64, 64, 1, icon_image) ;
X
X/*ARGSUSED*/
Xvoid
Xcanvas_proc(canvas, event)
XCanvas canvas ;
XEvent *event ;
X{
X  if (!started) return ;
X  cur_event = event ;
X  handle_event() ;       /* Determine what kind of event it is. */
X  process_event() ;      /* And process it. */
X}
X
Xcreate_menu(mtype, title, values)    /* Create popup menus for cycle items. */
Xenum menu_type mtype ;
Xchar *title, *values[] ;
X{
X  int i = 0 ;
X  int more = 1 ;   /* Cleared when current menu is complete.*/
X
X  menus[(int) mtype] = xv_create(XV_NULL,          MENU_COMMAND_MENU,
X                                 MENU_NOTIFY_PROC, menu_proc,
X                                 MENU_TITLE_ITEM,  title,
X                                 0) ;
X  do
X    {
X      if (values[i] != NULL)
X        XV_SET(menus[(int) mtype], MENU_STRING_ITEM, values[i], i+1, 0) ;
X      else more = 0 ;
X      i++ ;
X    }
X  while (more) ;
X}
X
XNotify_value
Xdestroy(client, status)
XNotify_client client ;
XDestroy_status status ;
X{
X  stop_scan() ;        /* Stop the current scan (if there is one). */
X  exit(0) ;
X}
X
Xdisplay_menu(menuno)
Xenum menu_type menuno ;
X{
X  cur_menu = menuno ;
X  menu_show(menus[(int) menuno], canvas, cur_event, 0) ;
X  return(0) ;
X}
X
Xdraw_area(x, y, width, height, op)
Xint x, y, width, height ;
Xenum op_type op ;
X{
X  if (op == GNOT)
X    {
X      XSetFunction(dpy, gc, GXcopyInverted) ;
X      XCopyArea(dpy, xid, xid, gc, x, y, width, height, x, y) ;
X    }
X  else
X    {
X      XSetFunction(dpy, backgc, ops[(int) op]) ;
X      XFillRectangle(dpy, xid, backgc, x, y, width, height) ;
X    }
X}
X
Xdraw_image(x, y, width, height, image)
Xint x, y, width, height ;
Xenum image_type image ;
X{
X  gc_mask = GCStipple | GCTileStipXOrigin | GCTileStipYOrigin ;
X  gc_val.stipple = images[(int) image] ;
X  gc_val.ts_x_origin = x ;
X  gc_val.ts_y_origin = y ;
X  XChangeGC(dpy, ropgc, gc_mask, &gc_val) ;
X  XFillRectangle(dpy, xid, ropgc, x, y, width, height) ;
X}
X
Xdraw_line(x1, y1, x2, y2, op)
Xint x1, y1, x2, y2 ;
Xenum op_type op ;
X{
X  gc_val.foreground = foregnd ;
X  gc_val.function = ops[(int) op] ;
X  XChangeGC(dpy, gc, GCForeground | GCFunction, &gc_val) ;
X  XDrawLine(dpy, xid, gc, x1, y1, x2, y2) ;
X}
X
X/*ARGSUSED*/
Xdraw_text(x, y, stencil, ftype, str)
Xint x, y ;
Xenum sten_type stencil ;
Xenum font_type ftype ;
Xchar *str ;
X{
X  gc_val.foreground = foregnd ;
X  gc_val.font = font[(int) ftype]->fid ;
X  if (stencil == STEN_INV) gc_val.function = GXcopyInverted ;
X  else                     gc_val.function = GXcopy ;
X  XChangeGC(dpy, gc, GCFont | GCForeground | GCFunction, &gc_val) ;
X  XDrawString(dpy, xid, gc, x, y, str, strlen(str)) ;
X}
X
Xget_event()       /* Get the next XView event. */
X{
X  XV_INPUT_READEVENT(wpw, cur_event, 1, 0, NULL) ;
X  if (event_is_button(cur_event))
X    if (event_is_down(cur_event))
X      fs = xv_create(wpw, FULLSCREEN,
X                     WIN_CONSUME_EVENTS,
X                       WIN_MOUSE_BUTTONS, LOC_DRAG, 0,
X                     0) ;
X    else if (event_is_up(cur_event)) xv_destroy(fs) ;
X}
X
XXFontStruct *
Xget_font(name)
Xchar *name ;
X{
X  XFontStruct *f ;
X 
X  if (!(f = XLoadQueryFont(dpy, name)))
X    if (!(f = XLoadQueryFont(dpy, DEFFONT)))
X      {
X        FPRINTF(stderr, "%s: couldn't get the default font.", progname) ;
X        exit(1) ;
X      }
X  return(f) ;
X}
X
Xget_strwidth(ftype, str)    /* Get width in pixels of string value. */
Xenum font_type ftype ;
Xchar *str ;
X{
X  return(XTextWidth(font[(int) ftype], str, strlen(str))) ;
X}
X
Xgrey_area(x, y, width, height)
X{
X  gc_mask = GCStipple | GCTileStipXOrigin | GCTileStipYOrigin ;
X  gc_val.stipple = grey_pr ;
X  gc_val.ts_x_origin = x % 16 ;
X  gc_val.ts_y_origin = y % 16 ;
X  XChangeGC(dpy, ropgc, gc_mask, &gc_val) ;
X  XFillRectangle(dpy, xid, ropgc, x, y, width, height) ;
X}
X
Xhandle_event()        /* Work out what kind of event this is. */
X{
X  curx = event_x(cur_event) ;
X  cury = event_y(cur_event) ;
X  cur_ch = event_id(cur_event) ;
X
X       if (cur_ch == LOC_WINENTER)   win_set_kbd_focus(canvas, xid) ;
X  else if (cur_ch == WIN_REPAINT)    type = REPAINT ;
X  else if (cur_ch == LOC_MOVE)       type = MOUSE_MOVE ;
X  else if (cur_ch == LOC_DRAG)       type = MOUSE_DRAG ;
X  else if (event_is_button(cur_event) && event_is_down(cur_event))
X    {
X           if (cur_ch == MS_LEFT)    type = LEFT_DOWN ;
X      else if (cur_ch == MS_MIDDLE)  type = MIDDLE_DOWN ;
X      else if (cur_ch == MS_RIGHT)   type = RIGHT_DOWN ;
X    }
X  else if (event_is_button(cur_event) && event_is_up(cur_event))
X    {
X           if (cur_ch == MS_LEFT)    type = LEFT_UP ;
X      else if (cur_ch == MS_MIDDLE)  type = MIDDLE_UP ;
X      else if (cur_ch == MS_RIGHT)   type = RIGHT_UP ;
X    }
X  else if (event_is_ascii(cur_event) &&
X           event_is_down(cur_event)) type = KEYBOARD ;
X  else                               type = IGNORE ;
X}
X
Xinit_fonts()
X{
X  font[(int) NFONT] = get_font(NORMALFONT) ;
X  font_width = font[(int) NFONT]->max_bounds.rbearing -
X               font[(int) NFONT]->min_bounds.lbearing ;
X  font[(int) BFONT] = get_font(BOLDFONT) ;
X}
X
Xinit_ws_type()
X{
X  ops[(int) GSET] = GXset ;
X  ops[(int) GCLR] = GXclear ;
X  ops[(int) GXOR] = GXxor ;
X  ops[(int) GSRC] = GXcopy ;
X  ops[(int) GOR]  = GXor ;
X  ops[(int) GNOT] = GXcopyInverted ;
X
X  started = 0 ;      /* Kludge to correctly handle repaints. */
X}
X
Xmake_frames(argc, argv)
Xint argc ;
Xchar *argv[] ;
X{
X  xv_init(XV_INIT_ARGS, argc, argv, 0) ;
X  scantool_icon = xv_create(XV_NULL, ICON,
X                            ICON_IMAGE, &icon_pr,
X                            0) ;
X  base_frame = xv_create(XV_NULL,                     FRAME,
X                         FRAME_ICON,                  scantool_icon,
X                         FRAME_LABEL,                 progname,
X                         FRAME_SHOW_RESIZE_CORNER,    FALSE,
X                         0) ;
X
X  show_frame = xv_create(base_frame, FRAME,
X                         FRAME_SHOW_LABEL, TRUE,
X                         XV_WIDTH,         650,
X                         XV_HEIGHT,        900,
X                         XV_X,             0,
X                         XV_Y,             0,
X                         XV_SHOW,          FALSE,
X                         0) ;
X}
X
Xmake_subframes()
X{
X  canvas = xv_create(base_frame,         CANVAS,
X                     CANVAS_RETAINED,    FALSE,
X                     OPENWIN_AUTO_CLEAR, FALSE,
X                     XV_WIDTH,           SCAN_WIDTH,
X                     XV_HEIGHT,          SCAN_HEIGHT,
X                     CANVAS_PAINTWINDOW_ATTRS,
X                       WIN_CONSUME_EVENTS,
X                         MS_LEFT, MS_MIDDLE, MS_RIGHT,
X                         WIN_ASCII_EVENTS, KBD_USE, KBD_DONE,
X                         LOC_WINENTER, LOC_WINEXIT, LOC_DRAG, LOC_MOVE,
X                         WIN_LEFT_KEYS, WIN_TOP_KEYS, WIN_RIGHT_KEYS,
X                         WIN_REPAINT,
X                       0,
X                       WIN_EVENT_PROC,   canvas_proc,
X                       0,
X                     0) ;
X  wpw = canvas_paint_window(canvas) ;
X 
X  dpy = (Display *) xv_get(base_frame, XV_DISPLAY) ;
X  xid = (Drawable) xv_get(wpw, XV_XID) ;
X 
X  screen = DefaultScreen(dpy) ;
X  root = RootWindow(dpy, screen) ;
X  foregnd = BlackPixel(dpy, screen) ;
X  backgnd = WhitePixel(dpy, screen) ;
X 
X  gc_mask = GCForeground | GCBackground | GCGraphicsExposures ;
X  gc_val.foreground = foregnd ;
X  gc_val.background = backgnd ;
X  gc_val.graphics_exposures = False ;
X  gc = XCreateGC(dpy, root, gc_mask, &gc_val) ;
X
X  backgc = XCreateGC(dpy, root, gc_mask, &gc_val) ;
X  XSetForeground(dpy, backgc, gc_val.background) ;
X
X  ropgc = XCreateGC(dpy, root, gc_mask, &gc_val) ;
X  gc_val.function = GXcopy ;
X  gc_val.fill_style = FillOpaqueStippled ;
X  XChangeGC(dpy, ropgc, GCFunction | GCFillStyle, &gc_val) ;
X
X  grey_pr = (Drawable) xv_get(make_server_image(grey_image, 16, 16), XV_XID) ;
X  frame_cursor_pr = make_server_image(frame_cursor_array, 16, 16) ;
X  help_cursor_pr  = make_server_image(help_cursor_array,  16, 16) ;
X  hour_cursor_pr  = make_server_image(hour_cursor_array,  16, 16) ;
X  main_cursor_pr  = make_server_image(main_cursor_array,  16, 16) ;
X  images[(int) B_NORMAL] = (Drawable)
X               xv_get(make_server_image(button_normal_image, 64, 64), XV_XID) ;
X  images[(int) B_INVERT] = (Drawable)
X               xv_get(make_server_image(button_invert_image, 64, 64), XV_XID) ;
X  images[(int) S_NORMAL] = (Drawable)
X               xv_get(make_server_image(switch_normal_image, 16, 16), XV_XID) ;
X  images[(int) S_INVERT] = (Drawable)
X               xv_get(make_server_image(switch_invert_image, 16, 16), XV_XID) ;
X  images[(int) EXCLAIM_IMAGE] = (Drawable)
X               xv_get(make_server_image(exclaim_image, 64, 64), XV_XID) ;
X
X  cursor[(int) FRAME_CUR] = xv_create(XV_NULL,      CURSOR,
X                                      CURSOR_IMAGE, frame_cursor_pr,
X                                      CURSOR_XHOT,  7,
X                                      CURSOR_YHOT,  7,
X                                      0) ;
X  cursor[(int) HELP_CUR] = xv_create(XV_NULL,      CURSOR,
X                                     CURSOR_IMAGE, help_cursor_pr,
X                                     0) ;
X  cursor[(int) HOUR_CUR] = xv_create(XV_NULL,      CURSOR,
X                                     CURSOR_IMAGE, hour_cursor_pr,
X                                     0) ;
X  cursor[(int) MAIN_CUR] = xv_create(XV_NULL,      CURSOR,
X                                     CURSOR_IMAGE, main_cursor_pr,
X                                     0) ;
X
X  show_canvas = xv_create(show_frame, CANVAS,
X                          CANVAS_REPAINT_PROC, repaint_show_canvas,
X                          0) ;
X  spw = canvas_paint_window(show_canvas) ;
X  spr = NULL ;
X
X  XV_SET(canvas, WIN_CURSOR, cursor[(int) MAIN_CUR]) ;
X}
X
Xmenu_proc(menu, menu_item)
XMenu menu ;
XMenu_item menu_item ;
X{
X  int choice ;
X
X  choice = (int) menu_get(menu_item, MENU_VALUE) ;
X  if (choice) process_menu(cur_menu, choice) ;
X}
X
XServer_image
Xmake_server_image(image, width, height)
Xunsigned short image[] ;
Xint width, height ;
X{
X  return(xv_create(XV_NULL,           SERVER_IMAGE,
X                   XV_WIDTH,          width,
X                   XV_HEIGHT,         height,
X                   SERVER_IMAGE_BITS, image,
X                   0)) ;
X}
X
X/*ARGSUSED*/
Xvoid
Xrepaint_show_canvas(canvas, pw, repaint_area)     /* Show current picture. */
XCanvas canvas ;
XPixwin *pw ;
XRectlist *repaint_area ;
X{
X  PW_WRITE(pw, 0, 0, hdr.ras_width, hdr.ras_height, PIX_SRC, spr, 0, 0) ;
X}
X
Xset_cursor(ctype)
Xenum cur_type ctype ;
X{
X  XV_SET(wpw, WIN_CURSOR, cursor[(int) ctype], 0) ;
X}
X
Xshow()      /* Display scanned image. */
X{
X  Rect *temprect ;
X  char errmes[MAXLINE] ;
X  int fd ;
X
X  showing = 1 ;
X  make_button(SCAN_WIDTH-150, 4*SWITCH_HEIGHT+100, "Show", B_INVERT) ;
X  if (spr) PR_DESTROY(spr) ;
X  if ((fd = open(picname, O_RDONLY | O_NDELAY, 0644)) == -1)
X    {
X      SPRINTF(errmes, "Cannot open %s.", picname) ;
X      make_display(errmes) ;
X    }
X  else
X    { 
X      READ(fd, (char *) &hdr, sizeof(struct rasterfile)) ;
X      if (hdr.ras_maplength)
X        {
X          make_display("Color rasterfiles currently not supported.") ;
X          return ;
X        }
X      spr = mem_create(hdr.ras_width, hdr.ras_height, hdr.ras_depth) ;
X      READ(fd, (char *) (mpr_d(spr)->md_image),
X           hdr.ras_width * hdr.ras_height) ;
X      CLOSE(fd) ;
X      temprect = (Rect *) xv_get(show_frame, FRAME_OPEN_RECT) ;
X      temprect->r_left = temprect->r_top = 0 ;
X      temprect->r_height = hdr.ras_height ;
X      temprect->r_width = hdr.ras_width ;
X      XV_SET(show_frame, FRAME_OPEN_RECT, temprect, 0) ;
X      XV_SET(show_frame, FRAME_LABEL, picname, 0) ;
X      XV_SET(show_frame, XV_SHOW, TRUE, 0) ;
X    }
X  make_button(SCAN_WIDTH-150, 4*SWITCH_HEIGHT+100, "Show", B_NORMAL) ;
X  showing = 0 ;
X}
X
Xstart_tool()
X{
X  window_fit(base_frame) ;
X  NOTIFY_INTERPOSE_DESTROY_FUNC(base_frame, destroy) ;
X  started = 1 ;
X  window_main_loop(base_frame) ;
X}
X
X/*ARGSUSED*/
XNotify_value
Xwait_child(frame, pid, status, rusage)
XWindow frame ;
Xint pid ;
Xunion wait *status ;
Xstruct rusage *rusage ;
X{
X  char output[MAXLINE] ;
X  int high, low ;
X
X  if (WIFSTOPPED(*status)) return (NOTIFY_IGNORED) ;
X       
X  high = (status->w_status & 0xFF00) >> 8 ;
X  low = status->w_status & 0xFF ;
X  if (low) SPRINTF(output, "Scan: terminated with signal %1d", (low & 0x3F)) ;
X  else 
X    {
X      switch (high)
X        {
X          case 0  : SPRINTF(output, "Scan: successful. %s saved",
X                                     picname) ;
X                    break ;
X          case 1  : SPRINTF(output, "Scan: cannot open tty port %c",
X                                     switches[SERIAL_PORT] + 'A') ;
X                    break ;
X          case 2  : SPRINTF(output, "Scan: cannot open temporary image file") ;
X                    break ;
X          case 3  : SPRINTF(output, "Scan: cannot open raster header file") ;
X                    break ;
X          case 4  : SPRINTF(output, "Scan: scanner not responding; aborting") ;
X                    break ;
X          case 5  : SPRINTF(output, "Scan: invalid command line argument") ;
X                    break ;
X          default : if (high >= 100 && high < 200)
X                      SPRINTF(output, "Scan: scanner error %1d; aborting",
X                                       high - 100) ;
X                    else
X                      SPRINTF(output, "Scan: terminated with signal %1d",
X                                       high - 200) ;
X        }
X    }    
X  make_display(output) ;
X  make_button(SCAN_WIDTH-150, 4*SWITCH_HEIGHT+20, "Scan",   B_NORMAL) ;
X  make_button(SCAN_WIDTH-150, 4*SWITCH_HEIGHT+60, "Cancel", B_NORMAL) ;
X  scanning = 0 ;
X  return (NOTIFY_DONE) ;
X}
X
Xwait_on_child(pid)      /* Wait on child scan process. */
Xint pid ;
X{
X  NOTIFY_SET_WAIT3_FUNC(base_frame, wait_child, pid) ;
X}
END_OF_FILE
if test 16921 -ne `wc -c <'scantool/xview.c'`; then
    echo shar: \"'scantool/xview.c'\" unpacked with wrong size!
fi
# end of 'scantool/xview.c'
fi
echo shar: End of archive 1 \(of 3\).
cp /dev/null ark1isdone
MISSING=""
for I in 1 2 3 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked all 3 archives.
    rm -f ark[1-9]isdone
else
    echo You still need to unpack the following archives:
    echo "        " ${MISSING}
fi
##  End of shell archive.
exit 0
dan
-----------------------------------------------------------
		    O'Reilly && Associates
		argv at sun.com / argv at ora.com
	   632 Petaluma Ave, Sebastopol, CA 95472 
     800-338-NUTS, in CA: 800-533-NUTS, FAX 707-829-0104
    Opinions expressed reflect those of the author only.



More information about the Comp.sources.x mailing list