[comp.sys.apollo] bgc - Display bitmap as background

ccsmm@bath.ac.uk (Martin Maclaren) (04/12/90)

Here's my attempt at converting Tim Lambert's Pascal bgc to C -
It lets you set up an Apollo GPR bitmap file as background.

The easiest way to get a GPR file is to take a screendump, using
cpo /com/cpscr <pathname> (-gpr_bitmap if it's mono).
However, this means that you can create a 'wanted' background picture
on your Apollo in the first place. Therefore, a more common approach
would be to convert one of the many available GIF files to GPR -
This can be done using the gif2gpr routine recently made available
by Roque Oliveira (oliveria@caen.engin.umich.edu)

NOTES: As we have no SR10.? machines at the mo, I haven't been able to
       verify my attempts at SR9.7/SR10.? dual environment programming.
       (Thanks to GELINASJ@CMR001.BITNET for the pointers)
       I'll get together a patch if there's any response.
       (Modify the Makefile if you don't like -O -M3000)


Have fun,
Martin
--------------------------------------------------------------------------------
#! /bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of shell archive."
# Contents:  Makefile bgc.c
# Wrapped by ccsmm@gdt on Thu Apr 12 10:18:00 1990
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'Makefile' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'Makefile'\"
else
echo shar: Extracting \"'Makefile'\" \(215 characters\)
sed "s/^X//" >'Makefile' <<'END_OF_FILE'
XCFLAGS    = -O -M3000
XLFLAGS    = -s
X#CFLAGS    = -g -DDEBUG
X#LFLAGS    =    -g
X
XOBJS = bgc.o
Xbgc : $(OBJS)
X	$(CC) $(LFLAGS) $(OBJS) -o bgc
X
Xbgc.o : bgc.c
X
Xclean:
X	rm -f *.o *.bak
X
Xrealclean: clean
X	rm -f *.bin bgc
END_OF_FILE
if test 215 -ne `wc -c <'Makefile'`; then
    echo shar: \"'Makefile'\" unpacked with wrong size!
fi
# end of 'Makefile'
fi
if test -f 'bgc.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'bgc.c'\"
else
echo shar: Extracting \"'bgc.c'\" \(14695 characters\)
sed "s/^X//" >'bgc.c' <<'END_OF_FILE'
X/* Name        : bgc
X/*
X/* Syntax      : bgc filename ...
X/*
X/* Description : "bgc" lets you use a bitmap as a background pattern.
X/*               If you give bgc more than one bitmap (e.g. "bgc *.bmf") it
X/*               picks one at random to use as background.  If you don't
X/*               like that one the AGAIN key makes bgc pick another at
X/*               random, and the EXIT key terminates "bgc".
X/*
X/* Authors     : Tim Lambert <lambert@spectrum.cs.unsw.oz.au>
X/*               Original version in Pascal. bgc.pas+bgc_rtn.pas+bgc.ins.pas
X/*               Martin Maclaren <ccsmm@uk.ac.bath>
X/*               Translation to C, one bgc.c, attempt at SR10 mods
X/*
X/* Bugs/Fixes  : If you make any improvements/bug fixes to this program,
X/*               please send them to the ccsmm@uk.ac.bath
X/*
X/* History...
X/*
X/* 10/04/89 : Add SR10 bits - untested
X/* 08/04/89 : Change from .pas to .c
X/* ??/??/?? : Oringinal Creation bgc.pas...
X/* */
X
X#include <stdio.h>
X#include <string.h>
X#ifdef __STDC__
X#include <apollo/base.h>
X#include <apollo/pgm.h>
X#include <apollo/pfm.h>
X#include <apollo/gpr.h>
X#include <apollo/pad.h>
X#include <apollo/ios.h>
X#define   OUTA &
X#define   OUTP
X#else
X#include "/sys/ins/base.ins.c"   /* common include file for all system routines */
X#include "/sys/ins/pgm.ins.c"    /* declarations for pgm routines (for getting file arguments) */
X#include "/sys/ins/pfm.ins.c"    /* for faults */
X#include "/sys/ins/gpr.ins.c"    /* contains the declarations for gpr routines */
X#include "/sys/ins/pad.ins.c"    /* contains the declarations for pad routines (for creating windows) */
X#include "/sys/ins/ios.ins.c"    /* i/o streams */
X#define   OUTA
X#define   OUTP *
X#endif
X
X#define   name_len   128
Xtypedef   char       name_t[name_len];
X
X status_$t           status;              /* all gpr calls return a status value indicating whether they've succeeded or failed */
X gpr_$bitmap_desc_t  display_bitmap;      /* this is the bitmap corresponding to the screen */
X gpr_$offset_t       display_size = {gpr_$max_x_size,gpr_$max_y_size};     /* size of display bitmap */
X gpr_$plane_t        display_hi_plane = gpr_$highest_plane; /* number of highest plane on screen - 7 for 8 plane nodes
X                                           1 for monochrome nodes.  we ask for maximum no of planes - gpr reduces this to fit */
X ios_$id_t           pad;                 /* handle to the window we create for drawing in */
X int                 no_of_args;          /* no of arguments to bg (counting argument 0) */
X char **             arg_pointer;         /* pointer to the arguments */
X
X extern void refresh();
X extern void check();     /* if last system call was unsuccesful prints an error message */
X extern int  randno();    /* returns a number in range 1..n */
X extern void drawit();    /* read in the bitmap in file_name and display it */
X extern pfm_$fh_func_val_t again_pressed(); /* this function is called when program gets a dq -c 1 signal */
X
Xmain(argc, argv)
Xint argc;
Xchar *argv[];
X{
X   short                unit = 1;
X   name_t               cmd;
X   static name_t        window_name = "/tmp/bgc";
X   pad_$window_desc_t   window;
X   gpr_$disp_char_t     disp_chars;                              /* display characteristics */
X   short                disp_len = sizeof(gpr_$disp_char_t);
X   short                disp_len_ret;
X   gpr_$event_t         event_type;          /* type of event returned by gpr_$event_wait - not used */
X   char                 event_char;          /* character user typed in window - not used */
X   gpr_$position_t      event_pos;           /* position where he/she typed it - not used */
X
X   int                  dummy;
X
X   no_of_args=argc; arg_pointer=argv;
X
X   if (no_of_args<=1) {
X      fprintf(stderr, "Usage: bgc bitmap-names\n");
X      pgm_$exit();
X   }
X   if ((dummy=fork()) != 0) {
X     if (dummy == -1)
X          perror("bgc: main: fault forking");
X     pgm_$exit();
X   }
X
X   /* kill previous bg, if any */
X   sprintf(cmd, "dq %s;msg ' '", window_name); /* hide error message if window does not exist */
X   pad_$dm_cmd(stream_$stdout,cmd,(short)strlen(cmd),OUTA status);
X   /* check("dm command"); */
X
X   /* initialize random number generator */
X   srand((unsigned) time((long *) 0));
X
X   gpr_$inq_disp_characteristics(gpr_$borrow,stream_$stdout,disp_len,OUTA disp_chars,OUTA disp_len_ret,OUTA status);
X    check("main: gpr_$inq_disp_characteristics");
X
X   /* create a window and initialise it for graphics */
X   window.left   = disp_chars.x_window_origin;
X   window.top    = disp_chars.y_window_origin;
X   window.width  = disp_chars.x_window_size;
X   window.height = disp_chars.y_window_size;
X
X   pad_$create_window(window_name,(short)strlen(window_name),pad_$transcript,unit,window,OUTA pad,OUTA status);
X    check("main: creating window");
X   if (unlink(window_name) != 0) {
X      perror("bgc: main: unable to unlink");
X      pgm_$exit();
X   }
X   if (window.width != 0) {
X     pad_$set_full_window(pad,(short) 1,window,OUTA status);
X      check("main: set full window");
X   }
X   pad_$set_auto_close(pad,(short) 1,true,OUTA status);
X    check("main: pad_$set_auto_close");
X   pad_$set_border(pad,(short) 1,false,OUTA status);
X    check("main: pad_$set_border");
X#ifdef __STDC__
X   pad_$set_erase(pad,(short) 1,false,OUTA status);
X#endif
X   gpr_$init(gpr_$direct, pad, display_size, display_hi_plane,OUTA display_bitmap,OUTA status);
X    check("main: gpr_init");
X   gpr_$inq_bitmap_dimensions(display_bitmap,OUTA display_size,OUTA display_hi_plane,OUTA status);
X    check("main: gpr_$inq_bitmap_dimensions");
X   gpr_$set_obscured_opt(gpr_$ok_if_obs,OUTA status);
X    check("main: gpr_$set_obscured_opt");
X   gpr_$set_cursor_active(true,OUTA status);
X    check("main: gpr_$set_cursor_active");
X
X   drawit(argv[randno(no_of_args-1)]);
X
X/* establish the refresh procedure.  if window needs to be refreshed as  */
X/* the result of a pop, the draw procedure will automatically be called. */
X   gpr_$set_refresh_entry (refresh, (long)0,OUTA status);
X    check("main: setting the refresh entry procedure.");
X
X/* establish the again_pressed procedure.  if window gets a dq -c 1 signal again_pressed will be called */
X   pfm_$establish_fault_handler ((long) 1,pfm_$fh_multi_level,again_pressed,OUTA status);
X    check("main: establishing fault handler");
X   pad_$def_pfk(pad,"R2  ","dq -c 1",(short) 7,status);
X    check("main: defining AGAIN");
X   pad_$def_pfk(pad,"R5  ","dq",(short) 2,status);
X    check("main: defining EXIT");
X
X   gpr_$event_wait (OUTA event_type,OUTA event_char,OUTA event_pos,OUTA status);
X/* We would have liked to have waited for a keystroke, but we can't do input */
X/* into partly obscured windows we resort to evil thing with signals instead */
X
X} /* end of main */
X
X/* MODULE view; - originally bgc_rtn.pas, now all one thingy */
X
X#define max_no_windows (short)50
X
X boolean             pattern = false;
X
X gpr_$offset_t       fill_size;      /* x and y size of our fill bitmap */
X gpr_$rgb_plane_t    fill_hi_plane;  /* number of highest plane in fill bitmap */
X gpr_$bitmap_desc_t  fill_bitmap;    /* this is the bitmap to fill with */
X boolean             first = true;   /* first time for getbitmap()? */
X
Xvoid check(messagex)
Xchar *messagex;
X{
X/* if last system call was unsuccesful prints an error message */
X
X   if ( status.all != status_$ok) {
X           error_$print(status);
X           fprintf(stderr,"bgc: error occurred with %s\n",messagex);
X           pgm_$exit();
X   }
X#ifdef DEBUG
X   fprintf(stdout,"check: %s\n", messagex);
X#endif
X}
X
Xint randno(n)
Xint n;
X{
X/* returns a number in range 1..n */
X     return(1 + (rand() % n));
X} /* randno */
X
Xvoid draw_image(clip)
Xgpr_$window_t clip;
X{
X    static gpr_$window_t  window = {{0,0},{0,0}};
X    gpr_$position_t       dest;  /* destinition point for our bit-blts */
X    int                   i,j;
X
X   gpr_$set_clip_window (clip,OUTA status);
X    check("draw_image: gpr_$set_clip_window");
X   gpr_$acquire_display(OUTA status);
X    check("draw_image: gpr_$acquire_display");
X   window.window_size.x_size = display_size.x_size;
X   window.window_size.y_size = display_size.y_size;
X   if (pattern==true) {
X      gpr_$set_fill_pattern(fill_bitmap,(short) 1,OUTA status);
X       check("draw_image: gpr_$set_fill_pattern");
X      gpr_$rectangle(window,OUTA status);
X       check("draw_image: rectangle");
X   } else {
X      for (i=clip.window_base.x_coord / fill_size.x_size;
X            i<=(clip.window_base.x_coord+clip.window_size.x_size) / fill_size.x_size; i++) {
X         dest.x_coord = i*fill_size.x_size;
X         for (j=clip.window_base.y_coord / fill_size.y_size;
X               j<=(clip.window_base.y_coord+clip.window_size.y_size) / fill_size.y_size; j++) {
X            dest.y_coord = j*fill_size.y_size;
X            gpr_$pixel_blt(fill_bitmap,window,dest,OUTA status );  /* does a bit_blt from bitmap file to fill */
X             check("draw_image: pixel_blt");
X         }
X      }
X   };
X   gpr_$release_display(OUTA status);
X    check("draw_image: gpr_$release_display");
X} /* draw_image */
X
Xvoid refresh(unobscured, position_change)
Xboolean unobscured;
Xboolean position_change;
X{
X     gpr_$window_t vis_list[max_no_windows];
X     short i, slots_total;
X
X     gpr_$release_display(OUTA status);
X      check("refresh: gpr_$release_display");
X     pad_$pop_push_window(pad,(short)1,false,OUTA status);
X      check("refresh: push");
X     gpr_$acquire_display(OUTA status);
X      check("refresh: gpr_$acquire_display");
X     gpr_$set_cursor_active(false,OUTA status);
X      check("refresh: gpr_$set_cursor_active");
X     gpr_$inq_vis_list (max_no_windows,OUTA slots_total,OUTA vis_list,OUTA status);
X      check("refresh: gpr_$inq_vis_list");
X     slots_total = (slots_total<max_no_windows) ? slots_total : max_no_windows;
X     for(i=0; i<slots_total; i++)
X       draw_image(vis_list[i]);
X     gpr_$set_cursor_active(true,OUTA status);
X      check("refresh: gpr_$set_cursor_active");
X}
X
X
Xvoid getbitmap(file_name)
Xchar *file_name;
X{
X/* gets bitmap from file_name */
X    gpr_$position_t                dest;                  /* destinition point for our bit-blts */
X    gpr_$rgb_plane_t               file_hi_plane;         /* number of highest plane in file bitmap */
X    gpr_$color_vector_t            color_map;
X    gpr_$version_t                 version;               /* some useless information returned by gpr_$open_bitmap_file */
X    gpr_$offset_t                  file_size;             /* x and y size of our file bitmap */
X    short                          groups;                /* more of the same */
X    gpr_$bmf_group_header_array_t  group_hs;              /* field pixel_size * field n_sects should give # of planes in bitmap */
X    gpr_$attribute_desc_t          attribs;               /* the attribute block for the bitmap file */
X    gpr_$bitmap_desc_t             file_bitmap;           /* this is the bitmap to fill with */
X    boolean                        created;               /* tells us if the bitmap file was created - should be false */
X    static gpr_$window_t           window = {{0,0},{0,0}};
X    int                            i,j;
X
X   gpr_$allocate_attribute_block(OUTA attribs,OUTA status );      /* our window */
X    check("getbitmap: gpr_$allocate_attribute_block");
X
X   /* open the bitmap file */
X   gpr_$open_bitmap_file(gpr_$readonly,OUTP file_name,(short)strlen(file_name),OUTA version,
X                          OUTA file_size,OUTA groups,OUTA group_hs,
X                          attribs,OUTA file_bitmap,OUTA created,OUTA status );
X    check("getbitmap: gpr_$open_bitmap_file");
X   file_hi_plane = group_hs[0].pixel_size * group_hs[0].n_sects - 1;  /* calculates # of planes in file bitmap */
X   fill_hi_plane = (display_hi_plane<file_hi_plane) ? display_hi_plane : file_hi_plane;
X   if (fill_hi_plane == 7) {
X       gpr_$inq_bitmap_file_color_map(file_bitmap,(short) 0,(short) 256,OUTA color_map,OUTA status);
X        check("getbitmap: gpr_$inq_bitmap_file_color_map");
X       gpr_$acquire_display(status);
X        check("getbitmap: gpr_$acquire_display");
X       gpr_$set_color_map((short) 16,(short) 240, color_map[16],OUTA status);
X        check("getbitmap: gpr_$set_color_map");
X       gpr_$release_display(OUTA status);
X        check("getbitmap: gpr_$release_display");
X   }
X   if ((file_size.x_size == 32) && (file_size.y_size == 32)) {
X      fill_size = file_size;
X      pattern = true;
X   } else {
X      /* make sure fill bitmap is at least 200x200 */
X      fill_size.x_size = file_size.x_size*(1+ 200 / file_size.x_size);
X      fill_size.y_size = file_size.y_size*(1+ 200 / file_size.y_size);
X      pattern = false;
X   }
X   if (first==false) { /* deallocate fill_bitmap if this isn't the first time we've been called */
X          gpr_$deallocate_bitmap(fill_bitmap,OUTA status);
X           check("getbitmap: gpr_$deallocate_bitmap");
X   } else first=false;
X/* allocate a memory bitmap for bit-blting to */
X   gpr_$allocate_bitmap(fill_size,fill_hi_plane,attribs,OUTA fill_bitmap,OUTA status);
X    check("getbitmap: gpr_$allocate_bitmap");
X   window.window_size.x_size = file_size.x_size;                                 /* bitmap file */
X   window.window_size.y_size = file_size.y_size;
X   gpr_$set_bitmap(fill_bitmap,OUTA status);
X    check("getbitmap: gpr_$set_bitmap");
X   for(i=0; i<=((fill_size.x_size-1) / file_size.x_size); i++) {
X      dest.x_coord = i*file_size.x_size;
X      for(j=0; j<=((fill_size.y_size-1) / file_size.y_size); j++) {
X          dest.y_coord = j*file_size.y_size;
X          gpr_$pixel_blt(file_bitmap,window,dest,OUTA status);   /* does a bit_blt from bitmap file to fill */
X           check("getbitmap: pixel_blt");
X      }
X   }
X   gpr_$deallocate_bitmap(file_bitmap,OUTA status);
X    check("getbitmap: gpr_$deallocate_bitmap");
X}
X
Xvoid drawit(file_name)
Xchar *file_name;
X{
X/* read in the bitmap in file_name and display it */
X   getbitmap(file_name);
X
X   /* draw the picture. */
X   gpr_$acquire_display(OUTA status);
X    check("drawit: gpr_$acquire_display");
X   gpr_$set_bitmap(display_bitmap,OUTA status );
X    check("drawit: gpr_$set_bitmap");
X   refresh(true,false);
X   gpr_$release_display(OUTA status);
X    check("drawit: gpr_$release_display");
X} /* drawit */
X
X
Xpfm_$fh_func_val_t again_pressed(f_status)
Xpfm_$fault_rec_t f_status;
X{
X/* this function is called when program gets a dq -c 1 signal,
X   this should happen when AGAIN is pressed */
X
X   static boolean lock=false;  /* we ignore further interupts till we're finished */
X#ifdef DEBUG
X   fprintf(stdout,"again_pressed:\n");
X#endif
X   if ( lock==false ) {
X	lock = true;
X     drawit(arg_pointer[randno(no_of_args-1)]);
X     lock = false;
X   }
X   return(pfm_$return_to_faulting_code);
X} /* again_pressed */
END_OF_FILE
if test 14695 -ne `wc -c <'bgc.c'`; then
    echo shar: \"'bgc.c'\" unpacked with wrong size!
fi
# end of 'bgc.c'
fi
echo shar: End of shell archive.
exit 0