v02i006: a maze graphical maze solver, Part01/01

Mike Wexler mikew at wyse.wyse.com
Sat Oct 22 09:49:05 AEST 1988


Submitted-by: James Peterson <peterson%sw.MCC.COM at MCC.COM>
Posting-number: Volume 2, Issue 6
Archive-name: maze2/part01



# This is a shar archive.
# Remove everything above this line.
# Run the file through sh, not csh.
# (type `sh this_file')
echo extracting - Makefile
sed 's/^X//' > Makefile << 'FRIDAY_NIGHT'
X##############################################################################
X#
X# 	Makefile for maze program
X#
X#	Create a maze, draw it on the screen, solve it; repeat until stopped
X#
X
X##############################################################################
X#
X#
X
XDESTDIR=
X
XALL=mazes mazew maze11
XCFLAGS = -g
X
Xall:	${ALL}
X
X##############################################################################
X#
X#	common part of code
X#
X
XCOMSRC = main.c maze.c path.c draw.c
XCOMOBJ = main.o maze.o path.o draw.o
X
X
Xmain.o:	main.h main.c
X	${CC} ${CFLAGS} main.c -c
X
Xmaze.o:	main.h maze.h maze.c
X	${CC} ${CFLAGS} maze.c -c
X
Xpath.o:	main.h maze.h path.c
X	${CC} ${CFLAGS} path.c -c
X
Xdraw.o:	main.h maze.h draw.c
X	${CC} ${CFLAGS} draw.c -c
X
X
X##############################################################################
X#
X#	window system dependent part for SUNTOOLS
X#
XWINLIBS=-lsuntool -lsunwindow -lpixrect
Xmazes: ${COMOBJ} suntool.o
X	${CC} ${CFLAGS} ${COMOBJ} suntool.o ${WINLIBS} -o mazes 
X
Xsuntool.o:	main.h suntool.c
X	${CC} ${CFLAGS} suntool.c -c
X	
X
X##############################################################################
X#
X#  For the old CMU Andrew window manager
X#
Xmazew: ${COMOBJ} andrew.o
X	${CC} ${CFLAGS} ${COMOBJ} andrew.o /usr/andrew/lib/libitc.a -o mazew 
X
Xandrew.o: main.h andrew.c
X	${CC} ${CFLAGS} -I/usr/andrew/include andrew.c -c
X
X
X##############################################################################
X#
X#  For the X11 window system
X#
Xmaze11: ${COMOBJ} x11.o
X	${CC} ${CFLAGS} ${COMOBJ} x11.o /usr/external/lib/libX11.a -o maze11
X
Xx11.o:  main.h x11.c x11-logo.xbm
X	${CC} ${CFLAGS} -I/usr/external/include x11.c -c
X
X
X##############################################################################
X#
X#
Xlint:
X	lint ${COMSRC} suntool.c
X	lint ${COMSRC} -I/usr/andrew/include andrew.c
X	lint ${COMSRC} -I/usr/external/include x11.c
X
X##############################################################################
X#
X#
Xclean:
X	rm -f *.o *~ \#*\# errs core ${ALL}
X
X##############################################################################
X#
X#
X
Xinstall: all
X	-for i in ${ALL}; do \
X		install -s $$i ${DESTDIR}/bin; \
X	done
X
FRIDAY_NIGHT
echo extracting - README
sed 's/^X//' > README << 'FRIDAY_NIGHT'
XThis program generates and then solves random mazes.  It is derived from
Xan early version by Martin Weiss.  It has been structured to run under
Xsuntools, the CMU wm window manager (obsolete), and X11.  Making it run
Xwith other window systems should be relatively simple.
X
XThe code has a main program that sets everything up and drives the rest
Xof the code (main.c).  maze.c generates and solves the maze.  draw.c and
Xpath.c support the general operation of maze.c.  The three files suntool.c,
Xandrew.c and x11.c are used to create the different versions of maze.  Each
Xof them define the device dependent routines that main, maze, draw, and path
Xuse to change the screen image.  These device dependent routines are all dd_*
Xroutines and are explained at the beginning of these three files.
X
XBoth color and mono displays are supported.
X
XIf you have a previous version of maze, I think it would be useful to compare
Xthis version with that one.  Which can you understand and modify better?
X
X
XJames Peterson
Xjames.peterson at mcc.com
X18 Oct 1988
FRIDAY_NIGHT
echo extracting - andrew.c
sed 's/^X//' > andrew.c << 'FRIDAY_NIGHT'
X/* ************************************************************ */
X
X/*	andrew.c	graphical maze program (support)	*/
X
X/*	
X  
X  Support code for the maze program under the andrew window manager
X  
X  Interface:
X  
X  dd_Set_Defaults() -- Set any global variable defaults.  
X                       Called only once at beginning
X  
X  dd_scan_arg(option) -- called when the maze program has a command line option
X                         that it does not recognize. Can be used to specify
X			 device dependent options (like Geometry and Display).
X
X  dd_initialize_window() -- Create a window on the screen.  Must set the
X                            size of the window and tell if it is mono or color
X  
X  dd_terminate_window() -- Delete the window and any other resources.
X
X  dd_restart() -- Check if we need to restart the display, either because
X                  the display has been corrupted, or user input.
X
X  dd_idle() -- Wait until user wants to restart computation.
X
X  dd_reset_restart() -- reset whatever state caused dd_restart to return true
X  
X  dd_lock_screen() -- set up access to the window; lock and unlock are called
X                      alternatively, so that all drawing calls are between a
X                      call to lock and its following unlock.
X  
X  dd_unlock_screen() -- access is finished for now, unlock or flush output
X  
X  dd_set_new_color_map() -- global variables rmap, gmap, bmap define a new
X                            color map which will be used for the following
X                            operations.  Change color support as necessary.
X                            If we have only mono display, then the size of
X                            the color map is only 2, and the first two entries
X                            define black and white.
X  
X  dd_clear_window(x, y, w, h, fillcolor) -- clear the window.  x,y will be
X                            0,0 and w,h is the width and height of the window.
X			    The fillcolor is ColorBack -- the background color.
X			    This could be done with a dd_fill_rectangle (below)
X			    but is provided in case there is a special case
X			    clear-window command that is significantly faster
X			    than the general dd_fill-rectangle.
X
X  dd_draw_line(x1,y1,x2,y2,color) -- draw a line from x1,y1 to x2,y2 in the
X                                     given color.
X  
X  dd_fill_rectangle(x,y,w,h,color) -- fill the rectangle with origin x,y of
X                                      width w and height h with the color.
X  
X  dd_draw_logo(x,y,color) -- draw the logo at origin x,y in the color.  The
X                             logo is of width LOGO_PIXELS_X and height
X                             LOGO_PIXELS_Y (typically 64 x 64).
X*/
X
X/*  Written; James Peterson, 17 Nov 1987      */
X
X/* ************************************************************ */
X/*                                                              */
X/*  Standard Initializations                                    */
X/*                                                              */
X/* ************************************************************ */
X
X#include "main.h"
X
X
X/* ************************************************************ */
X/*                                                              */
X/*  Device Dependent Code                                       */
X/*                                                              */
X/* ************************************************************ */
X
X#include "wmclient.h"
X
X/* ************************************************************ */
X/*                                                              */
X/*                                                              */
X/* ************************************************************ */
X
Xdd_Set_Defaults()
X{
X  enterprocedure("dd_Set_Defaults");
X}
X
Xdd_scan_arg(option)
Xchar *option;
X{
X  fprintf(stderr, "maze: Bad option %s\n", option);
X  Please_Exit = true;
X}
X
X/* ************************************************************ */
X
Xdd_initialize_window()	       /* take over and initialize window */
X{
X  /* 
X    Must define:
X	    screen_size
X	    ColorWindows
X	    InputFD
X  */
X  
X  enterprocedure("dd_initialize_window");
X  /* create new window */
X  /* get properties of graphics sub-window */
X  if (wm_NewWindow(0) == 0)
X    {
X      fprintf(stderr, "Need window manager\n");
X      exit(1);
X    };
X  /* spawn process for it */
X  if (fork())
X    exit(0);
X
X  InputFD = fileno(winin);
X  wm_SetProgramName("Maze");
X  wm_SetTitle(" ");
X  wm_DisableNewlines();
X  wm_AddMenu("Quit~99:\003");
X  
X  /* get screen size */
X  {
X    short   width, height;
X    wm_GetDimensions(&width, &height);
X    DefineScreenSize(width, height);
X  }
X  
X  
X  /* determine if we have a color screen or black and white */
X  ColorWindows = false;
X}			       /* end of dd_initialize_window() */
X
X
Xdd_terminate_window()
X{
X  enterprocedure("dd_terminate_window");
X}
X
Xdd_idle()
X{
X  enterprocedure("dd_idle");
X  Wait(0);
X  Please_Idle = false;
X}
X
X
X/* ************************************************************ */
X/*                                                              */
X/*                                                              */
X/* ************************************************************ */
X
Xstatic  Boolean SizeChanged = false;
X     
XBoolean dd_restart(full)
X     Boolean full;
X{
X  /* check if there is any reason to restart */
X  
X  enterprocedure("dd_restart");
X  if (SizeChanged)
X    return(true);
X  if (!full)
X    return(false);
X  
X  /* if full is true, be sure to check completely */
X  /* Polling for input is more expensive, only do if requested */
X  fflush(winout);
X  if (PollFile(winin)) DoInput();
X
X  return(false);
X}
X
X
XFlagRedraw()
X{
X  enterprocedure("FlagRedraw");
X  SizeChanged = true;
X  if (debug(4))
X    fprintf(stderr, "Size Changed\n");
X}
X
X
X/* ************************************************************ */
X/*                                                              */
X/*                                                              */
X/* ************************************************************ */
X
Xdd_reset_restart()
X{
X  enterprocedure("dd_reset_restart");
X  if (SizeChanged)
X    {
X      /* get screen size */
X      short   width, height;
X      wm_GetDimensions(&width, &height);
X      DefineScreenSize(width, height);
X    }
X  else
X    DoInput();
X  SizeChanged = false;
X}
X
XDoInput()
X{
X  int     c;
X  
X  enterprocedure("DoInput");
X  /* input is waiting on winin */
X  if (debug(4))
X    fprintf(stderr, "Read from winin ");
X  c = getc(winin);
X  if (debug(4))
X    fprintf(stderr, "[%d]\n", c);
X  if (c == EOF || c == '\003')
X      Please_Exit = true;
X  else switch (c)
X    {
X    case '+': 
X      IncreaseSquareSize(1, 1);
X      break;
X      
X    case '-': 
X      IncreaseSquareSize(-1, -1);
X      break;
X      
X    default: 
X      break;
X    }
X}
X
X
X/* ************************************************************ */
X/*                                                              */
X/* lock and unlock access to the window                         */
X/*                                                              */
X/* ************************************************************ */
X
X
Xdd_lock_screen()
X{
X  enterprocedure("dd_lock_screen");
X}
X
Xdd_unlock_screen()
X{
X  enterprocedure("dd_unlock_screen");
X  fflush(winout);
X}
X
X
X/* ************************************************************ */
X/*                                                              */
X/*                                                              */
X/* ************************************************************ */
X
X/* set the color map -- for black and white use only first 2 entries */
X
Xdd_set_new_color_map()
X{
X  enterprocedure("dd_set_new_color_map");
X}			       /* end of dd_set_new_color_map() */
X
X/* ************************************************************ */
X/*                                                              */
X/*                                                              */
X/* ************************************************************ */
X
X
Xdd_draw_line(x1, y1, x2, y2, linecolor)
X     short   x1;
X     short   y1;
X     short   x2;
X     short   y2;
X     ColorIndex linecolor;
X{
X  enterprocedure("dd_draw_line");
X  if (linecolor == 0)
X    {
X      wm_SetFunction(f_black);
X    }
X  else
X    wm_SetFunction(f_white);
X  wm_MoveTo(x1, y1);
X  wm_DrawTo(x2, y2);
X}			       /* end of dd_draw_line() */
X
X/* ************************************************************ */
X/*                                                              */
X/*                                                              */
X/* ************************************************************ */
X
Xdd_clear_window(x, y, w, h, fillcolor)
X     short   x;
X     short   y;
X     short   w;
X     short   h;
X     ColorIndex fillcolor;
X{
X  dd_fill_rectangle(x, y, w, h, fillcolor);
X}
X
X
Xdd_fill_rectangle(x, y, w, h, fillcolor)
X     short   x;
X     short   y;
X     short   w;
X     short   h;
X     ColorIndex fillcolor;
X{
X  enterprocedure("dd_fill_rectangle");
X  if (fillcolor == 0)
X    {
X      wm_SetFunction(f_black);
X    }
X  else
X    wm_SetFunction(f_white);
X  wm_RasterSmash(x, y, w, h);
X}			       /* end of dd_fill_rectangle() */
X
X
X/* ************************************************************ */
X/*                                                              */
X/*                                                              */
X/* ************************************************************ */
X
Xdd_draw_logo(x, y, logocolor)
X     ColorIndex logocolor;
X{
X  enterprocedure("dd_draw_logo");
X  if (logocolor == 0)
X    {
X      wm_SetFunction(f_black);
X    }
X  else
X    wm_SetFunction(f_white);
X  wm_MoveTo(x, y);
X  wm_printf(x, y, wm_AtTop | wm_AtLeft, spec());
X}			       /* end of dd_draw_logo() */
FRIDAY_NIGHT
echo extracting - draw.c
sed 's/^X//' > draw.c << 'FRIDAY_NIGHT'
X/* ************************************************************ */
X
X/*	maze.c		graphical maze program			*/
X
X/*	
X  
X  Generate a random maze and then solve it.
X  
X*/
X
X
X/* ************************************************************ */
X
X#include "main.h"
X#include "maze.h"
X
X
X/* ************************************************************ */
X/*                                                              */
X/*                                                              */
X/* ************************************************************ */
X
XClear_Window()
X{
X  enterprocedure("Clear_Window");
X  dd_clear_window(0, 0, screen_size.x, screen_size.y, ColorBack);
X}
X
X/* ************************************************************ */
X/*                                                              */
X/*                                                              */
X/* ************************************************************ */
X
Xstatic long LinesCalled;
Xstatic long LinesDrawn;
X
X#define MAXLineBuffer 10
Xtypedef long    LineBufferIndex;
X
X#define VERTICAL 0
X#define HORIZONTAL 1
X
Xstruct segment
X{
X  short   direction;
X  short   x1, y1;
X  short   x2, y2;
X  short   age;
X};
X
Xstatic  LineBufferIndex BufferLength = 0;
Xstruct segment  Buffer[MAXLineBuffer];
X
X#define SegmentLength(i) (Buffer[i].direction == VERTICAL \
X			  ? (Buffer[i].y2 - Buffer[i].y1) \
X			  : (Buffer[i].x2 - Buffer[i].x1))
X
XBegin_Draw_Lines()
X{
X  enterprocedure("Begin_Draw_Lines");
X  dd_lock_screen();
X  BufferLength = 0;
X  LinesCalled = 0;
X  LinesDrawn = 0;
X}
X
XDraw_Line(x1, y1, x2, y2)
X     short   x1;
X     short   y1;
X     short   x2;
X     short   y2;
X{
X  LineBufferIndex i;
X  short   NewDirection;
X  
X  enterprocedure("Draw_Line");
X  LinesCalled += 1 /* statistics */ ;
X  /* sort the direction of drawing */
X  {
X    short   tmp;
X    if (x1 > x2 && y1 == y2)
X      {
X	tmp = x1;
X	x1 = x2;
X	x2 = tmp;
X      }
X    if (y1 > y2 && x1 == x2)
X      {
X	tmp = y1;
X	y1 = y2;
X	y2 = tmp;
X      }
X  }
X  
X  /* determine if the new line is vertical or horizontal; if not, draw it */
X  if (x1 == x2)
X    NewDirection = VERTICAL;
X  else if (y1 == y2)
X    NewDirection = HORIZONTAL;
X  else
X    {
X      OutputLine(x1, y1, x2, y2, ColorWall);
X      return;
X    }
X  
X  /* see if this line is a continuation of another line in the buffer */
X  /* if so, merge these two line segments, and look for another one */
X  i = 0;
X  while (i < BufferLength)
X    {
X      if (Buffer[i].direction == NewDirection)
X	{
X	  if (NewDirection == VERTICAL)
X	    {      /* Direction is VERTICAL */
X	      if (x1 == Buffer[i].x1)
X		{
X		  if (Buffer[i].y2 == y1)
X		    {
X		      /* buffer.y1 < buffer.y2 = y1 < y2 */
X		      y1 = Buffer[i].y1;
X		      DeleteLineSegment(i);
X		      i = -1;
X		    }
X		  else if (y2 == Buffer[i].y1)
X		    {
X		      /* y1 < y2 = buffer.y1 <
X			 buffer.y2 */
X		      y2 = Buffer[i].y2;
X		      DeleteLineSegment(i);
X		      i = -1;
X		    }
X		}
X	    }
X	  else
X	    {
X	      if (NewDirection == HORIZONTAL)
X		{/* Direction is HORIZONTAL */
X		  if (y1 == Buffer[i].y1)
X		    {
X		      if (Buffer[i].x2 == x1)
X			{
X			  /* buffer.x1 < buffer.x2 = x1
X			     < x2 */
X			  x1 = Buffer[i].x1;
X			  DeleteLineSegment(i);
X			  i = -1;
X			}
X		      else if (x2 == Buffer[i].x1)
X			{
X			  /* x1 < x2 = buffer.x1 <
X			     buffer.x2 */
X			  x2 = Buffer[i].x2;
X			  DeleteLineSegment(i);
X			  i = -1;
X			}
X		    }
X		}
X	    }
X	}
X      i += 1;
X    }
X  
X  /* now put the new line segment into the line buffer */
X  if (BufferLength >= MAXLineBuffer)
X    {
X      LineBufferIndex maxIndex;
X      long    maxLength;
X      
X      /* find the oldest, longest line */
X      maxIndex = 0;
X      maxLength = SegmentLength(0);
X      for (i = 1; i < BufferLength; i++)
X	{
X	  long    length = SegmentLength (i);
X	  if (length > maxLength
X	      || (length == maxLength && Buffer[i].age < Buffer[maxIndex].age))
X	    {
X	      maxIndex = i;
X	      maxLength = length;
X	    }
X	}
X      
X      /* draw the longest line  and delete it */
X      OutputLine(Buffer[maxIndex].x1, Buffer[maxIndex].y1,
X		 Buffer[maxIndex].x2, Buffer[maxIndex].y2, ColorWall);
X      DeleteLineSegment(maxIndex);
X    }
X  
X  Buffer[BufferLength].direction = NewDirection;
X  Buffer[BufferLength].x1 = x1;
X  Buffer[BufferLength].y1 = y1;
X  Buffer[BufferLength].x2 = x2;
X  Buffer[BufferLength].y2 = y2;
X  Buffer[BufferLength].age = LinesCalled;
X  BufferLength += 1;
X}			       /* end of Draw_Line() */
X
XDeleteLineSegment(i)
X     LineBufferIndex i;
X{
X  enterprocedure("DeleteLineSegment");
X  if (i != BufferLength)
X    {
X      Buffer[i].direction = Buffer[BufferLength - 1].direction;
X      Buffer[i].x1 = Buffer[BufferLength - 1].x1;
X      Buffer[i].y1 = Buffer[BufferLength - 1].y1;
X      Buffer[i].x2 = Buffer[BufferLength - 1].x2;
X      Buffer[i].y2 = Buffer[BufferLength - 1].y2;
X      Buffer[i].age = Buffer[BufferLength - 1].age;
X    }
X  BufferLength -= 1;
X}
X
XEnd_Draw_Lines()
X{
X  register    LineBufferIndex i;
X  
X  enterprocedure("End_Draw_Line");
X  for (i = 0; i < BufferLength; i++)
X    OutputLine(Buffer[i].x1, Buffer[i].y1,
X	       Buffer[i].x2, Buffer[i].y2, ColorWall);
X  BufferLength = 0;
X  if (debug(16))
X    fprintf(stderr, "%d calls, %d draws\n", LinesCalled, LinesDrawn);
X  dd_unlock_screen();
X}
X
X
XOutputLine(x1, y1, x2, y2, LineColor)
X     short   x1;
X     short   y1;
X     short   x2;
X     short   y2;
X     ColorIndex LineColor;
X{
X  enterprocedure("OutputLine");
X  LinesDrawn += 1;
X  x1 = border.x + square_size.x * x1;
X  y1 = border.y + square_size.y * y1;
X  x2 = border.x + square_size.x * x2;
X  y2 = border.y + square_size.y * y2;
X  
X  if (debug(32))
X    fprintf(stderr, "Line %d: %d,%d -> %d,%d in %d\n",
X	    LinesDrawn, x1, y1, x2, y2, LineColor);
X  
X  dd_draw_line(x1, y1, x2, y2, LineColor);
X}
X
X
X/* ************************************************************ */
X/*                                                              */
X/*                                                              */
X/* ************************************************************ */
X
X
X/* draw a solid square in the i,j square */
XDraw_Solid_Square(i, j, dir, fillcolor)
X     register short  i;
X     register short  j;
X     register short  dir;
X     register    ColorIndex fillcolor;
X{
X  enterprocedure("Draw_Solid_Square");
X  switch (dir)
X    {
X    case TOP: 
X      OutputRectangle(square_size.x * i + HALF_BORDER + 1,
X		      square_size.y * j - HALF_BORDER,
X		      square_size.x - SQ_BORDER,
X		      square_size.y,
X		      fillcolor);
X      break;
X      
X    case RIGHT: 
X      OutputRectangle(square_size.x * i + HALF_BORDER + 1,
X		      square_size.y * j + HALF_BORDER + 1,
X		      square_size.x,
X		      square_size.y - SQ_BORDER,
X		      fillcolor);
X      break;
X      
X    case BOTTOM: 
X      OutputRectangle(square_size.x * i + HALF_BORDER + 1,
X		      square_size.y * j + HALF_BORDER + 1,
X		      square_size.x - SQ_BORDER,
X		      square_size.y,
X		      fillcolor);
X      break;
X      
X    case LEFT: 
X      OutputRectangle(square_size.x * i - HALF_BORDER,
X		      square_size.y * j + HALF_BORDER + 1,
X		      square_size.x,
X		      square_size.y - SQ_BORDER,
X		      fillcolor);
X      break;
X    }
X}			       /* end of Draw_Solid_Square() */
X
X
XOutputRectangle(x, y, w, h, FillColor)
X     short   x;
X     short   y;
X     short   w;
X     short   h;
X     ColorIndex FillColor;
X{
X  enterprocedure("OutputRectangle");
X  x = border.x + x;
X  y = border.y + y;
X  
X  if (debug(32))
X    fprintf(stderr, "Rectangle %d,%d (%d x %d) in %d\n",
X	    x, y, w, h, FillColor);
X  
X  dd_fill_rectangle(x, y, w, h, FillColor);
X}
FRIDAY_NIGHT
echo extracting - main.c
sed 's/^X//' > main.c << 'FRIDAY_NIGHT'
X/* ************************************************************ */
X
X/*	maze.c		graphical maze program			*/
X
X/*	
X  
X  Generate a random maze and then solve it.
X  
X*/
X
X/*  original version by Martin Weiss, Sun Microsystems, 21 June 85 */
X/*  Reorganized and rewritten; James Peterson,          17 Nov 87  */
X/*  X11 code by Richard Hess, Dave Lemke (Sun)          13 Oct 88  */
X
X/* ************************************************************ */
X/*                                                              */
X/*  Simple Support Routines                                     */
X/*                                                              */
X/* ************************************************************ */
X
X#include "main.h"
X
XEnterProcedure(name)
X     char   *name;
X{
X  fprintf(stderr, ">>> %s\n", name);
X}
X
X
X/* ************************************************************ */
X/*                                                              */
X/*  Random number code                                          */
X/*                                                              */
X/* ************************************************************ */
X
Xlong    random ();
X
Xshort   get_random (modulo)
X     short   modulo;
X{
X  enterprocedure("get_random");
X  return((short)((random() >> 10) % modulo));
X  
X}			       /* end of get_random() */
X
X/* ************************************************************ */
X/*                                                              */
X/*  Short time sleeping                                         */
X/*                                                              */
X/* ************************************************************ */
X
X#include <sys/time.h>	       /* for struct timeval */
X
Xstatic struct timeval   TimeOut = {  0, 0  };
X
XWait(n)
X     short   n;
X{
X  int     rfds, wfds, xfds;
X  struct timeval *Timer;
X  int rc;
X  
X  enterprocedure("Wait");
X  if (n < 0) return;
X  dd_unlock_screen();
X  if (n > 0)
X    {
X      TimeOut.tv_usec = n * 10;
X      Timer = &TimeOut;
X    }
X  else Timer = NULL;
X
X  rfds = wfds = xfds = 0;
X  if (InputFD >= 0) rfds = (1 << InputFD);
X
X  if (debug(4)) 
X    fprintf(stderr, "Select (%08x) wait for %d seconds or FD %d\n",
X			rfds, n, InputFD);
X  rc = select(InputFD+1, &rfds, &wfds, &xfds, Timer);
X  if (debug(4)) 
X    fprintf(stderr, "%d = select (%x, ...)\n", rc, rfds);
X  dd_lock_screen();
X}
X
X
X/* ************************************************************ */
X/*                                                              */
X/*  Poll for input on FILE *                                    */
X/*                                                              */
X/* ************************************************************ */
X
XBoolean PollFile(file)
XFILE *file;
X{
X  int     readfds;
X  int     nfds;
X  struct timeval  timeout;
X  
X  /* 
X    check if there is any input waiting from winin 
X    return true if so, or false if no input
X  */
X  
X  enterprocedure("PollFile");
X  /* first check the incore buffer for winin */
X  if (file->_cnt > 0)
X    {
X      if (debug(4)) fprintf(stderr, "file->_cnt non-zero\n");
X      return(true);
X    }
X  
X  /* use zero-valued time out */
X  timeout.tv_sec = 0;
X  timeout.tv_usec = 0;
X  
X  readfds = 1 << fileno(file);
X  nfds = select(fileno(file)+1, &readfds, (int *)NULL, (int *)NULL, &timeout);
X  if (nfds <= 0 || readfds == 0) return(false);
X
X  if (debug(4)) fprintf(stderr, "Poll of file nfds = %d, readfds = %4o\n",
X	    nfds, readfds);
X  return(true);
X}
X
X/* ************************************************************ */
X/*                                                              */
X/*  Standard Initializations                                    */
X/*                                                              */
X/* ************************************************************ */
X
XSetGlobalDefaults()
X{
X  enterprocedure("SetGlobalDefaults");
X  DebugLevel = 0;
X  Please_Exit = false;
X  Please_Idle = false;
X
X
X  ColorBack = 0;	       /* default values for color device */
X  ColorWall = 1;
X  ColorPath = 2;
X  ColorLogo = 3;
X  
X  srandom(getpid()) /* start random numbers */ ;
X  
X  Set_Maze_Defaults();
X  dd_Set_Defaults();
X}
X
X/* ************************************************************ */
X/*                                                              */
X/*                                                              */
X/* ************************************************************ */
X
X/*
X  Main Program:  Gets arguments, initializes everything.  Then an
X  infinite loop which 
X            (a) creates the maze and 
X	    (b) solves the maze.  
X  Exit is by an external abort (like a ^C or a kill), or program request 
X*/
X
X/* main module */
Xmain(argc, argv)
X     int     argc;
X     char  **argv;
X{
X  SetGlobalDefaults();
X  ScanArgs(argc, argv);
X  if (Please_Exit) Usage();
X  dd_initialize_window();
X  while (!Please_Exit)
X    {
X      /* define initial maze size, borders */
X      if (debug(8)) fprintf(stderr, "-> init maze\n");
X      Set_Maze_Sizes();
X      Initialize_Maze();
X      Continue_If_Restart();
X      if (debug(8)) fprintf(stdout, "%s\n",spec());
X            
X      /* change the display */
X      if (debug(8)) fprintf(stderr, "-> change color map\n");
X      Make_New_Color_Map();
X      Clear_Window();
X      Continue_If_Restart();
X      
X      if (debug(8)) fprintf(stderr, "-> maze border\n");
X      Draw_Maze_Border();
X      Continue_If_Restart();
X      
X      if (debug(8)) fprintf(stderr, "-> create maze\n");
X      Create_Maze();
X      Continue_If_Restart();
X      
X      sleep(2);
X      
X      if (debug(8)) fprintf(stderr, "-> solve maze\n");
X      Solve_Maze();
X      Continue_If_Restart();
X      
X      sleep(2);
X    }
X  dd_terminate_window();
X}			       /* end of main() */
X
X
X/* ************************************************************ */
X/*                                                              */
X/*                                                              */
X/* ************************************************************ */
X
X/*
X  Argument processing.  If invalid arguments, print Usage message.
X  For all arguments, process each one.
X  For each argument, process each character in the argument.
X  If an argument seems to make no sense to us, ask the device support
X*/
X
XUsage()
X{
X  fprintf(stderr, "usage: maze\n");
X  exit(1);
X}			       /* end of Usage() */
X
X
XScanArgs(argc, argv)
X     int     argc;
X     char  **argv;
X{
X  enterprocedure("ScanArgs");
X  argc--, argv++ /* skip program name */ ;
X  while (argc > 0)
X    {
X      if (**argv == '-')
X	ScanOneArgument(*argv);
X      else dd_scan_arg(*argv);
X      argc--, argv++;
X    }
X}			       /* end of ScanArgs() */
X
X
XScanOneArgument(option)
X     char   *option;
X{
X  enterprocedure("ScanOneArgument");
X  /* check each character of the option list for its meaning. */
X  
X  if (*++option != '\0')
X    switch (*option)
X      {
X	
X      case 'd':      /* debug option */
X	DebugLevel = atoi(&option[1]);
X	if (DebugLevel <= 0)
X	  DebugLevel = 255;
X	break;
X	
X      default: 
X	dd_scan_arg(--option);
X      }
X}			       /* end of ScanOneArgument() */
X
X
X
X/* ************************************************************ */
X/*                                                              */
X/*  Color Map code                                              */
X/*                                                              */
X/* ************************************************************ */
X
X
Xstruct RGBColor DarkColors[] =
X{
X  { 0, 0, 0},
X  {47, 47, 79}, {47, 79, 47}, {79, 47, 47},
X  {47, 79, 79}, {79, 47, 79}, {79, 79, 47},
X  {84, 84, 84},
X  {111, 66, 66}, {66, 111, 66}, {66, 66, 111}
X};
X
Xstruct RGBColor LightColors[] =
X{
X  {107, 142, 35},   {107, 35, 142},   {142, 107, 35},
X  {142, 35, 107},   {142, 35, 35},    {35, 107, 142},
X  {35, 142, 107},   {35, 142, 35},    {35, 35, 142},
X  {159, 159, 95},   {159, 95, 159},   {95, 159, 159},
X  {168, 168, 168},  {143, 143, 188},  {143, 188, 143},
X  {188, 143, 143},  {153, 204, 50},   {153, 50, 204},
X  {204, 127, 50},   {204, 50, 153},   {204, 50, 50},
X  {50, 153, 204},   {50, 204, 153},   {50, 204, 50},
X  {50, 50, 204},    {112, 147, 219},  {112, 219, 147},
X  {112, 219, 219},  {147, 112, 219},  {147, 219, 112},
X  {191, 216, 216},  {216, 191, 216},  {216, 216, 191},
X  {219, 112, 147},  {219, 112, 219},  {219, 147, 112},
X  {219, 219, 112},  {173, 234, 234},  {234, 173, 234},
X  {234, 234, 173},  {0, 0, 255},      {0, 127, 255},
X  {0, 255, 0},      {0, 255, 127},    {0, 255, 255},
X  {127, 255, 0},    {255, 0, 0},      {255, 0, 127},
X  {255, 0, 255},    {255, 127, 0},    {255, 255, 0},
X  {255, 255, 255}
X};
X
X#define NumberOfDarkColors (sizeof(DarkColors)/sizeof(struct RGBColor))
X#define NumberOfLightColors (sizeof(LightColors)/sizeof(struct RGBColor))
X
XBoolean ColorWindows;
X
X/* ************************************************************ */
X/*                                                              */
X
X#define COLOR_MAP_SIZE	4
Xu_char rmap[COLOR_MAP_SIZE] = {0,255,255,255};
Xu_char gmap[COLOR_MAP_SIZE] = {0,255,255,255};
Xu_char bmap[COLOR_MAP_SIZE] = {0,255,255,255};
X
X#define ColorSum(i) (rmap[i]+gmap[i]+bmap[i])
X
X/* ************************************************************ */
X/*                                                              */
X
XMake_New_Color_Map()	       /* make the colormap */
X{
X  short   RandomColor;
X  
X  enterprocedure("Make_New_Color_Map");
X
X  if (!ColorWindows)
X    {
X      ColorBack = 0;     /* reset values for black/white device */
X      ColorWall = 1;
X      ColorPath = 1;
X      ColorLogo = 1;
X      
X      rmap[ColorBack] = 0;/* black */
X      gmap[ColorBack] = 0;
X      bmap[ColorBack] = 0;
X      
X      rmap[ColorWall] = 255;/* white */
X      gmap[ColorWall] = 255;
X      bmap[ColorWall] = 255;
X    }
X  else
X    {
X      /* for a color display, choose a dark background with the rest light */
X      RandomColor = get_random(NumberOfDarkColors);
X      rmap[ColorBack] = DarkColors[RandomColor].r;
X      gmap[ColorBack] = DarkColors[RandomColor].g;
X      bmap[ColorBack] = DarkColors[RandomColor].b;
X      
X      /* choose a Wall color that is "enough" brigher than the Back */
X      do
X	{
X	  RandomColor = get_random(NumberOfLightColors);
X	  rmap[ColorWall] = LightColors[RandomColor].r;
X	  gmap[ColorWall] = LightColors[RandomColor].g;
X	  bmap[ColorWall] = LightColors[RandomColor].b;
X	} while (ColorSum(ColorWall) < 60 + 2 * ColorSum(ColorBack));
X      
X      /* choose any light color for the Path */
X      RandomColor = get_random(NumberOfLightColors);
X      rmap[ColorPath] = LightColors[RandomColor].r;
X      gmap[ColorPath] = LightColors[RandomColor].g;
X      bmap[ColorPath] = LightColors[RandomColor].b;
X      
X      /* choose any light color for the Logo */
X      RandomColor = get_random(NumberOfLightColors);
X      rmap[ColorLogo] = LightColors[RandomColor].r;
X      gmap[ColorLogo] = LightColors[RandomColor].g;
X      bmap[ColorLogo] = LightColors[RandomColor].b;
X    }
X
X  dd_set_new_color_map();
X  
X  if (debug(8))
X    {
X      fprintf(stderr, "Back color is %d,%d,%d\n",
X	      rmap[ColorBack], gmap[ColorBack], bmap[ColorBack]);
X      fprintf(stderr, "Wall color is %d,%d,%d\n",
X	      rmap[ColorWall], gmap[ColorWall], bmap[ColorWall]);
X      fprintf(stderr, "Path color is %d,%d,%d\n",
X	      rmap[ColorPath], gmap[ColorPath], bmap[ColorPath]);
X      fprintf(stderr, "Logo color is %d,%d,%d\n",
X	      rmap[ColorLogo], gmap[ColorLogo], bmap[ColorLogo]);
X    }
X}			       /* end of Make_New_Color_Map() */
FRIDAY_NIGHT
echo extracting - main.h
sed 's/^X//' > main.h << 'FRIDAY_NIGHT'
X/* ************************************************************ */
X
X/*	main.h		main maze program (header file) 	*/
X
X/*	
X
X  Generate a random maze and then solve it.
X	
X*/
X
X/*  original version by Martin Weiss, Sun Microsystems, 6/21/85 */
X/*  known bug ... problem when iconic cause core dump           */
X/*  Reorganized and rewritten; James Peterson, 17 Nov 1987      */
X
X/* ************************************************************ */
X/*                                                              */
X/*  Standard Initializations                                    */
X/*                                                              */
X/* ************************************************************ */
X
X#include <stdio.h>
X#include <sys/types.h>	       /* for u_char */
X
X#define false   0
X#define true    1
Xtypedef short   Boolean /* standard Boolean type */ ;
X
X/* ************************************************************ */
X/*                                                              */
X/*  Options                                                     */
X/*                                                              */
X/* ************************************************************ */
X
Xshort DebugLevel /* standard debug option */ ;
X#define debug(n) (DebugLevel & (n))
X
X#define enterprocedure(name) if (DebugLevel & 64) EnterProcedure(name);
X
X/* ************************************************************ */
X/*                                                              */
X/*  Restart code                                                */
X/*                                                              */
X/* ************************************************************ */
X
X/* should anything occur that damages the screen, dd_restart returns true */
X
XBoolean dd_restart() /* forward type declaration */ ;
X
X#define Return_If_Restart() if (dd_restart(false)) return
X#define Continue_If_Restart() if (dd_restart(true))              \
X                                  {dd_reset_restart();continue;} \
X                              if (Please_Idle) dd_idle();
X       
X
XBoolean Please_Exit; /* set if we want to exit maze */
XBoolean Please_Idle; /* set to cause maze to wait for another event */
X
Xshort InputFD;
X
X/* ************************************************************ */
X/*                                                              */
X/*                                                              */
X/* ************************************************************ */
X
X/* the following Color variables are indexes into a 4 element color
X   map.  If the display is Black/White, we reset them to be only 0 or 1 */
X
Xtypedef short   ColorIndex /* actually only need 0..3 */ ;
X
X
XColorIndex ColorBack;  /* default values for color device */
XColorIndex ColorWall;
XColorIndex ColorPath;
XColorIndex ColorLogo;
X
X
X/* ************************************************************ */
X/*                                                              */
X/*  Logo definition variables                                   */
X/*                                                              */
X/* ************************************************************ */
X
X/*
X  For commercial reasons, we include a logo in the maze.
X  The logo location, size, and image are controlled by the
X  logo routines (Set_Logo_Location and dd_draw_logo).  The
X  important thing from the maze point of view, is that we need
X  to know how many and which squares are being used by the logo.
X  They should be initialized to PREVIOUS_VISIT.
X*/
X
X#define LOGO_PIXELS_X 64       /* size of logo, in pixels */
X#define LOGO_PIXELS_Y 64  
X
X#define LOGO_BORDER_X 6	       /* border, in pixels */
X#define LOGO_BORDER_Y 6
X
X
X/* ************************************************************ */
X/*                                                              */
X/*  Color Map variables                                         */
X/*                                                              */
X/* ************************************************************ */
X
X
Xstruct RGBColor
X{
X    short   r /* red   */ ;
X    short   g /* green */ ;
X    short   b /* blue  */ ;
X};
X
X
XBoolean ColorWindows;
X
X/* ************************************************************ */
X/*                                                              */
X
X#define COLOR_MAP_SIZE	4
Xu_char rmap[COLOR_MAP_SIZE];
Xu_char gmap[COLOR_MAP_SIZE];
Xu_char bmap[COLOR_MAP_SIZE];
X
X/* ************************************************************ */
X/* forward type declaration */
X
Xchar   *sprintf();
Xshort   get_random ();
XBoolean PollFile();
Xchar   *spec();
FRIDAY_NIGHT
echo extracting - maze.c
sed 's/^X//' > maze.c << 'FRIDAY_NIGHT'
X/* ************************************************************ */
X
X/*	maze.c		graphical maze program			*/
X
X/*	
X  
X  Generate a random maze and then solve it.
X  
X*/
X
X
X/* ************************************************************ */
X
X#include "main.h"
X#include "maze.h"
X
Xshort   Speed = 0; /* speed (or slowness) of maze solving */
X     
X/* does maze cover entire window or are there unreachable parts ? */
XBoolean CompleteMaze = true;
X     
X     
X/* ************************************************************ */
X/*                                                              */
X/*  Maze size definition                                        */
X/*                                                              */
X/* ************************************************************ */
X
X/*
X  The maze is stored internally as a large two dimensional array.
X  Each element of the array gives the properties of that square of
X  the maze.
X*/
X
X
X#define MAX_MAZE_SIZE_X	100    /* maximum number of squares in the maze */
X#define MAX_MAZE_SIZE_Y	100
X
Xu_short maze[MAX_MAZE_SIZE_X][MAX_MAZE_SIZE_Y];
X
X/* ************************************************************ */
X/*                                                              */
X/*                                                              */
X/* ************************************************************ */
X
X/*
X  The maze size is parameterized.  We need to determine the size of
X  each square, in pixels, and the number of squares.  Plus, we want a
X  border around the outside of the maze. And each square of the maze
X  has a (wall or door) [1 pixel], a border between the wall/door and
X  the interior of the square and the interior.  The path through the
X  maze fills the interior of its squares.
X*/
X
X/* border around the maze */
X#define MAZE_BORDER_X        20/* desired number of border pixels */
X#define MAZE_BORDER_Y        20
X
X
X/* minimum reasonable square size (in pixels) 2 borders plus wall plus path*/
X#define MIN_SQ_SIZE_X	(SQ_BORDER+1)
X#define MIN_SQ_SIZE_Y	(SQ_BORDER+1)
X
X/* default size of square, in pixels -- actual may be larger or smaller */
X#define SQ_SIZE_X	10     /* normal square size (in pixels) */
X#define SQ_SIZE_Y	10     /* MIN_SQ_SIZE ... and up */
X
X
XTuple maze_size;	       /* number of squares in the maze */
X
X
X/* Location of the start and end of the maze */
XLocation Start_Square;	       /* location of start square */
XLocation End_Square;	       /* location of end square */
X
X
X/* ************************************************************ */
X/*                                                              */
X/*                                                              */
X/* ************************************************************ */
X
XSet_Maze_Defaults()
X{
X  enterprocedure("Set_Maze_Defaults");
X  border.x = MAZE_BORDER_X;
X  border.y = MAZE_BORDER_Y;
X  
X  square_size.x = SQ_SIZE_X;
X  square_size.y = SQ_SIZE_Y;
X  
X}
X
Xchar   *spec ()
X{
X  static char text[20];
X  
X  enterprocedure("spec");
X  sprintf(text, "%dx%d(%d)", square_size.x, square_size.y, Speed);
X  return(text);
X}
X
X/* ************************************************************ */
X/*                                                              */
X/*  Maze definition routines                                    */
X/*                                                              */
X/* ************************************************************ */
X
XDefineScreenSize(x, y)
X     short   x;
X     short   y;
X{
X  enterprocedure("DefineScreenSize");
X  screen_size.x = x;
X  screen_size.y = y;
X}
X
X
X/*  Given the screen_size, compute maze_size, square_size, and border */
X
XSet_Maze_Sizes()
X{
X  Boolean okay;
X  
X  enterprocedure("Set_Maze_Sizes");
X  if (debug(2))
X    fprintf(stderr, "screen size is %d x %d\n", 
X	    screen_size.x, screen_size.y);
X  
X  /* Brownian motion on the square_size in x and y directions */
X  {
X    short   n = get_random (10);
X    if (n < 3)
X      IncreaseSquareSize(1, 1);
X    else if (n > 6)
X      IncreaseSquareSize(-1, -1);
X  }
X  
X  /* Brownian motion on the speed of the drawing */
X  {
X    short   n = get_random (10);
X    if (n < 3)
X      Speed += 1;
X    else if (n > 6)
X      Speed -= 1;
X  }
X  
X  /* small probablity that the maze is incomplete */
X  CompleteMaze = (get_random(100) > 5);
X  
X  
X  /* compute maze size: number of squares (maze_size) and size of squares */
X  do
X    {
X      okay = true;
X      maze_size.x = (screen_size.x - MAZE_BORDER_X) / square_size.x;
X      maze_size.y = (screen_size.y - MAZE_BORDER_Y) / square_size.y;
X      
X      /* Check if the maze is too small */
X      if (maze_size.x < 3 || maze_size.y < 3)
X	{
X	  /* maze is too small, try to make the squares smaller, this
X	     will make the maze larger */
X	  if (square_size.x <= MIN_SQ_SIZE_X
X	      || square_size.y <= MIN_SQ_SIZE_Y)
X	    {
X	      fprintf(stderr, "maze too small (%d x %d)\n",
X		      maze_size.x, maze_size.y);
X	      exit(1);
X	    }
X	  IncreaseSquareSize(-1, -1);
X	  okay = false;
X	}
X      
X      /* Check if maze is too large */
X      /* make the squares larger, this will reduce the size of the maze */
X      if (maze_size.x >= MAX_MAZE_SIZE_X)
X	{
X	  IncreaseSquareSize(1, 0);
X	  okay = false;
X	}
X      if (maze_size.y >= MAX_MAZE_SIZE_Y)
X	{
X	  IncreaseSquareSize(0, 1);
X	  okay = false;
X	}
X    }
X  while (!okay);
X  
X  /* recompute borders to include any extra pixels due to rounding */
X  border.x = (screen_size.x - maze_size.x * square_size.x) / 2;
X  border.y = (screen_size.y - maze_size.y * square_size.y) / 2;
X  
X  if (debug(2))
X    {
X      fprintf(stderr, "square size is %d x %d\n",
X	      square_size.x, square_size.y);
X      fprintf(stderr, "border size is %d x %d\n",
X	      border.x, border.y);
X      fprintf(stderr, "maze size is %d x %d\n",
X	      maze_size.x, maze_size.y);
X    }
X  
X}			       /* end of Set_Maze_Sizes() */
X
XIncreaseSquareSize(dx, dy)
X     short   dx, dy;
X{
X  enterprocedure("IncreaseSquareSize");
X  square_size.x += dx;
X  if (square_size.x < MIN_SQ_SIZE_X)
X    square_size.x = MIN_SQ_SIZE_X;
X  square_size.y += dy;
X  if (square_size.y < MIN_SQ_SIZE_Y)
X    square_size.y = MIN_SQ_SIZE_Y;
X}
X
X
X/* ************************************************************ */
X/*                                                              */
X/*  Maze Element Properties                                     */
X/*                                                              */
X/* ************************************************************ */
X
X/*
X  Each Maze element has a definition.  The definition tells us if
X  there are walls or doors on the top, bottom, left and right.
X  In addition, elements may be on the edge, with a wall next to them
X  or be the start or end of the maze.
X  
X  We keep two sets with each element: 
X  
X  the set of walls around it
X  
X  the set of doors around it
X  
X  If there is a wall in a particular direction (top, right, bottom, left),
X  there is obviously no wall in that direction.  But we can have three
X  states for each direction of a square: wall, door, not yet defined.
X  We determine if there is a wall by WALL, if there is a door by
X  DOOR.  If neither is set, it is not yet defined.
X  
X  And as we build the maze, we need to know if a square is or is
X  not in the process of being defined (PREVIOUS_VISIT).
X  
X  This representation requires 9 bits per square, which we store in a short.
X*/
X
X#define OPPOSITE(x)   (((x)+2) % 4)
X
X#define DOOR(direction)    (0x008 >> (direction))
X#define WALL(direction)    (0x080 >> (direction))
X#define PREVIOUS_VISIT	    0x100
X
X#define SetDOOR(x,y,direction)   maze[x][y] |= DOOR(direction)
X#define TestDOOR(x,y,direction) (maze[x][y] & DOOR(direction))
X
X#define SetWALL(x,y,direction)   maze[x][y] |= WALL(direction)
X#define ClearWALL(x,y,direction) maze[x][y] &= ~WALL(direction)
X#define TestWALL(x,y,direction) (maze[x][y] & WALL(direction))
X
X#define SetVISIT(x,y)   maze[x][y] |= PREVIOUS_VISIT
X#define TestVISIT(x,y)  maze[x][y] &  PREVIOUS_VISIT
X  
XTuple move_delta[4] = {
X			  { 0, -1 },
X			  { 1,  0 },	
X			  { 0,  1 },
X			  {-1,  0 }
X		      };
X
X/* ************************************************************ */
X
X/* define the surrounding wall and start/end squares            */
X
XInitialize_Maze()
X{
X  register short  i;
X  register short  j;
X  register    Direction wall;
X  
X  enterprocedure("Initialize_Maze");
X  /* initialize all squares */
X  for (i = 0; i < maze_size.x; i++)
X    for (j = 0; j < maze_size.y; j++)
X      maze[i][j] = 0;
X  
X  
X  /* top wall */
X  for (i = 0; i < maze_size.x; i++)
X    SetWALL(i, 0, TOP);
X  
X  /* right wall */
X  for (j = 0; j < maze_size.y; j++)
X    SetWALL(maze_size.x - 1, j, RIGHT);
X  
X  /* bottom wall */
X  for (i = 0; i < maze_size.x; i++)
X    SetWALL(i, maze_size.y - 1, BOTTOM);
X  
X  /* left wall */
X  for (j = 0; j < maze_size.y; j++)
X    SetWALL(0, j, LEFT);
X  
X  /* set start square */
X  wall = get_random(4);
X  switch (wall)
X    {
X    case TOP: 
X      Start_Square.x = get_random(maze_size.x);
X      Start_Square.y = 0;
X      break;
X    case RIGHT: 
X      Start_Square.x = maze_size.x - 1;
X      Start_Square.y = get_random(maze_size.y);
X      break;
X    case BOTTOM: 
X      Start_Square.x = get_random(maze_size.x);
X      Start_Square.y = maze_size.y - 1;
X      break;
X    case LEFT: 
X      Start_Square.x = 0;
X      Start_Square.y = get_random(maze_size.y);
X      break;
X    }
X  SetDOOR(Start_Square.x, Start_Square.y, wall);
X  ClearWALL(Start_Square.x, Start_Square.y, wall);
X  Start_Square.dir = wall;
X  if (debug(2))
X    fprintf(stderr, "start location is %d,%d\n",
X	    Start_Square.x, Start_Square.y);
X  
X  /* set end square */
X  wall = OPPOSITE(wall);
X  switch (wall)
X    {
X    case TOP: 
X      End_Square.x = get_random(maze_size.x);
X      End_Square.y = 0;
X      break;
X    case RIGHT: 
X      End_Square.x = maze_size.x - 1;
X      End_Square.y = get_random(maze_size.y);
X      break;
X    case BOTTOM: 
X      End_Square.x = get_random(maze_size.x);
X      End_Square.y = maze_size.y - 1;
X      break;
X    case LEFT: 
X      End_Square.x = 0;
X      End_Square.y = get_random(maze_size.y);
X      break;
X    }
X  SetDOOR(End_Square.x, End_Square.y, wall);
X  ClearWALL(End_Square.x, End_Square.y, wall);
X  End_Square.dir = wall;
X  if (debug(2))
X    fprintf(stderr, "end location is %d,%d\n", End_Square.x, End_Square.y);
X  
X  /* set logo */
X  Set_Logo_Location();
X}			       /* end of Initialize_Maze() */
X
X/* ************************************************************ */
X/*                                                              */
X/*  Logo definition routines                                    */
X/*                                                              */
X/* ************************************************************ */
X
X/*
X  For commercial reasons, we include a logo in the maze.
X  The logo location, size, and image are controlled by the
X  logo routines (Set_Logo_Location and dd_draw_logo).  The
X  important thing from the maze point of view, is that we need
X  to know how many and which squares are being used by the logo.
X  They should be initialized to PREVIOUS_VISIT.
X*/
X
X
XTuple logo_size;	       /* size of logo, in squares */
XPoint logo_location;	       /* location of logo, in squares */
XTuple logo_border;
X
X
XSet_Logo_Location()
X{
X  register short  i;
X  register short  j;
X  
X  enterprocedure("Set_Logo_Location");
X  /* compute logo size in squares; check that there is room */
X  logo_size.x = (LOGO_PIXELS_X + square_size.x - 1) / square_size.x;
X  logo_size.y = (LOGO_PIXELS_Y + square_size.y - 1) / square_size.y;
X  logo_border.x = ((logo_size.x * square_size.x) - LOGO_PIXELS_X) / 2;
X  logo_border.y = ((logo_size.y * square_size.y) - LOGO_PIXELS_Y) / 2;
X  
X  if ((maze_size.x <= logo_size.x + LOGO_BORDER_X)
X      || (maze_size.y <= logo_size.y + LOGO_BORDER_Y))
X    logo_location.y = logo_location.x = -1 /* no logo */ ;
X  else
X    {
X      /* compute location of logo */
X      logo_location.x = get_random(maze_size.x - logo_size.x - LOGO_BORDER_X)
X	+ LOGO_BORDER_X / 2;
X      logo_location.y = get_random(maze_size.y - logo_size.y - LOGO_BORDER_Y)
X	+ LOGO_BORDER_Y / 2;
X      
X      /* set the squares occupied by the logo to not be part of maze */
X      for (i = 0; i < logo_size.x; i++)
X	for (j = 0; j < logo_size.y; j++)
X	  SetVISIT(logo_location.x + i, logo_location.y + j);
X      
X    }
X  
X  if (debug(2))
X    fprintf(stderr, "logo location is %d,%d\n",
X	    logo_location.x, logo_location.y);
X  
X}			       /* end of Set_Logo_Location() */
X
X
X/* draw the logo; offset by the maze border and the logo border */
XDrawLogo()
X{
X  enterprocedure("DrawLogo");
X  dd_draw_logo(border.x + square_size.x * logo_location.x + logo_border.x,
X	       border.y + square_size.y * logo_location.y + logo_border.y,
X	       ColorLogo);
X}
X
X
X/* ************************************************************ */
X/*                                                              */
X/*                                                              */
X/* ************************************************************ */
X
XDraw_Maze_Border()	       /* draw the maze outline */
X{
X  register short  i;
X  register short  j;
X  
X  enterprocedure("Draw_Maze_Border");
X  Begin_Draw_Lines();
X  for (i = 0; i < maze_size.x; i++)
X    {
X      if (TestWALL(i, 0, TOP))
X	Draw_Line(i, 0, i + 1, 0);
X      if (TestWALL(i, maze_size.y - 1, BOTTOM))
X	Draw_Line(i, maze_size.y, i + 1, maze_size.y);
X    }
X  
X  for (j = 0; j < maze_size.y; j++)
X    {
X      if (TestWALL(maze_size.x - 1, j, RIGHT))
X	Draw_Line(maze_size.x, j, maze_size.x, j + 1);
X      if (TestWALL(0, j, LEFT))
X	Draw_Line(0, j, 0, j + 1);
X    }
X  End_Draw_Lines();
X  
X  dd_lock_screen();
X  if (logo_location.x != -1)
X    DrawLogo();
X  
X  Draw_Solid_Square(Start_Square.x, Start_Square.y,
X		    Start_Square.dir, ColorPath);
X  Draw_Solid_Square(End_Square.x, End_Square.y,
X		    End_Square.dir, ColorWall);
X  
X  dd_unlock_screen();
X}			       /* end of Draw_Maze_Border() */
X
X
X/* ************************************************************ */
X/*                                                              */
X/*                                                              */
X/* ************************************************************ */
X
X/*
X  The maze that is created is basically a tree.  We start with the
X  root of the tree being the Start Square.  For any given square,
X  we check each side to determine if it is already a wall or door,
X  or still undefined.  If it is undefined, it could be a wall or a
X  door.  
X  
X  * It is a wall if we have already defined the square on the
X  other side of it.  This occurs if we have not yet finished defining
X  all the walls/doors around that other square, which is because that
X  other square is still on the current path.
X  
X  * Otherwise, we choose one of the undefined wall/doors for this square
X  and make it a door.
X  
X  This continues until we have defined all walls/doors for each square.
X  Effectively this is a depth first traversal of the entire maze array.
X  
X*/
X
X
X/* create a maze layout given the initialized maze */
XCreate_Maze()
X{
X  Point current_square;
X  Direction newdoor;
X  
X  enterprocedure("Create_Maze");
X  Begin_Draw_Lines();
X  ClearPath();
X  current_square.x = Start_Square.x;
X  current_square.y = Start_Square.y;
X  newdoor = Start_Square.dir;
X  do
X    {
X      /* note that we have/are processing the current square */
X      SetVISIT(current_square.x, current_square.y);
X      
X      /* pick a new door (if possible) for the current square */
X      newdoor = Choose_Door(current_square.x, current_square.y);
X      while (newdoor == -1)
X	{
X	  /* no more doors ... backup */
X	  if (EmptyPath())
X	    {
X	      End_Draw_Lines();
X	      return;/* done ... return */
X	    }
X	  
X	  /* back up to previous square and see if more doors for it */
X	  PopPath(&current_square.x, &current_square.y, &newdoor);
X	  newdoor = Choose_Door(current_square.x, current_square.y);
X	}
X      Return_If_Restart();
X      
X      /* remember which square we are at */
X      AddToPath(current_square.x, current_square.y, newdoor);
X      
X      /* mark the door for this square */
X      SetDOOR(current_square.x, current_square.y, newdoor);
X      
X      /* move to the new square */
X      current_square.x += move_delta[newdoor].x;
X      current_square.y += move_delta[newdoor].y;
X      
X      /* mark the door also for the neighbor on the other side */
X      SetDOOR(current_square.x, current_square.y, OPPOSITE(newdoor));
X      
X    } while (!Please_Exit);
X}			       /* end of Create_Maze() */
X
X/* ************************************************************ */
X/*                                                              */
X/*                                                              */
X/* ************************************************************ */
X
X/*
X  To compute a new door, we need a list of each direction which
X  is a candidate to become a door.
X*/
X
XDirection candidates[3];
Xshort   num_candidates;
X
X
XChoose_Door(x, y)	       /* pick a new path */
X     short   x;
X     short   y;
X{
X  enterprocedure("Choose_Door");
X  num_candidates = 0;
X  
X  Check_Square(x, y, TOP, 0, -1);
X  Check_Square(x, y, RIGHT, 1, 0);
X  Check_Square(x, y, BOTTOM, 0, 1);
X  Check_Square(x, y, LEFT, -1, 0);
X  
X  if (num_candidates == 0)
X    return(-1);
X  if (num_candidates == 1)
X    return(candidates[0]);
X  return(candidates[get_random(num_candidates)]);
X}			       /* end of Choose_Door() */
X
X/* ************************************************************ */
X
X
XCheck_Square(x, y, wall, xdelta, ydelta)
X     short   x;
X     short   y;
X     Direction wall;
X{
X  enterprocedure("Check_Square");
X  if (TestDOOR(x, y, wall))
X    return;
X  
X  if (TestWALL(x, y, wall))
X    return;
X  
X  /* check if the neighboring square has been visited; 
X     if so, make a wall between them and us. */
X  if (TestVISIT(x + xdelta, y + ydelta)
X
X  /* also, if the maze need not be complete, 
X     make a wall just for perversity sometimes */
X      || (!CompleteMaze && (get_random(100) < 30)))
X
X    {
X      SetWALL(x, y, wall);
X      SetWALL(x + xdelta, y + ydelta, OPPOSITE(wall));
X      Draw_Wall(x, y, wall);
X      return;
X    }
X  candidates[num_candidates] = wall;
X  num_candidates += 1;
X}
X
X/* ************************************************************ */
X
X
XDraw_Wall(i, j, dir)	       /* draw a single wall */
X     short   i;
X     short   j;
X     Direction dir;
X{
X  enterprocedure("Draw_Wall");
X  switch (dir)
X    {
X    case TOP: 	       /* wall at top of i,j */
X      Draw_Line(i, j, i + 1, j);
X      break;
X      
X    case RIGHT:        /* wall at right of i,j */
X      Draw_Line(i + 1, j, i + 1, j + 1);
X      break;
X      
X    case BOTTOM:       /* wall at left of i,j */
X      Draw_Line(i, j + 1, i + 1, j + 1);
X      break;
X      
X    case LEFT: 	       /* wall at bottom of i,j */
X      Draw_Line(i, j, i, j + 1);
X      break;
X    }
X}			       /* end of Draw_Wall */
X
X/* ************************************************************ */
X/*                                                              */
X/*                                                              */
X/* ************************************************************ */
X
X
XSolve_Maze()		       /* solve it with graphical feedback */
X{
X  Point current_square;
X  Direction dir;
X  
X  enterprocedure("Solve_Maze");
X  SetWALL(Start_Square.x, Start_Square.y, Start_Square.dir);
X  SetWALL(End_Square.x, End_Square.y, End_Square.dir);
X  
X  /* initialize search path */
X  ClearPath();
X  
X  /* set current square and direction */
X  current_square.x = Start_Square.x;
X  current_square.y = Start_Square.y;
X  dir = -1;
X  
X  /* start search */
X  dd_lock_screen();
X  while (current_square.x != End_Square.x || current_square.y != End_Square.y)
X    {
X      dir += 1;
X      if (dir >= 4)
X	{
X	  if (EmptyPath())
X	    return;
X	  PopPath(&current_square.x, &current_square.y, &dir);
X	  Draw_Solid_Square(current_square.x, current_square.y, 
X			    dir, ColorBack);
X	  if (Speed > 0) Wait(Speed);
X	  Return_If_Restart();
X	}
X      else
X	{
X	  /* check (a) if the way is not blocked in the direction that
X	     we are going and (b) if we are not going back where we
X	     just came from */
X	  
X	  if (TestWALL(current_square.x, current_square.y, dir))
X	    continue;
X	  
X	  {
X	    register short  previous = PathDir ();
X	    if (previous != -1 && dir == OPPOSITE(previous))
X	      continue;
X	  }
X	  
X	  Draw_Solid_Square(current_square.x, current_square.y, dir, ColorPath);
X	  if (Speed > 0) Wait(Speed);
X	  AddToPath(current_square.x, current_square.y, dir);
X	  current_square.x += move_delta[dir].x;
X	  current_square.y += move_delta[dir].y;
X	  dir = -1;
X	}
X    }
X  dd_unlock_screen();
X}			       /* end of Solve_Maze() */
X
FRIDAY_NIGHT
echo extracting - maze.h
sed 's/^X//' > maze.h << 'FRIDAY_NIGHT'
X/* ************************************************************ */
X
X/*	maze.h		maze support (header file)		*/
X
X/*
X  definitions and variables shared by maze.c and its supporting
X  routines in path.c and draw.c
X*/
X
X/* ************************************************************ */
X/*                                                              */
X/*                                                              */
X/* ************************************************************ */
X
X/*
X    To represent the maze, we need the following types:
X
X    (a) a point, in pixels.
X    (b) a point, in squares of the maze.
X    (c) a direction, (up, down, left, right).
X    (d) a location, which is a point and a direction.
X*/
X
Xstruct tuple
X{
X    short   x;
X    short   y;
X};
X
Xtypedef struct tuple    Tuple;
X
Xtypedef struct tuple    Point;
X
Xtypedef short   Direction;
X
Xstruct location
X{
X    short   x,
X            y;
X            Direction dir;
X};
X
Xtypedef struct location Location;
X
X/* ************************************************************ */
X
X/* bits to use to define the four directions in a square, for doors/walls */
X#define TOP        0
X#define RIGHT      1
X#define BOTTOM     2
X#define LEFT       3
X
X/* border around the path in a square */
X#define HALF_BORDER 2
X/* total border within a square; between wall/door and path */
X#define SQ_BORDER (2*HALF_BORDER+1)
X
X/* ************************************************************ */
X/*                                                              */
X/*                                                              */
X/* ************************************************************ */
X
X
X/* actual screen size (in pixels) */
XPoint screen_size;
X
X/* actual number of border pixels */
XTuple   border;
X
X/* size of each square (in pixels) */
XTuple   square_size;
X
X
X/* ************************************************************ */
X/*                                                              */
X/*                                                              */
X/* ************************************************************ */
X
XBoolean EmptyPath();
XDirection PathDir();
FRIDAY_NIGHT
echo extracting - path.c
sed 's/^X//' > path.c << 'FRIDAY_NIGHT'
X/* ************************************************************ */
X
X/*	path.c		path support for graphical maze program	*/
X
X/*	
X  
X  Routines to support defining and modifying a path
X  through the maze
X  
X*/
X
X/*  Reorganized and rewritten; James Peterson, 17 Nov 1987      */
X
X/* ************************************************************ */
X/*                                                              */
X/*  Standard Initializations                                    */
X/*                                                              */
X/* ************************************************************ */
X
X#include "main.h"
X#include "maze.h"
X
X/* ************************************************************ */
X/*                                                              */
X/*                                                              */
X/* ************************************************************ */
X
X/*
X  As we attempt to create or solve the maze, we must keep a history of our
X  current path through the maze.  This lets us back up and try again
X  if we find that we have taken a wrong turn.
X*/
X
Xstruct pathelement
X{
X  struct pathelement *next;
X  short   x;
X  short   y;
X  Direction dir;
X};
X
Xtypedef struct pathelement *PathElement;
X
X
XPathElement FreePathElementList = NULL;
X
XPathElement Path = NULL;
Xlong    PathLength = 0;
X
X
X/* ************************************************************ */
X
X/* routines to create and free Path Element storage */
X
Xextern char *malloc();
X
X
XPathElement NewPathElement()
X{
X  PathElement p;
X  
X  enterprocedure("NewPathElement");
X  if (FreePathElementList == NULL)
X    {
X      /* no free element, malloc another one */
X      p = (PathElement) malloc(sizeof(*p));
X      if (p == NULL)
X	{
X	  fprintf(stderr, "Not enough malloc space for path\n");
X	  exit(1);
X	}
X    }
X  else
X    {
X      p = FreePathElementList;
X      FreePathElementList = FreePathElementList->next;
X    }
X  return(p);
X}
X
XFreePathElement(p)
X     PathElement p;
X{
X  enterprocedure("FreePathElement");
X  p->next = FreePathElementList;
X  FreePathElementList = p;
X}
X
X/* ************************************************************ */
X
X/* routines to test for empty and empty the path */
X
XBoolean EmptyPath()
X{
X  enterprocedure("EmptyPath");
X  return(Path == NULL);
X}
X
XClearPath()
X{
X  PathElement p;
X  
X  enterprocedure("ClearPath");
X  if (debug(16))
X    fprintf(stderr, "ClearPath\n"), fflush(stderr);
X  for (p = Path; p != NULL; p = Path)
X    {
X      Path = Path->next;
X      FreePathElement(p);
X    }
X  PathLength = 0;
X}
X
X/* ************************************************************ */
X
X/* routines to add, look at, and remove elements from the path */
X
XAddToPath(x, y, dir)
X     short   x, y;
X     Direction dir;
X{
X  PathElement p;
X  
X  enterprocedure("AddToPath");
X  if (debug(16))
X    fprintf(stderr, "Add %d,%d,%d to path\n", x, y, dir);
X  p = NewPathElement();
X  p->x = x;
X  p->y = y;
X  p->dir = dir;
X  p->next = Path;
X  Path = p;
X  PathLength += 1;
X}
X
X
XDirection PathDir()
X{
X  enterprocedure("PathDir");
X  if (Path == NULL)
X    return(-1);
X  return(Path->dir);
X}
X
X
XPopPath(x, y, dir)
X     short  *x, *y;
X     Direction * dir;
X{
X  PathElement p;
X  
X  enterprocedure("PopPath");
X  if (Path == NULL)
X    return;
X  *x = Path->x;
X  *y = Path->y;
X  *dir = Path->dir;
X  if (debug(16))
X    fprintf(stderr, "Pop %d,%d,%d to path\n", *x, *y, *dir);
X  p = Path;
X  Path = Path->next;
X  FreePathElement(p);
X  PathLength -= 1;
X}
FRIDAY_NIGHT
echo extracting - suntool.c
sed 's/^X//' > suntool.c << 'FRIDAY_NIGHT'
X/* ************************************************************ */
X
X/*	suntool.c	graphical maze program (support)	*/
X
X/*	
X  
X  Support code for the maze program under the suntool window system
X
X  Interface:
X  
X  dd_Set_Defaults() -- Set any global variable defaults.  
X                       Called only once at beginning
X  
X  dd_scan_arg(option) -- called when the maze program has a command line option
X                         that it does not recognize. Can be used to specify
X			 device dependent options (like Geometry and Display).
X
X  dd_initialize_window() -- Create a window on the screen.  Must set the
X                            size of the window and tell if it is mono or color
X  
X  dd_terminate_window() -- Delete the window and any other resources.
X
X  dd_restart() -- Check if we need to restart the display, either because
X                  the display has been corrupted, or user input.
X
X  dd_idle() -- Wait until user wants to restart computation.
X
X  dd_reset_restart() -- reset whatever state caused dd_restart to return true
X  
X  dd_lock_screen() -- set up access to the window; lock and unlock are called
X                      alternatively, so that all drawing calls are between a
X                      call to lock and its following unlock.
X  
X  dd_unlock_screen() -- access is finished for now, unlock or flush output
X  
X  dd_set_new_color_map() -- global variables rmap, gmap, bmap define a new
X                            color map which will be used for the following
X                            operations.  Change color support as necessary.
X                            If we have only mono display, then the size of
X                            the color map is only 2, and the first two entries
X                            define black and white.
X  
X  dd_clear_window(x, y, w, h, fillcolor) -- clear the window.  x,y will be
X                            0,0 and w,h is the width and height of the window.
X			    The fillcolor is ColorBack -- the background color.
X			    This could be done with a dd_fill_rectangle (below)
X			    but is provided in case there is a special case
X			    clear-window command that is significantly faster
X			    than the general dd_fill-rectangle.
X
X  dd_draw_line(x1,y1,x2,y2,color) -- draw a line from x1,y1 to x2,y2 in the
X                                     given color.
X  
X  dd_fill_rectangle(x,y,w,h,color) -- fill the rectangle with origin x,y of
X                                      width w and height h with the color.
X  
X  dd_draw_logo(x,y,color) -- draw the logo at origin x,y in the color.  The
X                             logo is of width LOGO_PIXELS_X and height
X                             LOGO_PIXELS_Y (typically 64 x 64).
X  
X*/
X
X/*  Written; James Peterson, 17 Nov 1987      */
X
X/* ************************************************************ */
X/*                                                              */
X/*  Standard Initializations                                    */
X/*                                                              */
X/* ************************************************************ */
X
X#include "main.h"
X
X
X/* ************************************************************ */
X/*                                                              */
X/*  Device Dependent Code                                       */
X/*                                                              */
X/* ************************************************************ */
X
X
X#include <sunwindow/window_hs.h>
X#include <sunwindow/cms.h>
X#include <suntool/gfxsw.h>
X
X
Xstruct gfxsubwindow *gfx;
Xstruct rect pwrect;
X
X
XBoolean dd_check_lock();       /* forward type declaration */
X
X/* ************************************************************ */
X/*                                                              */
X/*                                                              */
X/* ************************************************************ */
X
Xdd_Set_Defaults()
X{
X  enterprocedure("dd_Set_Defaults");
X}
X
X
Xdd_scan_arg(option)
Xchar *option;
X{
X  fprintf(stderr, "maze: Bad option %s\n", option);
X  Please_Exit = true;
X}
X
X/* ************************************************************ */
X
Xdd_initialize_window()	       /* take over and initialize window */
X{
X  /* 
X    Must define:
X	    screen_size
X	    ColorWindows
X	    InputFD
X  */
X  
X  enterprocedure("dd_initialize_window");
X  InputFD = fileno(stdin);
X
X  /* get properties of graphics sub-window */
X  gfx = gfxsw_init(0, 0);
X  if (gfx == NULL)
X    {
X      fprintf(stderr, "Can't get graphics display window\n");
X      exit(1);
X    }
X  
X  /* get screen size */
X  DefineScreenSize(
X		   gfx->gfx_pixwin->pw_clipdata->pwcd_prmulti->pr_size.x,
X		   gfx->gfx_pixwin->pw_clipdata->pwcd_prmulti->pr_size.y
X		   );
X  
X  /* determine if we have a color screen or black and white */
X  ColorWindows = false;
X  if (gfx->gfx_pixwin->pw_pixrect->pr_ops == &gp1_ops)
X    ColorWindows = true;
X  if (gfx->gfx_pixwin->pw_pixrect->pr_ops == &cg1_ops)
X    ColorWindows = true;
X  if (gfx->gfx_pixwin->pw_pixrect->pr_ops == &cg2_ops)
X    ColorWindows = true;
X  
X  /* set the color map segment name */
X  {
X    char    cmsname[CMS_NAMESIZE];
X    (void) sprintf(cmsname, "maze%%10D", getpid());
X    pw_setcmsname(gfx->gfx_pixwin, cmsname);
X  }
X  
X  dd_set_new_color_map();
X  
X  pw_exposed(gfx->gfx_pixwin);
X  win_getrect(gfx->gfx_pixwin->pw_clipdata->pwcd_windowfd, &pwrect);
X}			       /* end of dd_initialize_window() */
X
X
Xdd_terminate_window()
X{
X  enterprocedure("dd_terminate_window");
X}
X
Xdd_idle()
X{
X  enterprocedure("dd_idle");
X  Please_Idle = false;
X}
X  
X
X
X/* ************************************************************ */
X/*                                                              */
X/*                                                              */
X/* ************************************************************ */
X
Xstatic  Boolean Restart = false;
X
XBoolean dd_restart(full)
X     Boolean full;
X{
X  enterprocedure("dd_restart");
X  /* check if there is any reason to restart */
X  /* for example, do we have input on stdin ? */
X  
X  /* if full is true, be sure to check completely */
X  if (PollFile(stdin)) DoInput();
X  if (full && debug(4) && Restart)
X    fprintf(stderr, "Full redisplay\n");
X  return(Restart);
X}
X
Xdd_reset_restart()
X{
X  enterprocedure("dd_reset_restart");
X  Restart = false;
X}
X
XDoInput()
X{
X  int     c;
X  
X  enterprocedure("DoInput");
X  /* input is waiting on stdin */
X  if (debug(4)) fprintf(stderr, "Read from stdin ");
X  c = getc(stdin);
X  if (debug(4)) fprintf(stderr, "[%d]\n", c);
X  if (c == EOF || c == '\003') 
X    Please_Exit = true;
X  else  switch (c)
X    {
X    case '+': 
X      IncreaseSquareSize(1, 1);
X      break;
X      
X    case '-': 
X      IncreaseSquareSize(-1, -1);
X      break;
X      
X    default: 
X      break;
X    }
X}
X
X/* ************************************************************ */
X/*                                                              */
X/* lock and unlock access to the window                         */
X/*                                                              */
X/* ************************************************************ */
X
X
X#define LOCK_COUNT	50
Xstatic short    lockcount;
X
Xdd_lock_screen()
X{
X  enterprocedure("dd_lock_screen");
X  lockcount = LOCK_COUNT;
X  pw_lock(gfx->gfx_pixwin, &pwrect);
X}			       /* end of dd_lock_screen() */
X
XBoolean dd_check_lock()
X{
X  enterprocedure("dd_check_lock");
X  lockcount -= 1;
X  if (lockcount == 0)
X    return(true);
X  return(false);
X}			       /* end of dd_check_lock() */
X
X/* ************************************************************ */
X
Xdd_unlock_screen()
X{
X  enterprocedure("dd_unlock_screen");
X  pw_unlock(gfx->gfx_pixwin);
X  if (gfx->gfx_flags & GFX_DAMAGED)
X    {
X      gfxsw_handlesigwinch(gfx);
X      Restart = true;
X    }
X  if (gfx->gfx_flags & GFX_RESTART)
X    {
X      gfx->gfx_flags &= ~GFX_RESTART;
X      Restart = true;
X    }
X}			       /* end of dd_unlock_screen() */
X
X
X/* ************************************************************ */
X/*                                                              */
X/*                                                              */
X/* ************************************************************ */
X
X/* set the color map -- for black and white use only first 2 entries */
X
Xdd_set_new_color_map()
X{
X  short   color_map_size = COLOR_MAP_SIZE;
X  
X  enterprocedure("dd_set_new_color_map");
X  if (!ColorWindows)
X    color_map_size = 2;
X  
X  pw_putcolormap(gfx->gfx_pixwin, 0, color_map_size, rmap, gmap, bmap);
X}			       /* end of dd_set_new_color_map() */
X
X/* ************************************************************ */
X/*                                                              */
X/*                                                              */
X/* ************************************************************ */
X
Xdd_draw_line(x1, y1, x2, y2, linecolor)
X     short   x1;
X     short   y1;
X     short   x2;
X     short   y2;
X     ColorIndex linecolor;
X{
X  int     op = PIX_SRC | PIX_COLOR (linecolor);
X  
X  enterprocedure("dd_draw_line");
X  pw_vector(gfx->gfx_pixwin, x1, y1, x2, y2, op, 0);
X  
X  if (dd_check_lock())
X    {
X      dd_unlock_screen();
X      Return_If_Restart();
X      dd_lock_screen();
X    }
X}			       /* end of dd_draw_line() */
X
X/* ************************************************************ */
X/*                                                              */
X/*                                                              */
X/* ************************************************************ */
X
Xdd_clear_window(x, y, w, h, fillcolor)
X     short   x;
X     short   y;
X     short   w;
X     short   h;
X     ColorIndex fillcolor;
X{
X  dd_fill_rectangle(x, y, w, h, fillcolor);
X}
X
X
Xdd_fill_rectangle(x, y, w, h, fillcolor)
X     short   x;
X     short   y;
X     short   w;
X     short   h;
X     ColorIndex fillcolor;
X{
X  int     op;
X  
X  enterprocedure("dd_fill_rectangle");
X  op = PIX_SRC | PIX_COLOR(fillcolor);
X  
X  pw_rop(gfx->gfx_pixwin, x, y, w, h, op,(struct pixrect *) 0, 0, 0);
X  
X  if (dd_check_lock())
X    {
X      dd_unlock_screen();
X      Return_If_Restart();
X      dd_lock_screen();
X    }
X}			       /* end of dd_fill_rectangle() */
X
X
X/* ************************************************************ */
X/*                                                              */
X/*                                                              */
X/* ************************************************************ */
X
Xu_short icon_data[256] =
X{
X#                        include <images/lockscreen.icon>
X};
X
Xmpr_static(icon_mpr, LOGO_PIXELS_X, LOGO_PIXELS_Y, 1, icon_data);
X
X/* ************************************************************ */
X
Xdd_draw_logo(x, y, logocolor)
X     short   x;
X     short   y;
X     ColorIndex logocolor;
X{
X  int     op;
X  
X  enterprocedure("dd_draw_logo");
X  op = PIX_SRC | PIX_COLOR(logocolor);
X  
X  pw_rop(gfx->gfx_pixwin, x, y,
X	 LOGO_PIXELS_X, LOGO_PIXELS_Y,
X	 op, &icon_mpr, 0, 0);
X}			       /* end of dd_draw_logo() */
FRIDAY_NIGHT
echo extracting - x11-logo.xbm
sed 's/^X//' > x11-logo.xbm << 'FRIDAY_NIGHT'
X#define logo_width 64
X#define logo_height 64
Xstatic char logo_bits[] = {
X0x00, 0x00, 0x00, 0xc0, 0x03, 0x00, 0x00, 0x00, 
X0x00, 0x00, 0x00, 0xf0, 0x0f, 0x00, 0x00, 0x00, 
X0x00, 0x00, 0x00, 0xf8, 0x1f, 0x00, 0x00, 0x00, 
X0x00, 0x00, 0x00, 0xfc, 0x3f, 0x00, 0x00, 0x00, 
X0x00, 0x00, 0x00, 0xfc, 0x7f, 0x00, 0x00, 0x00, 
X0x00, 0x00, 0x00, 0xfe, 0xff, 0x00, 0x00, 0x00, 
X0x00, 0x00, 0x00, 0x7e, 0xff, 0x01, 0x00, 0x00, 
X0x00, 0x00, 0x50, 0xfe, 0xfe, 0x03, 0x00, 0x00, 
X0x00, 0x00, 0xe0, 0xfc, 0xfd, 0x07, 0x00, 0x00, 
X0x00, 0x00, 0xf0, 0xfd, 0xfb, 0x0f, 0x00, 0x00, 
X0x00, 0x00, 0xf8, 0xfb, 0xf7, 0x1f, 0x00, 0x00, 
X0x00, 0x00, 0xf5, 0xf7, 0xef, 0x3f, 0x00, 0x00, 
X0x00, 0x00, 0xee, 0xef, 0xdf, 0x7f, 0x00, 0x00, 
X0x00, 0x00, 0xdf, 0xdf, 0xbf, 0xff, 0x00, 0x00, 
X0x00, 0x80, 0xbf, 0xbf, 0x7f, 0xff, 0x00, 0x00, 
X0x00, 0x80, 0x7f, 0x7f, 0xff, 0x7e, 0x03, 0x00, 
X0x00, 0x60, 0xff, 0xfe, 0xfe, 0xbd, 0x07, 0x00, 
X0x00, 0xf0, 0xfe, 0xfd, 0xfd, 0xdb, 0x0f, 0x00, 
X0x00, 0xf8, 0xfd, 0xfb, 0xfb, 0xe7, 0x1f, 0x00, 
X0x00, 0xfc, 0xfb, 0xf7, 0xf7, 0xf7, 0x2f, 0x00, 
X0x00, 0xfe, 0xf5, 0xef, 0xef, 0xfb, 0x77, 0x00, 
X0x00, 0xff, 0xee, 0xdf, 0xcf, 0xfd, 0xfb, 0x00, 
X0x80, 0x7f, 0xdf, 0xbf, 0x9f, 0xfe, 0xfd, 0x01, 
X0xc0, 0xbf, 0xbf, 0xff, 0x1f, 0xff, 0xfe, 0x00, 
X0xe0, 0xdf, 0x1f, 0xff, 0x9f, 0x7f, 0x7f, 0x00, 
X0xf0, 0xef, 0x0f, 0xfe, 0xcf, 0xbf, 0x3f, 0x07, 
X0xf8, 0xf7, 0xe7, 0xfc, 0xef, 0xdf, 0xdf, 0x1f, 
X0xfc, 0xfb, 0xfb, 0xfb, 0xf7, 0xef, 0xef, 0x3f, 
X0xfe, 0xfd, 0xfd, 0xe7, 0xf9, 0xf7, 0xf7, 0x7f, 
X0xfe, 0xfe, 0xfe, 0x07, 0xf8, 0xfb, 0xfb, 0x7f, 
X0x7f, 0x7f, 0xff, 0x0f, 0xfc, 0xfd, 0xfd, 0xff, 
X0xbf, 0xbf, 0xff, 0x0f, 0xfc, 0xfe, 0xfe, 0xff, 
X0xff, 0xdf, 0xdf, 0x0f, 0xfc, 0x7f, 0xff, 0xfe, 
X0xff, 0xef, 0xef, 0x0f, 0xfc, 0xbf, 0x7f, 0xff, 
X0xfe, 0xf7, 0xf7, 0x07, 0xf8, 0xdf, 0xbf, 0x7f, 
X0xfe, 0xfb, 0xfb, 0xe7, 0xf9, 0xef, 0xdf, 0x7f, 
X0xfc, 0xfd, 0xfd, 0xfb, 0xf7, 0xf7, 0xef, 0x3f, 
X0x70, 0xfe, 0xfe, 0xfd, 0xcf, 0xf9, 0xf7, 0x1f, 
X0x00, 0x7f, 0xff, 0xfc, 0x1f, 0xfc, 0xfb, 0x0f, 
X0x80, 0xbf, 0x7f, 0xfe, 0x3f, 0xfe, 0xfd, 0x07, 
X0xc0, 0xdf, 0x3f, 0xfe, 0x7f, 0xff, 0xfe, 0x03, 
X0x80, 0xef, 0x5f, 0x7e, 0xff, 0x7e, 0xff, 0x01, 
X0x00, 0xf7, 0xef, 0xfc, 0xfe, 0xbd, 0xff, 0x00, 
X0x00, 0xfa, 0xf7, 0xfd, 0xfd, 0xdb, 0x7f, 0x00, 
X0x00, 0xfc, 0xfb, 0xfb, 0xfb, 0xe7, 0x3f, 0x00, 
X0x00, 0xf8, 0xf5, 0xf7, 0xf7, 0xef, 0x1f, 0x00, 
X0x00, 0xf0, 0xee, 0xef, 0xef, 0xdf, 0x0f, 0x00, 
X0x00, 0x60, 0xdf, 0xdf, 0xdf, 0xbf, 0x07, 0x00, 
X0x00, 0x80, 0xbf, 0xbf, 0xbf, 0x7f, 0x03, 0x00, 
X0x00, 0x80, 0x7f, 0x7f, 0x7f, 0xff, 0x00, 0x00, 
X0x00, 0x00, 0xff, 0xfe, 0xfe, 0xfe, 0x00, 0x00, 
X0x00, 0x00, 0xfe, 0xfd, 0xfd, 0x7d, 0x00, 0x00, 
X0x00, 0x00, 0xfc, 0xfb, 0xfb, 0x3b, 0x00, 0x00, 
X0x00, 0x00, 0xf8, 0xf7, 0xf7, 0x17, 0x00, 0x00, 
X0x00, 0x00, 0xf0, 0xef, 0xef, 0x0f, 0x00, 0x00, 
X0x00, 0x00, 0xe0, 0xdf, 0xdf, 0x07, 0x00, 0x00, 
X0x00, 0x00, 0xc0, 0xbf, 0x9f, 0x03, 0x00, 0x00, 
X0x00, 0x00, 0x80, 0x7f, 0x3f, 0x01, 0x00, 0x00, 
X0x00, 0x00, 0x00, 0xff, 0x3f, 0x00, 0x00, 0x00, 
X0x00, 0x00, 0x00, 0xfe, 0x3f, 0x00, 0x00, 0x00, 
X0x00, 0x00, 0x00, 0xfc, 0x1f, 0x00, 0x00, 0x00, 
X0x00, 0x00, 0x00, 0xf8, 0x1f, 0x00, 0x00, 0x00, 
X0x00, 0x00, 0x00, 0xf0, 0x0f, 0x00, 0x00, 0x00, 
X0x00, 0x00, 0x00, 0xc0, 0x03, 0x00, 0x00, 0x00};
X
FRIDAY_NIGHT
echo extracting - x11.c
sed 's/^X//' > x11.c << 'FRIDAY_NIGHT'
X/* ************************************************************ */
X
X/*	x11.c		graphical maze program (support)	*/
X
X/*	
X  
X  Support code for the maze program under the x11 window system
X  
X  Interface:
X  
X  dd_Set_Defaults() -- Set any global variable defaults.  
X                       Called only once at beginning
X
X  dd_scan_arg(option) -- called when the maze program has a command line option
X                         that it does not recognize. Can be used to specify
X			 device dependent options (like Geometry and Display).
X
X  dd_initialize_window() -- Create a window on the screen.  Must set the
X                            size of the window and tell if it is mono or color
X  
X  dd_terminate_window() -- Delete the window and any other resources.
X
X  dd_restart() -- Check if we need to restart the display, either because
X                  the display has been corrupted, or user input.
X
X  dd_idle() -- Wait until user wants to restart computation.
X
X  dd_reset_restart() -- reset whatever state caused dd_restart to return true
X  
X  dd_lock_screen() -- set up access to the window; lock and unlock are called
X                      alternatively, so that all drawing calls are between a
X                      call to lock and its following unlock.
X  
X  dd_unlock_screen() -- access is finished for now, unlock or flush output
X  
X  dd_set_new_color_map() -- global variables rmap, gmap, bmap define a new
X                            color map which will be used for the following
X                            operations.  Change color support as necessary.
X                            If we have only mono display, then the size of
X                            the color map is only 2, and the first two entries
X                            define black and white.
X  
X  dd_clear_window(x, y, w, h, fillcolor) -- clear the window.  x,y will be
X                            0,0 and w,h is the width and height of the window.
X			    The fillcolor is ColorBack -- the background color.
X			    This could be done with a dd_fill_rectangle (below)
X			    but is provided in case there is a special case
X			    clear-window command that is significantly faster
X			    than the general dd_fill-rectangle.
X
X  dd_draw_line(x1,y1,x2,y2,color) -- draw a line from x1,y1 to x2,y2 in the
X                                     given color.
X  
X  dd_fill_rectangle(x,y,w,h,color) -- fill the rectangle with origin x,y of
X                                      width w and height h with the color.
X  
X  dd_draw_logo(x,y,color) -- draw the logo at origin x,y in the color.  The
X                             logo is of width LOGO_PIXELS_X and height
X                             LOGO_PIXELS_Y (typically 64 x 64).
X*/
X
X/*  
X  Written by James Peterson, 13 Oct 1988
X  Based on an earlier versions by Richard Hess and Dave Lemke.
X*/
X
X/* ************************************************************ */
X/*                                                              */
X/*  Standard Initializations                                    */
X/*                                                              */
X/* ************************************************************ */
X
X#include "main.h"
X
X
X/* ************************************************************ */
X/*                                                              */
X/*  Device Dependent Code                                       */
X/*                                                              */
X/* ************************************************************ */
X
X
X#include <X11/Xlib.h>
X#include <X11/Xutil.h>
X
X
X/* ************************************************************ */
X/*                                                              */
X/*  Device Dependent Variables                                  */
X/*                                                              */
X/* ************************************************************ */
X
Xchar   *getenv ();
X
Xchar   *display = NULL;	   /* name of the display to use, or NULL for local */
Xchar   *geo = NULL;	   /* geometry of window, or NULL for whole  screen */
X
X#define	BORDERWIDTH     2
X#define MIN_W  200
X#define MIN_H  200
X
XDisplay * CurrentXDisplay;
XWindow    CurrentXWindow;
Xint       CurrentXScreen;
X
XColormap  CurrentXColormap;
XGC ColorGC[4];
X
XPixmap logo_map;
X#include "x11-logo.xbm"
X
X/* ************************************************************ */
X/*                                                              */
X/*                                                              */
X/* ************************************************************ */
X
Xdd_Set_Defaults()
X{
X  enterprocedure("dd_Set_Defaults");
X}
X
X
Xchar *index() /* external type declaration */;
X
Xdd_scan_arg(option)
Xchar *option;
X{
X  /* check for two options: a display or geometry */
X  /* geometry should be of form =... */
X  if (option[0] == '=')
X    {
X      geo = option;
X    }
X  /* check if it is a display name of the form machine:display */
X  else if (index(option,':') != NULL)
X    {
X      display = option;
X    }
X  /* must be an error */
X  else 
X    {
X    fprintf(stderr, "maze: Bad option %s\n", option);
X    Please_Exit = true;
X  }
X}
X
X/* ************************************************************ */
X
Xdd_initialize_window()	       /* take over and initialize window */
X{
X  /* 
X    Must define:
X	    screen_size
X	    ColorWindows
X	    InputFD
X  */
X  
X  int     width, height;
X  int     x, y;
X  long    background;
X  
X  enterprocedure("dd_initialize_window");
X  /* Create a Window */
X  if (display == NULL)
X    display = getenv("DISPLAY");
X  if ((CurrentXDisplay = XOpenDisplay(display)) == NULL)
X    {
X      fprintf(stderr, "Can't find X11 server on %s\n", display);
X      exit(0);
X    }
X  CurrentXScreen = DefaultScreen(CurrentXDisplay);
X  
X  /* get screen size */
X  if (geo == NULL)
X    {
X      width = DisplayWidth(CurrentXDisplay, CurrentXScreen) - 2 * BORDERWIDTH;
X      height = DisplayHeight(CurrentXDisplay, CurrentXScreen) - 2 * BORDERWIDTH;
X      x = 0;
X      y = 0;
X    }
X  else
X    {
X      int     flags;
X      
X      flags = XParseGeometry(geo, &x, &y, &width, &height);
X      if ((flags & XValue) && (flags & XNegative))
X	x += DisplayWidth(CurrentXDisplay, CurrentXScreen) - width;
X      if ((flags & YValue) && (flags & YNegative))
X	y += DisplayHeight(CurrentXDisplay, CurrentXScreen) - height;
X    }
X  
X  background = WhitePixel(CurrentXDisplay, CurrentXScreen);
X  CurrentXWindow = XCreateSimpleWindow(CurrentXDisplay, RootWindow(CurrentXDisplay, CurrentXScreen), x, y, width,
X			    height, BORDERWIDTH, 1, background);
X  
X  
X  /* determine if we have a color screen or black and white */
X  DefineScreenSize(width, height);
X  ColorWindows = (DefaultDepth(CurrentXDisplay,CurrentXScreen) > 1);
X  if (debug(1))
X    fprintf(stderr, "Depth of display is %d\n",
X	    DefaultDepth(CurrentXDisplay,CurrentXScreen));
X  InputFD = ConnectionNumber(CurrentXDisplay);
X  
X  /* select input events */
X  XSelectInput(CurrentXDisplay, CurrentXWindow, ExposureMask | ButtonPressMask | StructureNotifyMask);
X
X  /* create graphics contexts for each of the four possible colors */
X  ColorGC[0] = XCreateGC(CurrentXDisplay, CurrentXWindow, 0, 0);
X  ColorGC[1] = XCreateGC(CurrentXDisplay, CurrentXWindow, 0, 0);
X  ColorGC[2] = XCreateGC(CurrentXDisplay, CurrentXWindow, 0, 0);
X  ColorGC[3] = XCreateGC(CurrentXDisplay, CurrentXWindow, 0, 0);
X  
X  /* set up colors for display */
X  CurrentXColormap = XDefaultColormap(CurrentXDisplay,CurrentXScreen);
X  dd_set_new_color_map();
X  
X  logo_map = XCreateBitmapFromData(CurrentXDisplay, CurrentXWindow, 
X				   logo_bits, logo_width, logo_height);
X  if (!logo_map)
X    {
X      fprintf(stderr, "Can't create logo pixmap\n");
X      exit(1);
X    }
X  
X  {
X    XSizeHints size_hints;
X    char  **Xargv = NULL;
X    int     Xargc = 0;
X    
X    size_hints.flags = USPosition | USSize | PMinSize;
X    size_hints.x = x;
X    size_hints.y = y;
X    size_hints.width = width;
X    size_hints.height = height;
X    size_hints.min_width = MIN_W;
X    size_hints.min_height = MIN_H;
X    
X    XSetStandardProperties(CurrentXDisplay, CurrentXWindow, 
X			   "Xmaze", "Xmaze", logo_map,
X			   Xargv, Xargc, &size_hints);
X  }
X  
X  XMapWindow(CurrentXDisplay, CurrentXWindow);
X
X  /* wait until exposure and map events start coming from the server */
X  Wait(0);
X}			       /* end of dd_initialize_window() */
X
Xdd_terminate_window()
X{
X  enterprocedure("dd_terminate_window");
X  XFreeGC(CurrentXDisplay, ColorGC[0]);
X  XFreeGC(CurrentXDisplay, ColorGC[1]);
X  XFreeGC(CurrentXDisplay, ColorGC[2]);
X  XFreeGC(CurrentXDisplay, ColorGC[3]);
X  XDestroyWindow(CurrentXDisplay, CurrentXWindow);
X  XCloseDisplay(CurrentXDisplay);
X}
X
Xdd_idle()
X{
X  XEvent e;
X
X  enterprocedure("dd_idle");
X  XNextEvent(CurrentXDisplay, &e);
X  check_events(&e);
X  Please_Idle = false;
X}
X
X
X
X
X/* ************************************************************ */
X/*                                                              */
X/*                                                              */
X/* ************************************************************ */
X
X
Xstatic  Boolean Restart = false;
X
X
Xcheck_events(e)	       /* X event handler [ rhess ] */
X     XEvent *e;
X{
X  enterprocedure("check_events");
X  switch (e->type)
X    {
X    case ButtonPress: 
X      if (debug(4)) fprintf(stderr, "Button event\n");
X      HandleXButton(e->xbutton.button);
X      Restart = true;
X      break;
X      
X    case ConfigureNotify: 
X      if (debug(4)) fprintf(stderr, "Config event\n");
X      Restart = true;
X      break;
X      
X    case UnmapNotify: 
X      if (debug(4)) fprintf(stderr, "Unmap event\n");
X      Please_Idle = 1;
X      XClearWindow(CurrentXDisplay, CurrentXWindow);
X      XFlush(CurrentXDisplay);
X      break;
X      
X    case Expose: 
X      if (debug(4)) fprintf(stderr, "Expose event\n");
X      Restart = true;
X      break;
X    }
X}
X
X
X/* 
X  "Right"  mouse click --> causes the program to exit...
X  "Middle" mouse click --> toggles the maze off and on (ie. stop/start)...
X  "Left"   mouse click --> causes a new maze pattern to be created...
X*/
X
XHandleXButton(button)
X     unsigned int  button;
X{
X  enterprocedure("HandleXButton");
X  switch (button)
X    {
X    case 3: 	       /* right button */
X      if (debug(4)) fprintf(stderr, "Right Button\n");
X      Restart = true;
X      Please_Exit = true;
X      break;
X      
X    case 2: 	       /* middle button */
X      if (debug(4)) fprintf(stderr, "Middle Button\n");
X      Please_Idle = true;
X      break;
X      
X    default: 
X      /* left button */
X      if (debug(4)) fprintf(stderr, "Left Button\n");
X      break;
X    }
X}
X
X
X/* ************************************************************ */
X/*                                                              */
X/*                                                              */
X/* ************************************************************ */
X
XBoolean dd_restart(full)
X     Boolean full;
X{
X  enterprocedure("dd_restart");
X  /* check if there is any reason to restart */
X  if (Restart)    return(true);
X  
X  /* if full is true, be sure to check completely */
X  /* polling for input is expensive, only do so if requested */
X  if (full)
X    {
X      XEvent e;
X      if (XPending(CurrentXDisplay))
X	{
X	  XNextEvent(CurrentXDisplay, &e);
X	  check_events(&e);
X	}
X    }
X  
X  if (debug(4) && Restart)  fprintf(stderr, "Full redisplay\n");
X  return(Restart);
X}
X
Xdd_reset_restart()
X{
X  XWindowAttributes win_attr;
X
X  enterprocedure("dd_reset_restart");
X  XGetWindowAttributes(CurrentXDisplay, CurrentXWindow, &win_attr);
X  DefineScreenSize(win_attr.width, win_attr.height);
X  Restart = false;
X}
X
X
X/* ************************************************************ */
X/*                                                              */
X/* lock and unlock access to the window                         */
X/*                                                              */
X/* ************************************************************ */
X
X
Xdd_lock_screen()
X{
X  enterprocedure("dd_lock_screen");
X}			       /* end of dd_lock_screen() */
X
X
X/* ************************************************************ */
X
Xdd_unlock_screen()
X{
X  enterprocedure("dd_unlock_screen");
X  XFlush(CurrentXDisplay);
X}			       /* end of dd_unlock_screen() */
X
X
X/* ************************************************************ */
X/*                                                              */
X/*                                                              */
X/* ************************************************************ */
X
X/* set the color map -- for black and white use only first 2 entries */
X
Xdd_set_new_color_map()
X{
X  XColor ColorStruct;
X  short i;
X  
X  enterprocedure("dd_set_new_color_map");
X  
X  /* for each of our four colors (background, wall, path, logo),
X     define a graphics context which uses that color */
X
X  for (i = ColorLogo; i >= ColorBack; i--)
X    {
X      /* get a color for rmap[i], gmap[i], bmap[i] and put it in ColorGC[i] */
X      ColorStruct.red = rmap[i] << 8;
X      ColorStruct.green = gmap[i] << 8;
X      ColorStruct.blue = bmap[i] << 8;
X      if (debug(1))
X	fprintf(stderr,"Requested color %d is %d, %d, %d\n",
X		i, ColorStruct.red, ColorStruct.green, ColorStruct.blue);
X      
X      XAllocColor(CurrentXDisplay,CurrentXColormap, &ColorStruct);
X      XSetForeground(CurrentXDisplay, ColorGC[i], ColorStruct.pixel);      
X    }
X
X  /* we have arranged for the Background color (ColorBack) to be the
X     last color processed.  Thus ColorStruct.pixel is the pixel value
X     for the Background color.  Set the backgrounds for all GC's to
X     the ColorBack color.  This is mainly important for the logo. */
X
X  XSetWindowBackground(CurrentXDisplay, CurrentXWindow, ColorStruct.pixel);
X  for (i = ColorLogo; i >= ColorBack; i--)
X    XSetBackground(CurrentXDisplay, ColorGC[i], ColorStruct.pixel);
X
X}			       /* end of dd_set_new_color_map() */
X
X/* ************************************************************ */
X/*                                                              */
X/*                                                              */
X/* ************************************************************ */
X
Xdd_draw_line(x1, y1, x2, y2, linecolor)
X     short   x1;
X     short   y1;
X     short   x2;
X     short   y2;
X     ColorIndex linecolor;
X{
X  enterprocedure("dd_draw_line");
X  XDrawLine(CurrentXDisplay, CurrentXWindow, ColorGC[linecolor], x1, y1, x2, y2);
X  XFlush(CurrentXDisplay);
X}			       /* end of dd_draw_line() */
X
X/* ************************************************************ */
X/*                                                              */
X/*                                                              */
X/* ************************************************************ */
X
Xdd_clear_window(x, y, w, h, fillcolor)
X     short   x;
X     short   y;
X     short   w;
X     short   h;
X     ColorIndex fillcolor;
X{
X  XClearWindow(CurrentXDisplay, CurrentXWindow);
X}
X
Xdd_fill_rectangle(x, y, w, h, fillcolor)
X     short   x;
X     short   y;
X     short   w;
X     short   h;
X     ColorIndex fillcolor;
X{
X  enterprocedure("dd_fill_rectangle");
X  XFillRectangle(CurrentXDisplay, CurrentXWindow, ColorGC[fillcolor], x, y, w, h);
X  XFlush(CurrentXDisplay);
X}			       /* end of dd_fill_rectangle() */
X
X
X/* ************************************************************ */
X/*                                                              */
X/*                                                              */
X/* ************************************************************ */
X
X
Xdd_draw_logo(x, y, logocolor)
X     short   x;
X     short   y;
X     ColorIndex logocolor;
X{
X  enterprocedure("dd_draw_logo");
X  XCopyPlane(CurrentXDisplay, logo_map, CurrentXWindow, ColorGC[logocolor],
X	     0, 0, logo_width, logo_height, x, y, 1);
X}			       /* end of dd_draw_logo() */
FRIDAY_NIGHT
-- 
Mike Wexler(wyse!mikew)    Phone: (408)433-1000 x1330
Moderator of comp.sources.x



More information about the Comp.sources.x mailing list