[comp.os.minix] MINI-X graphics package

dbell@pdact.pd.necisa.oz.au (David I. Bell) (04/22/91)

This is my mini-X graphics package for 32-bit IBM PC MINIX.
Enjoy, and let me know if there are any problems.

David I. Bell
dbell@pdact.pd.necisa.oz.au


#! /bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of archive 1 (of 9)."
# Contents:  mini-x/CRCS mini-x/FILES mini-x/clients/makefile
#   mini-x/clients/tm.c mini-x/cpp/cpp5.c.cdif mini-x/cpp/cpp6.c.cdif
#   mini-x/fs/table.c.cdif mini-x/kernel/cstart.c.cdif
#   mini-x/kernel/glo.h.cdif mini-x/kernel/graph_dev.h
#   mini-x/kernel/klib386.x.cdif mini-x/kernel/makefile.cdif
#   mini-x/kernel/makefile.cpp.c mini-x/kernel/makefile.cpp.n
#   mini-x/kernel/makefile.new mini-x/kernel/proto.h.cdif
#   mini-x/kernel/start.x.cdif mini-x/kernel/start.x.insert
#   mini-x/kernel/table.c.cdif mini-x/kernel/tty.c.cdif
#   mini-x/server/keyboard.c mini-x/server/makefile
#   mini-x/server/mouse.c mini-x/server/serv_main.c
# Wrapped by dbell@elm on Mon Apr 22 11:21:41 1991
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
echo shar: making directories
mkdir mini-x
mkdir mini-x/clients mini-x/cpp mini-x/fs
mkdir mini-x/include mini-x/kernel mini-x/server
if test -f 'mini-x/CRCS' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'mini-x/CRCS'\"
else
echo shar: Extracting \"'mini-x/CRCS'\" \(1292 characters\)
sed "s/^X//" >'mini-x/CRCS' <<'END_OF_FILE'
X62472   2528 FILES
X11163  22803 README
X18215  45475 TUTORIAL
X30700   9582 clients/demo.c
X23193    472 clients/makefile
X48396    181 clients/tm.c
X07810    623 cpp/cpp5.c.cdif
X26598    429 cpp/cpp6.c.cdif
X14859    502 fs/table.c.cdif
X23825   5685 include/graph_msg.h
X44796  14242 include/graphics.h
X47124    676 kernel/cstart.c.cdif
X19215   8077 kernel/cursor_gen.c
X57267  18881 kernel/ega.x
X37490    483 kernel/glo.h.cdif
X63954   8352 kernel/graph_clip.c
X55049   3989 kernel/graph_dev.h
X58440  14152 kernel/graph_ega.c
X48462  11017 kernel/graph_gen.c
X28400  21918 kernel/graph_main.c
X43163  19967 kernel/graphics.c
X58006   2827 kernel/klib386.x.cdif
X11354   2505 kernel/makefile.cdif
X23516   2119 kernel/makefile.cpp.c
X03828   4726 kernel/makefile.cpp.n
X32556   3325 kernel/makefile.new
X26435    294 kernel/proto.h.cdif
X21896    571 kernel/start.x.cdif
X63621    736 kernel/start.x.insert
X10882   1162 kernel/table.c.cdif
X28761    619 kernel/tty.c.cdif
X14280  16055 server/client.c
X21673   9325 server/graph_serv.h
X40374   2281 server/keyboard.c
X29806    965 server/makefile
X42686   4826 server/mouse.c
X59503   6673 server/mousedev.c
X05554  21102 server/serv_dev.c
X23366  16971 server/serv_event.c
X39406  33072 server/serv_func.c
X53799   5039 server/serv_main.c
X14628  26728 server/serv_util.c
END_OF_FILE
if test 1292 -ne `wc -c <'mini-x/CRCS'`; then
    echo shar: \"'mini-x/CRCS'\" unpacked with wrong size!
fi
# end of 'mini-x/CRCS'
fi
if test -f 'mini-x/FILES' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'mini-x/FILES'\"
else
echo shar: Extracting \"'mini-x/FILES'\" \(2528 characters\)
sed "s/^X//" >'mini-x/FILES' <<'END_OF_FILE'
XFILES			this file giving summary of changes to files
XCRCS			checksums for files in the package
XREADME			overall description and installation instructions
XTUTORIAL		tutorial in concepts and usage of graphics routines
X
Xfs/table.c.cdif		diff of table.c: add graphics device interface
X
Xkernel/makefile.cdif	diff of makefile: add graphics device files
Xkernel/makefile.cpp.c	diff of makefile.cpp: add graphics device files
Xkernel/makefile.new	complete copy of new makefile
Xkernel/makefile.cpp.n	complete copy of new makefile.cpp
Xkernel/cstart.c.cdif	diff of cstart.c: get rom character table address
Xkernel/glo.h.cdif	diff of glo.h: add external symbol rom_char_addr
Xkernel/klib386.x.cdif	diff of klib386.x: add put_byte routine
Xkernel/proto.h.cdif	diff of proto.h: add graphics task definition
Xkernel/start.x.cdif	diff of start.x: add get_rom_char_addr definition
Xkernel/start.x.insert	insert for start.x: add get_rom_char_addr routine
Xkernel/table.c.cdif	diff of table.c: add graphics task definitions
Xkernel/tty.c.cdif	diff of tty.c: make non-blocking reads work
Xkernel/graph_dev.h	new: global definitions for graphics device
Xkernel/graphics.c	new: graphics device driver
Xkernel/graph_clip.c	new: clipping routines
Xkernel/graph_gen.c	new: generic drawing routines
Xkernel/graph_main.c	new: top-level drawing routines
Xkernel/graph_ega.c	new: EGA graphics high-level routines
Xkernel/ega.x		new: EGA graphics assembly routines
Xkernel/cursor_gen.c	new: software cursor routines
X
Xserver/makefile		new: makefile to build graphics server library
Xserver/graph_serv.h	new: global definitions for graphics server
Xserver/client.c		new: routines called by client programs
Xserver/serv_dev.c	new: interface routines to kernel graphics device
Xserver/serv_event.c	new: event routines
Xserver/serv_func.c	new: interface routines to call graphics server
Xserver/serv_main.c	new: graphics server initialization
Xserver/serv_util.c	new: utility routines for graphics server
Xserver/keyboard.c	new: keyboard interface
Xserver/mouse.c		new: mouse high-level interface
Xserver/mousedev.c	new: mouse low-level interface
X
Xclients/makefile	new: makefile to build client programs
Xclients/demo.c		new: demonstration program for graphics
Xclients/tm.c		new: utility to reset terminal back to text mode
X
Xinclude/graphics.h	new: public include file in /usr/include
Xinclude/graph_msg.h	new: server/kernel include file in /usr/include/minix
X
Xcpp/cpp5.c.cdif		diff of cpp5.c: fix for undefined symbol errors
Xcpp/cpp5.c.cdif		diff of cpp5.c: fix for misquoted string errors
END_OF_FILE
if test 2528 -ne `wc -c <'mini-x/FILES'`; then
    echo shar: \"'mini-x/FILES'\" unpacked with wrong size!
fi
# end of 'mini-x/FILES'
fi
if test -f 'mini-x/clients/makefile' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'mini-x/clients/makefile'\"
else
echo shar: Extracting \"'mini-x/clients/makefile'\" \(472 characters\)
sed "s/^X//" >'mini-x/clients/makefile' <<'END_OF_FILE'
XCFLAGS = -i -O
XLDFLAGS = -i
XINCLUDES = /usr/include/graphics.h
XLIBRARIES = /usr/local/lib/i386/libgraph.a
XBINDIR = /bin
XPROGS = demo tm
X
X
Xall:	$(PROGS)
X
Xinstall:	$(PROGS)
X	cp $(PROGS) $(BINDIR)
X	cd $(BINDIR); strip $(PROGS); chmod 755 $(PROGS)
X
Xclean:
X	rm -rf $(PROGS) *.o
X
Xdemo:	demo.o $(LIBRARIES)
X	cc -o demo $(LDFLAGS) demo.o -lgraph
X	chmem =24000 demo
X
Xtm:	tm.o $(LIBRARIES)
X	cc -o tm $(LDFLAGS) tm.o -lgraph
X	chmem =8192 tm
X
X
Xtm.o:		$(INCLUDES)
Xdemo.o:		$(INCLUDES)
END_OF_FILE
if test 472 -ne `wc -c <'mini-x/clients/makefile'`; then
    echo shar: \"'mini-x/clients/makefile'\" unpacked with wrong size!
fi
# end of 'mini-x/clients/makefile'
fi
if test -f 'mini-x/clients/tm.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'mini-x/clients/tm.c'\"
else
echo shar: Extracting \"'mini-x/clients/tm.c'\" \(181 characters\)
sed "s/^X//" >'mini-x/clients/tm.c' <<'END_OF_FILE'
X/*
X * Reset the terminal back to text mode.
X * This is done by simply opening the graphics screen and closing it again.
X */
X#include "graphics.h"
X
Xmain()
X{
X	GrOpen();
X	GrClose();
X}
END_OF_FILE
if test 181 -ne `wc -c <'mini-x/clients/tm.c'`; then
    echo shar: \"'mini-x/clients/tm.c'\" unpacked with wrong size!
fi
# end of 'mini-x/clients/tm.c'
fi
if test -f 'mini-x/cpp/cpp5.c.cdif' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'mini-x/cpp/cpp5.c.cdif'\"
else
echo shar: Extracting \"'mini-x/cpp/cpp5.c.cdif'\" \(623 characters\)
sed "s/^X//" >'mini-x/cpp/cpp5.c.cdif' <<'END_OF_FILE'
X*** old/cpp5.c	Sun Apr 21 12:17:37 1991
X--- cpp5.c	Sat Apr 20 16:04:30 1991
X***************
X*** 417,424 ****
X  	     * warning except where the programmer was careful to write
X  	     * 		#if defined(foo) ? foo : 0
X  	     */
X! 	    if (!skip)
X! 		cwarn("undefined symbol \"%s\" in #if, 0 used", token);
X  	    evalue = 0;
X  	    return (DIG);
X  	}
X--- 417,426 ----
X  	     * warning except where the programmer was careful to write
X  	     * 		#if defined(foo) ? foo : 0
X  	     */
X! #if 0
X! 	    if (!skip)
X! 		cwarn("undefined symbol \"%s\" in #if, 0 used", token);
X! #endif
X  	    evalue = 0;
X  	    return (DIG);
X  	}
END_OF_FILE
if test 623 -ne `wc -c <'mini-x/cpp/cpp5.c.cdif'`; then
    echo shar: \"'mini-x/cpp/cpp5.c.cdif'\" unpacked with wrong size!
fi
# end of 'mini-x/cpp/cpp5.c.cdif'
fi
if test -f 'mini-x/cpp/cpp6.c.cdif' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'mini-x/cpp/cpp6.c.cdif'\"
else
echo shar: Extracting \"'mini-x/cpp/cpp6.c.cdif'\" \(429 characters\)
sed "s/^X//" >'mini-x/cpp/cpp6.c.cdif' <<'END_OF_FILE'
X*** old/cpp6.c	Sun Apr 21 12:17:43 1991
X--- cpp6.c	Sat Apr 20 16:04:31 1991
X***************
X*** 295,302 ****
X  	    return (TRUE);
X  	}
X  	else {
X! 	    if (!eflag)
X! 		cerror("Unterminated string", NULLST);
X  	    unget();
X  	    return (FALSE);
X  	}
X--- 295,304 ----
X  	    return (TRUE);
X  	}
X  	else {
X! #if 0
X! 	    if (!eflag)
X! 		cerror("Unterminated string", NULLST);
X! #endif
X  	    unget();
X  	    return (FALSE);
X  	}
END_OF_FILE
if test 429 -ne `wc -c <'mini-x/cpp/cpp6.c.cdif'`; then
    echo shar: \"'mini-x/cpp/cpp6.c.cdif'\" unpacked with wrong size!
fi
# end of 'mini-x/cpp/cpp6.c.cdif'
fi
if test -f 'mini-x/fs/table.c.cdif' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'mini-x/fs/table.c.cdif'\"
else
echo shar: Extracting \"'mini-x/fs/table.c.cdif'\" \(502 characters\)
sed "s/^X//" >'mini-x/fs/table.c.cdif' <<'END_OF_FILE'
X*** ../old/fs/table.c	Sun Jan 27 10:54:20 1991
X--- table.c	Tue Mar 12 21:52:41 1991
X***************
X*** 111,116 ****
X--- 111,117 ----
X      tty_open,  rw_dev,      no_call,    TTY,         /* 4 = /dev/tty0 */
X      no_call,   rw_dev2,     no_call,    TTY,         /* 5 = /dev/tty  */
X      no_call,   rw_dev,      no_call,    PRINTER,     /* 6 = /dev/lp   */
X+     no_call,   rw_dev,      no_call,	GRAPHICS,    /* 7 = /dev/graphics */
X  };
X  
X  PUBLIC int max_major = sizeof(dmap)/sizeof(struct dmap);
END_OF_FILE
if test 502 -ne `wc -c <'mini-x/fs/table.c.cdif'`; then
    echo shar: \"'mini-x/fs/table.c.cdif'\" unpacked with wrong size!
fi
# end of 'mini-x/fs/table.c.cdif'
fi
if test -f 'mini-x/kernel/cstart.c.cdif' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'mini-x/kernel/cstart.c.cdif'\"
else
echo shar: Extracting \"'mini-x/kernel/cstart.c.cdif'\" \(676 characters\)
sed "s/^X//" >'mini-x/kernel/cstart.c.cdif' <<'END_OF_FILE'
X*** ../old/kernel/cstart.c	Tue Mar  5 22:13:16 1991
X--- cstart.c	Tue Mar 26 22:16:46 1991
X***************
X*** 42,47 ****
X--- 42,50 ----
X  FORWARD char *k_getenv();
X  FORWARD void rel_vec();
X  
X+ EXTERN	u32_t get_rom_char_addr();
X+ 
X+ 
X  /*==========================================================================*
X   *				cstart					    *
X   *==========================================================================*/
X***************
X*** 99,104 ****
X--- 102,108 ----
X    /* Get information from the BIOS. */
X    color = get_chrome();
X    ega = get_ega();
X+   rom_char_addr = get_rom_char_addr();
X    ext_memsize = get_ext_memsize();
X    low_memsize = get_low_memsize();
X  
END_OF_FILE
if test 676 -ne `wc -c <'mini-x/kernel/cstart.c.cdif'`; then
    echo shar: \"'mini-x/kernel/cstart.c.cdif'\" unpacked with wrong size!
fi
# end of 'mini-x/kernel/cstart.c.cdif'
fi
if test -f 'mini-x/kernel/glo.h.cdif' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'mini-x/kernel/glo.h.cdif'\"
else
echo shar: Extracting \"'mini-x/kernel/glo.h.cdif'\" \(483 characters\)
sed "s/^X//" >'mini-x/kernel/glo.h.cdif' <<'END_OF_FILE'
X*** ../old/kernel/glo.h	Tue Mar  5 22:13:22 1991
X--- glo.h	Sun Mar 24 17:39:26 1991
X***************
X*** 42,47 ****
X--- 42,48 ----
X  EXTERN int ega;			/* nonzero if console is EGA */
X  EXTERN int scan_code;		/* scan code of key pressed to start minix */
X  EXTERN int snow;		/* nonzero if screen needs snow removal */
X+ EXTERN u32_t rom_char_addr;	/* address of rom character table */
X  
X  /* Memory sizes. */
X  EXTERN unsigned ext_memsize;	/* initialized by assembler startup code */
END_OF_FILE
if test 483 -ne `wc -c <'mini-x/kernel/glo.h.cdif'`; then
    echo shar: \"'mini-x/kernel/glo.h.cdif'\" unpacked with wrong size!
fi
# end of 'mini-x/kernel/glo.h.cdif'
fi
if test -f 'mini-x/kernel/graph_dev.h' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'mini-x/kernel/graph_dev.h'\"
else
echo shar: Extracting \"'mini-x/kernel/graph_dev.h'\" \(3989 characters\)
sed "s/^X//" >'mini-x/kernel/graph_dev.h' <<'END_OF_FILE'
X/* Copyright (c) 1991 David I. Bell
X * Permission is granted to use, distribute, or modify this source,
X * provided that this copyright notice remains intact.
X *
X * mini-X graphics - kernel private definitions
X */
X
X#ifndef	GRAPH_DEV_H
X#define	GRAPH_DEV_H
X
X#include <graphics.h>
X
X
X/* Pixel packings within words. */
X#define	GR_BITMAPBITS	(sizeof(GR_BITMAP) * 8)
X#define	GR_ZEROBITS	((GR_BITMAP) 0x0000)
X#define	GR_ONEBITS	((GR_BITMAP) 0xffff)
X#define	GR_FIRSTBIT	((GR_BITMAP) 0x8000)
X#define	GR_LASTBIT	((GR_BITMAP) 0x0001)
X#define	GR_BITVALUE(n)	((GR_BITMAP) (((GR_BITMAP) 1) << (n)))
X#define	GR_SHIFTBIT(m)	((GR_BITMAP) ((m) << 1))
X#define	GR_NEXTBIT(m)	((GR_BITMAP) ((m) >> 1))
X#define	GR_TESTBIT(m)	(((m) & GR_FIRSTBIT) != 0)
X
X
Xtypedef struct {
X  int (*init) ();		/* init graphics mode for device */
X  void (*term) ();		/* terminate graphics mode for device */
X  void (*setmode) ();		/* set drawing mode */
X  void (*drawpoint) ();		/* draw point */
X  void (*drawline) ();		/* draw line */
X  void (*drawrow) ();		/* draw horizontal line */
X  void (*drawcol) ();		/* draw vertical line */
X  void (*fillrect) ();		/* draw filled in rectangle */
X  void (*drawellipse) ();	/* draw ellipse */
X  void (*fillellipse) ();	/* fill ellipse */
X  void (*drawtext) ();		/* draw text string */
X  void (*sizetext) ();		/* return size of text string */
X  void (*drawarea8) ();		/* draw area with 8 bit color values */
X  void (*drawbitmap) ();	/* draw bitmap */
X   GR_COLOR(*readpoint) ();	/* read pixel value */
X  void (*setcursor) ();		/* set cursor size and shape */
X  void (*movecursor) ();	/* move location of cursor */
X  void (*checkcursor) ();	/* check cursor for overlapped io */
X  void (*fixcursor) ();		/* fix back cursor after overlaps */
X  void (*copyarea) ();		/* copy rectangular area */
X  void (*getcharbits) ();	/* return bitmap for character */
X  void (*getscreeninfo) ();	/* return screen configuration info */
X  void (*getfontinfo) ();	/* return font information */
X
X  /* Data values which are constants of the device. */
X  GR_SIZE rows;			/* number of rows in device */
X  GR_SIZE cols;			/* number of columns in device */
X  long colors;			/* number of colors for device */
X  GR_COLOR black;		/* color value for black */
X  GR_COLOR white;		/* color value for white */
X} GR_DEV;
X
XEXTERN GR_DEV gr_dev;		/* device for drawing */
X
X
X/* Other useful global symbols. */
XEXTERN GR_MODE gr_mode;		/* current drawing mode */
XEXTERN GR_COLOR gr_foreground;	/* foreground color */
XEXTERN GR_COLOR gr_background;	/* background color */
XEXTERN GR_BOOL gr_usebg;	/* TRUE if use background in pixmaps */
XEXTERN GR_BOOL gr_error;	/* TRUE if had graphics error */
X
X
X/* Clip cache rectangle information.
X * After calling clipcheck, this rectangle is guaranteed to contain the
X * specified point (among others), and all points in the rectangle are
X * plottable or not according to the value of clipresult.
X */
XEXTERN GR_COORD clipminx;	/* minimum x value of cache rectangle */
XEXTERN GR_COORD clipminy;	/* minimum y value of cache rectangle */
XEXTERN GR_COORD clipmaxx;	/* maximum x value of cache rectangle */
XEXTERN GR_COORD clipmaxy;	/* maximum y value of cache rectangle */
XEXTERN GR_BOOL clipresult;	/* whether clip rectangle is plottable */
X
X#define	GR_CLIP_INVISIBLE	0	/* clip area is invisible */
X#define	GR_CLIP_VISIBLE		1	/* clip area is visible */
X#define	GR_CLIP_PARTIAL		2	/* clip area may be partially visible */
X
X
X/* Generic routines for drawing which use other primitives. */
Xextern void gen_drawline();
Xextern void gen_drawrow();
Xextern void gen_drawcol();
Xextern void gen_fillrect();
Xextern void gen_drawellipse();
Xextern void gen_fillellipse();
Xextern void gen_drawtext();
Xextern void gen_drawarea8();
Xextern void gen_drawbitmap();
Xextern void gen_initcursor();
Xextern void gen_setcursor();
Xextern void gen_movecursor();
Xextern void gen_checkcursor();
Xextern void gen_fixcursor();
Xextern void gen_copyarea();
X
Xextern GR_BOOL clippoint();
Xextern int cliparea();
X
X#endif
X
X/* END CODE */
END_OF_FILE
if test 3989 -ne `wc -c <'mini-x/kernel/graph_dev.h'`; then
    echo shar: \"'mini-x/kernel/graph_dev.h'\" unpacked with wrong size!
fi
# end of 'mini-x/kernel/graph_dev.h'
fi
if test -f 'mini-x/kernel/klib386.x.cdif' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'mini-x/kernel/klib386.x.cdif'\"
else
echo shar: Extracting \"'mini-x/kernel/klib386.x.cdif'\" \(2827 characters\)
sed "s/^X//" >'mini-x/kernel/klib386.x.cdif' <<'END_OF_FILE'
X*** ../old/kernel/klib386.x	Tue Mar  5 22:13:24 1991
X--- klib386.x	Tue Apr 16 22:35:01 1991
X***************
X*** 9,14 ****
X--- 9,15 ----
X  .define		_cim_xt_wini
X  .define		_cp_mess
X  .define		_get_byte
X+ .define		_put_byte
X  .define		_in_byte
X  .define		_klib_1hook
X  .define		_klib_2hook
X***************
X*** 260,289 ****
X  
X  
X  |*===========================================================================*
X! |*				in_byte					     *
X! |*===========================================================================*
X! | PUBLIC unsigned in_byte(port_t port);
X! | Read an (unsigned) byte from the i/o port  port  and return it.
X! 
X! _in_byte:
X! 	mov	edx,4(esp)		| port
X! 	sub	eax,eax
X! 	in				| read 1 byte
X  	ret
X  
X  
X  |*===========================================================================*
X! |*				klib_1hook				     *
X! |*===========================================================================*
X! | PUBLIC void klib_1hook();
X! | Initialize klib from real mode for protected mode (no real mode).
X! | Nothing to do.
X! 
X! _klib_1hook:
X! 	ret				| cheat: opcode same for 16/32-bits
X  
X  
X  |*===========================================================================*
X  |*				klib_2hook				     *
X  |*===========================================================================*
X  | PUBLIC void klib_2hook();
X--- 261,306 ----
X  
X  
X  |*===========================================================================*
X! |*				put_byte				     *
X! |*===========================================================================*
X! | PUBLIC void put_byte(u32_t segment, u32_t *offset, data);
X! | Store the data byte at the far pointer  segment:offset.
X! 
X! _put_byte:
X! 	mov	cx,ds
X! 	mov	ds,4(esp)		| segment
X! 	mov	eax,4+4(esp)		| offset
X! 	mov	ebx,4+4+4(esp)		| data byte
X! 	movb	(eax),bl		| byte to store
X! 	mov	ds,cx
X  	ret
X  
X  
X  |*===========================================================================*
X! |*				in_byte					     *
X! |*===========================================================================*
X! | PUBLIC unsigned in_byte(port_t port);
X! | Read an (unsigned) byte from the i/o port  port  and return it.
X! 
X! _in_byte:
X! 	mov	edx,4(esp)		| port
X! 	sub	eax,eax
X! 	in				| read 1 byte
X! 	ret
X  
X  
X  |*===========================================================================*
X+ |*				klib_1hook				     *
X+ |*===========================================================================*
X+ | PUBLIC void klib_1hook();
X+ | Initialize klib from real mode for protected mode (no real mode).
X+ | Nothing to do.
X+ 
X+ _klib_1hook:
X+ 	ret				| cheat: opcode same for 16/32-bits
X+ 
X+ 
X+ |*===========================================================================*
X  |*				klib_2hook				     *
X  |*===========================================================================*
X  | PUBLIC void klib_2hook();
END_OF_FILE
if test 2827 -ne `wc -c <'mini-x/kernel/klib386.x.cdif'`; then
    echo shar: \"'mini-x/kernel/klib386.x.cdif'\" unpacked with wrong size!
fi
# end of 'mini-x/kernel/klib386.x.cdif'
fi
if test -f 'mini-x/kernel/makefile.cdif' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'mini-x/kernel/makefile.cdif'\"
else
echo shar: Extracting \"'mini-x/kernel/makefile.cdif'\" \(2505 characters\)
sed "s/^X//" >'mini-x/kernel/makefile.cdif' <<'END_OF_FILE'
X*** ../old/kernel/makefile	Mon Mar  4 21:05:43 1991
X--- makefile	Sat Apr 20 13:35:08 1991
X***************
X*** 1,4 ****
X- 
X  AS =as -3
X  BIN =/etc/system
X  CC =cc -3
X--- 1,3 ----
X***************
X*** 15,21 ****
X  s =/usr/include/sys
X  
X  KEROBJS =cstart.o protect.o protect1.o klib.o mpx.o wini.o table.o main.o tty.o floppy.o system.o proc.o clock.o memory.o console.o rs232.o rs2.o printer.o dmp.o exception.o i8259.o misc.o keyboard.o
X! SOBJS =start.s klib.s mpx.s rs2.s
X  
X  .SUFFIXES: .x
X  .x.s:
X--- 14,20 ----
X  s =/usr/include/sys
X  
X  KEROBJS =cstart.o protect.o protect1.o klib.o mpx.o wini.o table.o main.o tty.o floppy.o system.o proc.o clock.o memory.o console.o rs232.o rs2.o printer.o dmp.o exception.o i8259.o misc.o keyboard.o graphics.o graph_main.o graph_gen.o graph_clip.o cursor_gen.o graph_ega.o ega.o
X! SOBJS =start.s klib.s mpx.s rs2.s ega.s
X  
X  .SUFFIXES: .x
X  .x.s:
X***************
X*** 33,41 ****
X  $(BIN)/kernel: $(START) $(KEROBJS) $(LIBS) $(END)
X  	$(LD) $(LDFLAGS) -o $(BIN)/kernel $(START) $(KEROBJS) $(LIBS) $(END)
X  clean:
X- 
X- 
X- 
X  	rm -f $(START) $(KEROBJS) $(SOBJS)
X  
X  
X--- 32,37 ----
X***************
X*** 43,48 ****
X--- 39,45 ----
X  mpx.s: $h/config.h $h/const.h $h/com.h const.h protect.h sconst.h mpx.x
X  rs2.s: $h/config.h $h/const.h const.h sconst.h rs2.x
X  start.s: $h/config.h $h/const.h $h/com.h const.h protect.h sconst.h start.x
X+ ega.s: $h/config.h $h/const.h $h/com.h const.h protect.h sconst.h ega.x
X  
X  start.o: start.s
X  	$(AS) -0 -a start.s -o start.o
X***************
X*** 64,73 ****
X  cstart.o: $a
X  cstart.o: $h/boot.h
X  cstart.o: cstart.c
X- 
X  	bcc -0 -c $(CFLAGS) cstart.c
X  
X  
X  dmp.o: $a
X  dmp.o: $h/callnr.h
X  dmp.o: $h/com.h
X--- 61,74 ----
X  cstart.o: $a
X  cstart.o: $h/boot.h
X  cstart.o: cstart.c
X  	bcc -0 -c $(CFLAGS) cstart.c
X  
X  
X+ cursor_gen.o: $a
X+ cursor_gen.o: $i/graphics.h
X+ cursor_gen.o: $h/graph_msg.h
X+ cursor_gen.o: graph_dev.h
X+ 
X  dmp.o: $a
X  dmp.o: $h/callnr.h
X  dmp.o: $h/com.h
X***************
X*** 81,86 ****
X--- 82,108 ----
X  floppy.o: $h/callnr.h
X  floppy.o: $h/com.h
X  
X+ graphics.o: $a
X+ graphics.o: $i/graphics.h
X+ graphics.o: $h/graph_msg.h
X+ graphics.o: graph_dev.h
X+ 
X+ graph_clip.o: $a
X+ graph_clip.o: $i/graphics.h
X+ graph_clip.o: graph_dev.h
X+ 
X+ graph_ega.o: $a
X+ graph_ega.o: $i/graphics.h
X+ graph_ega.o: graph_dev.h
X+ 
X+ graph_gen.o: $a
X+ graph_gen.o: $i/graphics.h
X+ graph_gen.o: graph_dev.h
X+ 
X+ graph_main.o: $a
X+ graph_main.o: $i/graphics.h
X+ graph_main.o: graph_dev.h
X+ 
X  i8259.o: $a
X  
X  keyboard.o: $a
END_OF_FILE
if test 2505 -ne `wc -c <'mini-x/kernel/makefile.cdif'`; then
    echo shar: \"'mini-x/kernel/makefile.cdif'\" unpacked with wrong size!
fi
# end of 'mini-x/kernel/makefile.cdif'
fi
if test -f 'mini-x/kernel/makefile.cpp.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'mini-x/kernel/makefile.cpp.c'\"
else
echo shar: Extracting \"'mini-x/kernel/makefile.cpp.c'\" \(2119 characters\)
sed "s/^X//" >'mini-x/kernel/makefile.cpp.c' <<'END_OF_FILE'
X*** ../old/kernel/makefile.cpp	Tue Mar  5 22:13:26 1991
X--- makefile.cpp	Sat Apr 20 13:35:36 1991
X***************
X*** 56,63 ****
X  KEROBJS		=cstart.O protect.O protect1.O klib.O mpx.O wini.O \
X  	table.O main.O tty.O floppy.O system.O proc.O \
X  	clock.O memory.O console.O rs232.O rs2.O printer.O \
X! 	dmp.O exception.O i8259.O misc.O keyboard.O
X! SOBJS		=start.s klib.s mpx.s rs2.s
X  
X  # Rules.
X  .SUFFIXES: .x		# .x files are .s files which need C-preprocessing
X--- 56,66 ----
X  KEROBJS		=cstart.O protect.O protect1.O klib.O mpx.O wini.O \
X  	table.O main.O tty.O floppy.O system.O proc.O \
X  	clock.O memory.O console.O rs232.O rs2.O printer.O \
X! 	dmp.O exception.O i8259.O misc.O keyboard.O \
X! 	graphics.O graph_main.O graph_gen.O graph_clip.O cursor_gen.O \
X! 	graph_ega.O ega.O
X! 
X! SOBJS		=start.s klib.s mpx.s rs2.s ega.s
X  
X  # Rules.
X  .SUFFIXES: .x		# .x files are .s files which need C-preprocessing
X***************
X*** 98,103 ****
X--- 101,107 ----
X  mpx.s: $h/config.h $h/const.h $h/com.h const.h protect.h sconst.h mpx.x
X  rs2.s: $h/config.h $h/const.h const.h sconst.h rs2.x
X  start.s: $h/config.h $h/const.h $h/com.h const.h protect.h sconst.h start.x
X+ ega.s: $h/config.h $h/const.h $h/com.h const.h protect.h sconst.h ega.x
X  #if !ACK
X  start.O: start.s
X  	$(AS) -0 -a start.s -o start.O
X***************
X*** 123,128 ****
X--- 127,137 ----
X  	bcc -0 -c $(CFLAGS) cstart.c
X  #endif
X  
X+ cursor_gen.O:	$a
X+ cursor_gen.O:	$i/graphics.h
X+ cursor_gen.O:	$h/graph_msg.h
X+ cursor_gen.O:	graph_dev.h
X+ 
X  dmp.O:		$a
X  dmp.O:		$h/callnr.h
X  dmp.O:		$h/com.h
X***************
X*** 136,141 ****
X--- 145,171 ----
X  floppy.O:	$h/callnr.h
X  floppy.O:	$h/com.h
X  
X+ graphics.O:	$a
X+ graphics.O:	$i/graphics.h
X+ graphics.O:	$h/graph_msg.h
X+ graphics.O:	graph_dev.h
X+ 
X+ graph_clip.O:	$a
X+ graph_clip.O:	$i/graphics.h
X+ graph_clip.O:	graph_dev.h
X+ 
X+ graph_ega.O:	$a
X+ graph_ega.O:	$i/graphics.h
X+ graph_ega.O:	graph_dev.h
X+ 
X+ graph_gen.O:	$a
X+ graph_gen.O:	$i/graphics.h
X+ graph_gen.O:	graph_dev.h
X+ 
X+ graph_main.O:	$a
X+ graph_main.O:	$i/graphics.h
X+ graph_main.O:	graph_dev.h
X+ 
X  i8259.O:	$a
X  
X  keyboard.O:	$a
END_OF_FILE
if test 2119 -ne `wc -c <'mini-x/kernel/makefile.cpp.c'`; then
    echo shar: \"'mini-x/kernel/makefile.cpp.c'\" unpacked with wrong size!
fi
# end of 'mini-x/kernel/makefile.cpp.c'
fi
if test -f 'mini-x/kernel/makefile.cpp.n' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'mini-x/kernel/makefile.cpp.n'\"
else
echo shar: Extracting \"'mini-x/kernel/makefile.cpp.n'\" \(4726 characters\)
sed "s/^X//" >'mini-x/kernel/makefile.cpp.n' <<'END_OF_FILE'
X#if ACK
X# Makefile for kernel using standard Minix directory layout and compiler.
X# CPP may need changing to /usr/lib/cpp.
X# The following nonstandard flags are used:
X# -F:	run cpp and cem sequentially (used when memory is tight)
X# -T.:	put temporaries in working directory (when RAM disk is small)
X#	define	O	s
XBIN		=.
XCC		=cc
XCFLAGS		=-F -T.
XCPP		=/usr/lib/cpp
XCPPFLAGS	=-DASLD -P
XEND		=/usr/lib/end.s
XLD		=asld
XLDFLAGS		=-i
XLIBS		=/usr/lib/libc.a
XSTART		=start.O
X#else
X# Makefile for kernel using Bruce's Minix directory layout and compiler.
X# The following nonstandard flags are used:
X# -0:	produce 16-bit (8086) object code
X# -3:	produce 32-bit (80386) object code
X#	define	O	o
X#	if INTEL_32BITS
XAS		=as -3
XBIN		=/etc/system
XCC		=cc -3
XCFLAGS		=-DINTEL_32BITS
XCPP		=/usr/lib/cpp
XCPPFLAGS	=-DINTEL_32BITS -P
XLD		=ld -3
XLDFLAGS		=-i
XLIBS		=/usr/local/lib/i386/libc.a longlib.a
XSTART		=start.O
X#	else
XAS		=as -0 -a
XBIN		=/tmp
XCC		=cc -0
XCFLAGS		=
XCPP		=/usr/lib/cpp
XCPPFLAGS	=-P
XLD		=ld -0
XLDFLAGS		=-i
XLIBS		=/usr/local/lib/i86/libc.a
XSTART		=start.O
X#	endif
X#endif
X
Xa		=kernel.h $h/config.h $h/const.h $h/type.h \
X		 $s/types.h $i/limits.h $i/errno.h \
X		 const.h type.h proto.h glo.h
Xh		=/usr/include/minix
Xi		=/usr/include
Xs		=/usr/include/sys
X
XKEROBJS		=cstart.O protect.O protect1.O klib.O mpx.O wini.O \
X	table.O main.O tty.O floppy.O system.O proc.O \
X	clock.O memory.O console.O rs232.O rs2.O printer.O \
X	dmp.O exception.O i8259.O misc.O keyboard.O \
X	graphics.O graph_main.O graph_gen.O graph_clip.O cursor_gen.O \
X	graph_ega.O ega.O
X
XSOBJS		=start.s klib.s mpx.s rs2.s ega.s
X
X# Rules.
X.SUFFIXES: .x		# .x files are .s files which need C-preprocessing
X.x.s:
X	$(CPP) $(CPPFLAGS) $< >$@
X#if !ACK
X.s.O:
X	$(AS) $< -o $@
X.x.O:
X	$(CPP) $(CPPFLAGS) $< >$@
X	$(AS) $< -o $@
X#endif
X
X# What to make.
Xdummy: $(BIN)/kernel	# this line fixes a bug in RAL's latest make
X
X$(BIN)/kernel: $(START) $(KEROBJS) $(LIBS) $(END)
X#if ACK
X	$(LD) $(LDFLAGS) -o $(BIN)/kernel \
X	$(START) $(KEROBJS) \
X	$(LIBS) $(END) -s > kernel.sym
X	ast -X $(BIN)/kernel kernel.sym
X	@rm kernel.sym
X#else
X	$(LD) $(LDFLAGS) -o $(BIN)/kernel \
X	$(START) $(KEROBJS) \
X	$(LIBS) $(END)
X#endif
X
Xclean:
X#if ACK
X	@rm -f $(START) $(KEROBJS) $(SOBJS)
X#else
X	rm -f $(START) $(KEROBJS) $(SOBJS)
X#endif
X
Xklib.s: $h/config.h $h/const.h const.h protect.h sconst.h klib.x
Xmpx.s: $h/config.h $h/const.h $h/com.h const.h protect.h sconst.h mpx.x
Xrs2.s: $h/config.h $h/const.h const.h sconst.h rs2.x
Xstart.s: $h/config.h $h/const.h $h/com.h const.h protect.h sconst.h start.x
Xega.s: $h/config.h $h/const.h $h/com.h const.h protect.h sconst.h ega.x
X#if !ACK
Xstart.O: start.s
X	$(AS) -0 -a start.s -o start.O
X#endif
X
Xclock.O:	$a
Xclock.O:	$i/signal.h
Xclock.O:	$h/callnr.h
Xclock.O:	$h/com.h
Xclock.O:	proc.h
X
Xconsole.O:	$a
Xconsole.O:	$i/sgtty.h
Xconsole.O:	$h/callnr.h
Xconsole.O:	$h/com.h
Xconsole.O:	protect.h
Xconsole.O:	tty.h
X
Xcstart.O:	$a
Xcstart.O:	$h/boot.h
Xcstart.O:	cstart.c
X#if INTEL_32BITS
X	bcc -0 -c $(CFLAGS) cstart.c
X#endif
X
Xcursor_gen.O:	$a
Xcursor_gen.O:	$i/graphics.h
Xcursor_gen.O:	$h/graph_msg.h
Xcursor_gen.O:	graph_dev.h
X
Xdmp.O:		$a
Xdmp.O:		$h/callnr.h
Xdmp.O:		$h/com.h
Xdmp.O:		proc.h
X
Xexception.O:	$a
Xexception.O:	$i/signal.h
Xexception.O:	proc.h
X
Xfloppy.O:	$a
Xfloppy.O:	$h/callnr.h
Xfloppy.O:	$h/com.h
X
Xgraphics.O:	$a
Xgraphics.O:	$i/graphics.h
Xgraphics.O:	$h/graph_msg.h
Xgraphics.O:	graph_dev.h
X
Xgraph_clip.O:	$a
Xgraph_clip.O:	$i/graphics.h
Xgraph_clip.O:	graph_dev.h
X
Xgraph_ega.O:	$a
Xgraph_ega.O:	$i/graphics.h
Xgraph_ega.O:	graph_dev.h
X
Xgraph_gen.O:	$a
Xgraph_gen.O:	$i/graphics.h
Xgraph_gen.O:	graph_dev.h
X
Xgraph_main.O:	$a
Xgraph_main.O:	$i/graphics.h
Xgraph_main.O:	graph_dev.h
X
Xi8259.O:	$a
X
Xkeyboard.O:	$a
Xkeyboard.O:	$i/sgtty.h
Xkeyboard.O:	$i/signal.h
Xkeyboard.O:	$h/callnr.h
Xkeyboard.O:	$h/com.h
Xkeyboard.O:	tty.h
X
Xmain.O:	$a
Xmain.O:	$i/signal.h
Xmain.O:	$h/callnr.h
Xmain.O:	$h/com.h
Xmain.O:	proc.h
X
Xmemory.O:	$a
Xmemory.O:	$h/callnr.h
Xmemory.O:	$h/com.h
X
Xmisc.O:	$a
Xmisc.O:	$h/com.h
X
Xprinter.O:	$a
Xprinter.O:	$h/callnr.h
Xprinter.O:	$h/com.h
X
Xproc.O:	$a
Xproc.O:	$h/callnr.h
Xproc.O:	$h/com.h
Xproc.O:	proc.h
X
Xprotect.O:	$a
Xprotect.O:	protect.h
Xprotect.O:	protect1.c
X#if INTEL_32BITS
Xprotect.O:	protect.c
X	bcc -0 -c $(CFLAGS) protect.c
X#endif
X
Xprotect1.O:	$a
Xprotect1.O:	proc.h
Xprotect1.O:	protect.h
X
Xrs232.O:	$a
Xrs232.O:	$i/sgtty.h
Xrs232.O:	tty.h
X
Xsystem.O:	$a
Xsystem.O:	$i/signal.h
Xsystem.O:	$h/boot.h
Xsystem.O:	$h/callnr.h
Xsystem.O:	$h/com.h
Xsystem.O:	proc.h
Xsystem.O:	protect.h
X
Xtable.O:	$a
Xtable.O:	$h/com.h
Xtable.O:	proc.h
Xtable.O:	tty.h
X
Xtty.O:		$a
Xtty.O:		$i/sgtty.h
Xtty.O:		$i/signal.h
Xtty.O:		$h/callnr.h
Xtty.O:		$h/com.h
Xtty.O:		tty.h
X
Xwini.O:	$a
Xwini.O:	$h/callnr.h
Xwini.O:	$h/com.h
Xwini.O:	$h/partition.h
X#if ACK /* two gratuitous blank lines :-( */
X
X
X#endif
END_OF_FILE
if test 4726 -ne `wc -c <'mini-x/kernel/makefile.cpp.n'`; then
    echo shar: \"'mini-x/kernel/makefile.cpp.n'\" unpacked with wrong size!
fi
# end of 'mini-x/kernel/makefile.cpp.n'
fi
if test -f 'mini-x/kernel/makefile.new' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'mini-x/kernel/makefile.new'\"
else
echo shar: Extracting \"'mini-x/kernel/makefile.new'\" \(3325 characters\)
sed "s/^X//" >'mini-x/kernel/makefile.new' <<'END_OF_FILE'
XAS =as -3
XBIN =/etc/system
XCC =cc -3
XCFLAGS =-DINTEL_32BITS
XCPP =/usr/lib/cpp
XCPPFLAGS =-DINTEL_32BITS -P
XLD =ld -3
XLDFLAGS =-i
XLIBS =/usr/local/lib/i386/libc.a longlib.a
XSTART =start.o
Xa =kernel.h $h/config.h $h/const.h $h/type.h $s/types.h $i/limits.h $i/errno.h const.h type.h proto.h glo.h
Xh =/usr/include/minix
Xi =/usr/include
Xs =/usr/include/sys
X
XKEROBJS =cstart.o protect.o protect1.o klib.o mpx.o wini.o table.o main.o tty.o floppy.o system.o proc.o clock.o memory.o console.o rs232.o rs2.o printer.o dmp.o exception.o i8259.o misc.o keyboard.o graphics.o graph_main.o graph_gen.o graph_clip.o cursor_gen.o graph_ega.o ega.o
XSOBJS =start.s klib.s mpx.s rs2.s ega.s
X
X.SUFFIXES: .x
X.x.s:
X	$(CPP) $(CPPFLAGS) $< >$@
X
X.s.o:
X	$(AS) $< -o $@
X.x.o:
X	$(CPP) $(CPPFLAGS) $< >$@
X	$(AS) $< -o $@
X
X
Xdummy: $(BIN)/kernel
X
X$(BIN)/kernel: $(START) $(KEROBJS) $(LIBS) $(END)
X	$(LD) $(LDFLAGS) -o $(BIN)/kernel $(START) $(KEROBJS) $(LIBS) $(END)
Xclean:
X	rm -f $(START) $(KEROBJS) $(SOBJS)
X
X
Xklib.s: $h/config.h $h/const.h const.h protect.h sconst.h klib.x
Xmpx.s: $h/config.h $h/const.h $h/com.h const.h protect.h sconst.h mpx.x
Xrs2.s: $h/config.h $h/const.h const.h sconst.h rs2.x
Xstart.s: $h/config.h $h/const.h $h/com.h const.h protect.h sconst.h start.x
Xega.s: $h/config.h $h/const.h $h/com.h const.h protect.h sconst.h ega.x
X
Xstart.o: start.s
X	$(AS) -0 -a start.s -o start.o
X
X
Xclock.o: $a
Xclock.o: $i/signal.h
Xclock.o: $h/callnr.h
Xclock.o: $h/com.h
Xclock.o: proc.h
X
Xconsole.o: $a
Xconsole.o: $i/sgtty.h
Xconsole.o: $h/callnr.h
Xconsole.o: $h/com.h
Xconsole.o: protect.h
Xconsole.o: tty.h
X
Xcstart.o: $a
Xcstart.o: $h/boot.h
Xcstart.o: cstart.c
X	bcc -0 -c $(CFLAGS) cstart.c
X
X
Xcursor_gen.o: $a
Xcursor_gen.o: $i/graphics.h
Xcursor_gen.o: $h/graph_msg.h
Xcursor_gen.o: graph_dev.h
X
Xdmp.o: $a
Xdmp.o: $h/callnr.h
Xdmp.o: $h/com.h
Xdmp.o: proc.h
X
Xexception.o: $a
Xexception.o: $i/signal.h
Xexception.o: proc.h
X
Xfloppy.o: $a
Xfloppy.o: $h/callnr.h
Xfloppy.o: $h/com.h
X
Xgraphics.o: $a
Xgraphics.o: $i/graphics.h
Xgraphics.o: $h/graph_msg.h
Xgraphics.o: graph_dev.h
X
Xgraph_clip.o: $a
Xgraph_clip.o: $i/graphics.h
Xgraph_clip.o: graph_dev.h
X
Xgraph_ega.o: $a
Xgraph_ega.o: $i/graphics.h
Xgraph_ega.o: graph_dev.h
X
Xgraph_gen.o: $a
Xgraph_gen.o: $i/graphics.h
Xgraph_gen.o: graph_dev.h
X
Xgraph_main.o: $a
Xgraph_main.o: $i/graphics.h
Xgraph_main.o: graph_dev.h
X
Xi8259.o: $a
X
Xkeyboard.o: $a
Xkeyboard.o: $i/sgtty.h
Xkeyboard.o: $i/signal.h
Xkeyboard.o: $h/callnr.h
Xkeyboard.o: $h/com.h
Xkeyboard.o: tty.h
X
Xmain.o: $a
Xmain.o: $i/signal.h
Xmain.o: $h/callnr.h
Xmain.o: $h/com.h
Xmain.o: proc.h
X
Xmemory.o: $a
Xmemory.o: $h/callnr.h
Xmemory.o: $h/com.h
X
Xmisc.o: $a
Xmisc.o: $h/com.h
X
Xprinter.o: $a
Xprinter.o: $h/callnr.h
Xprinter.o: $h/com.h
X
Xproc.o: $a
Xproc.o: $h/callnr.h
Xproc.o: $h/com.h
Xproc.o: proc.h
X
Xprotect.o: $a
Xprotect.o: protect.h
Xprotect.o: protect1.c
X
Xprotect.o: protect.c
X	bcc -0 -c $(CFLAGS) protect.c
X
X
Xprotect1.o: $a
Xprotect1.o: proc.h
Xprotect1.o: protect.h
X
Xrs232.o: $a
Xrs232.o: $i/sgtty.h
Xrs232.o: tty.h
X
Xsystem.o: $a
Xsystem.o: $i/signal.h
Xsystem.o: $h/boot.h
Xsystem.o: $h/callnr.h
Xsystem.o: $h/com.h
Xsystem.o: proc.h
Xsystem.o: protect.h
X
Xtable.o: $a
Xtable.o: $h/com.h
Xtable.o: proc.h
Xtable.o: tty.h
X
Xtty.o: $a
Xtty.o: $i/sgtty.h
Xtty.o: $i/signal.h
Xtty.o: $h/callnr.h
Xtty.o: $h/com.h
Xtty.o: tty.h
X
Xwini.o: $a
Xwini.o: $h/callnr.h
Xwini.o: $h/com.h
Xwini.o: $h/partition.h
END_OF_FILE
if test 3325 -ne `wc -c <'mini-x/kernel/makefile.new'`; then
    echo shar: \"'mini-x/kernel/makefile.new'\" unpacked with wrong size!
fi
# end of 'mini-x/kernel/makefile.new'
fi
if test -f 'mini-x/kernel/proto.h.cdif' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'mini-x/kernel/proto.h.cdif'\"
else
echo shar: Extracting \"'mini-x/kernel/proto.h.cdif'\" \(294 characters\)
sed "s/^X//" >'mini-x/kernel/proto.h.cdif' <<'END_OF_FILE'
X*** ../old/kernel/proto.h	Tue Mar  5 22:13:23 1991
X--- proto.h	Tue Mar 12 21:38:17 1991
X***************
X*** 32,37 ****
X--- 32,40 ----
X  /* printer.c, stprint.c */
X  void printer_task();
X  
X+ /* graphics.c */
X+ void graphics_task();
X+ 
X  /* proc.c */
X  void interrupt();
X  int lock_mini_send();
END_OF_FILE
if test 294 -ne `wc -c <'mini-x/kernel/proto.h.cdif'`; then
    echo shar: \"'mini-x/kernel/proto.h.cdif'\" unpacked with wrong size!
fi
# end of 'mini-x/kernel/proto.h.cdif'
fi
if test -f 'mini-x/kernel/start.x.cdif' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'mini-x/kernel/start.x.cdif'\"
else
echo shar: Extracting \"'mini-x/kernel/start.x.cdif'\" \(571 characters\)
sed "s/^X//" >'mini-x/kernel/start.x.cdif' <<'END_OF_FILE'
X*** ../old/kernel/start.x	Tue Mar  5 22:13:26 1991
X--- start.x	Wed Apr 10 09:32:05 1991
X***************
X*** 5,10 ****
X--- 5,11 ----
X  .define		_db		| trap to external debugger
X  .define		_get_chrome	| returns nonzero if display is color
X  .define		_get_ega	| returns nonzero if display is ega
X+ .define		_get_rom_char_addr  | returns address of ROM character table
X  .define		_get_ext_memsize  | returns amount of extended memory in K
X  .define		_get_low_memsize  | returns amount of low memory in K
X  .define		_get_processor	| returns processor type (86, 186, 286, 386)
END_OF_FILE
if test 571 -ne `wc -c <'mini-x/kernel/start.x.cdif'`; then
    echo shar: \"'mini-x/kernel/start.x.cdif'\" unpacked with wrong size!
fi
# end of 'mini-x/kernel/start.x.cdif'
fi
if test -f 'mini-x/kernel/start.x.insert' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'mini-x/kernel/start.x.insert'\"
else
echo shar: Extracting \"'mini-x/kernel/start.x.insert'\" \(736 characters\)
sed "s/^X//" >'mini-x/kernel/start.x.insert' <<'END_OF_FILE'
X|*===========================================================================*
X|*				get_rom_char_addr 			     *
X|*===========================================================================*
X
X| PUBLIC u32_t get_rom_char_addr();
X| Call the BIOS to find out the address of the ROM character table. 
X
X_get_rom_char_addr:
X	push	bp		| interrupt uses these
X	push	es
X	mov	ax,#0x1130	| function for address of rom character table
X	mov	bx,#0x0202	| want address of ROM 8x14 character table
X	int	VIDEO		| return address in es:bp
X	mov	ax,es		| turn segment into physical address
X	mov	bx,ax
X	shl	ax,#4
X	shr	bx,#12
X	mov	cx,bp		| add offset into physical address
X	add	ax,cx
X	adc	bx,#0
X	mov	dx,bx
X	pop	es		| restore registers and return
X	pop	bp
X	ret
END_OF_FILE
if test 736 -ne `wc -c <'mini-x/kernel/start.x.insert'`; then
    echo shar: \"'mini-x/kernel/start.x.insert'\" unpacked with wrong size!
fi
# end of 'mini-x/kernel/start.x.insert'
fi
if test -f 'mini-x/kernel/table.c.cdif' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'mini-x/kernel/table.c.cdif'\"
else
echo shar: Extracting \"'mini-x/kernel/table.c.cdif'\" \(1162 characters\)
sed "s/^X//" >'mini-x/kernel/table.c.cdif' <<'END_OF_FILE'
X*** ../old/kernel/table.c	Tue Mar  5 22:13:20 1991
X--- table.c	Tue Mar 12 21:37:44 1991
X***************
X*** 42,47 ****
X--- 42,48 ----
X  #else
X  #define	IDLE_STACK	(3 * 2 + 3 * 2 + 4 * 2)	/* 3 intr, 3 temps, 4 db */
X  #endif
X+ #define	GRAPHICS_STACK	SMALL_STACK
X  #define	PRINTER_STACK	SMALL_STACK
X  #define	WINCH_STACK	SMALL_STACK
X  #define	FLOP_STACK	(3*SMALL_STACK/2)
X***************
X*** 61,67 ****
X  #endif
X  
X  #define	TOT_STACK_SPACE		(TTY_STACK + AMOEBA_STACK_SPACE + \
X! 				 IDLE_STACK + HARDWARE_STACK + \
X  				 PRINTER_STACK + WINCH_STACK + FLOP_STACK + \
X  				 MEM_STACK + CLOCK_STACK + SYS_STACK)
X  
X--- 62,68 ----
X  #endif
X  
X  #define	TOT_STACK_SPACE		(TTY_STACK + AMOEBA_STACK_SPACE + \
X! 				 IDLE_STACK + HARDWARE_STACK + GRAPHICS_STACK + \
X  				 PRINTER_STACK + WINCH_STACK + FLOP_STACK + \
X  				 MEM_STACK + CLOCK_STACK + SYS_STACK)
X  
X***************
X*** 85,90 ****
X--- 86,92 ----
X  	amoeba_task,		AMOEBA_STACK,	"AMTASK",
X  #endif
X  	idle_task,		IDLE_STACK,	"IDLE  ",
X+ 	graphics_task,		GRAPHICS_STACK,	"GRAPH ",
X  	printer_task,		PRINTER_STACK,	"PRINTR",
X  	winchester_task,	WINCH_STACK,	"WINCHE",
X  	floppy_task,		FLOP_STACK,	"FLOPPY",
END_OF_FILE
if test 1162 -ne `wc -c <'mini-x/kernel/table.c.cdif'`; then
    echo shar: \"'mini-x/kernel/table.c.cdif'\" unpacked with wrong size!
fi
# end of 'mini-x/kernel/table.c.cdif'
fi
if test -f 'mini-x/kernel/tty.c.cdif' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'mini-x/kernel/tty.c.cdif'\"
else
echo shar: Extracting \"'mini-x/kernel/tty.c.cdif'\" \(619 characters\)
sed "s/^X//" >'mini-x/kernel/tty.c.cdif' <<'END_OF_FILE'
X*** ../old/kernel/tty.c	Tue Mar  5 22:13:22 1991
X--- tty.c	Mon Apr  1 15:35:25 1991
X***************
X*** 461,466 ****
X--- 461,476 ----
X  	return;
X    }
X  
X+   /* If non-blocking is required see if we would block, and if so,
X+    * return EAGAIN to the caller.
X+    */  
X+   if (m_ptr->TTY_FLAGS && (tp->tty_incount == 0 ||
X+       !(tp->tty_mode & (RAW | CBREAK)) && tp->tty_lfct == 0))
X+   {
X+ 	tty_reply(TASK_REPLY, m_ptr->m_source, m_ptr->PROC_NR, EAGAIN);
X+ 	return;
X+   }
X+ 
X    /* Copy information from the message to the tty struct. */
X    tp->tty_incaller = m_ptr->m_source;
X    tp->tty_inproc = m_ptr->PROC_NR;
END_OF_FILE
if test 619 -ne `wc -c <'mini-x/kernel/tty.c.cdif'`; then
    echo shar: \"'mini-x/kernel/tty.c.cdif'\" unpacked with wrong size!
fi
# end of 'mini-x/kernel/tty.c.cdif'
fi
if test -f 'mini-x/server/keyboard.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'mini-x/server/keyboard.c'\"
else
echo shar: Extracting \"'mini-x/server/keyboard.c'\" \(2281 characters\)
sed "s/^X//" >'mini-x/server/keyboard.c' <<'END_OF_FILE'
X/*
X * Copyright (c) 1991 David I. Bell
X * Permission is granted to use, distribute, or modify this source,
X * provided that this copyright notice remains intact.
X *
X * Keyboard reading routines.
X */
X#include <fcntl.h>
X#include <errno.h>
X#include <sgtty.h>
X#include "graph_serv.h"
X
X
X/*
X * The following is the keyboard device associated with the screen.
X */
X#define	KEYBOARD	"/dev/console"
X
X
X/*
X * Defining debug disables setting of the terminal modes, making it
X * easier to see output.
X */
X#define	DEBUG	0
X
X
Xstatic	int		fd;		/* file descriptor for keyboard */
Xstatic	struct sgttyb	oldsgttyb;	/* original terminal modes */
X
X
X/*
X * Open the keyboard.
X * This is real simple, we just use a special file handle
X * that allows non-blocking I/O, and put the terminal into
X * character mode.
X */
Xint
XGsOpenKeyboard()
X{
X	struct sgttyb	newsgttyb;	/* new terminal modes */
X
X	fd = open(KEYBOARD, O_NONBLOCK);
X	if (fd < 0)
X		return -1;
X
X	if (ioctl(fd, TIOCGETP, &oldsgttyb) < 0) {
X		close(fd);
X		fd = 0;
X		return -1;
X	}
X
X#if !DEBUG
X	newsgttyb = oldsgttyb;
X	newsgttyb.sg_flags |= CBREAK;
X	newsgttyb.sg_flags &= ~(EVENP | ODDP | ECHO | XTABS | CRMOD);
X
X	if (ioctl(fd, TIOCSETP, &newsgttyb) < 0) {
X		close(fd);
X		fd = 0;
X		return -1;
X	}
X#endif
X	return 0;
X}
X
X
X
X/*
X * Return the possible modifiers for the keyboard.
X */
Xvoid
XGsGetModifierInfo(modifiers)
X	GR_MODIFIER	*modifiers;	/* returned mask of modifiers */
X{
X	*modifiers = 0;			/* no modifiers available */
X}
X
X
X/*
X * Close the keyboard.
X * This resets the terminal modes.
X */
Xvoid
XGsCloseKeyboard()
X{
X	ioctl(fd, TIOCSETP, &oldsgttyb);
X	close(fd);
X	fd = 0;
X}
X
X
X/*
X * This reads one keystroke from the keyboard, and the current state of
X * the mode keys (ALT, SHIFT, CTRL).  Returns -1 on error, 0 if no data
X * is ready, and 1 if data was read.  This is a non-blocking call.
X * Without MINIX kernel changes, no shift keys information is available.
X */
Xint
XGsReadKeyboard(buf, modifiers)
X	GR_CHAR		*buf;		/* data character */
X	GR_MODIFIER	*modifiers;	/* modifier keys (SHIFT, CTRL, etc) */
X{
X	int	cc;			/* characters read */
X
X#if	DEBUG
X	return	0;
X#endif
X
X	*modifiers = 0;			/* no modifiers yet */
X	cc = read(fd, buf, 1);
X	if (cc > 0)
X		return 1;
X	if ((cc < 0) && (errno != EINTR) && (errno != EAGAIN))
X		return -1;
X	return 0;
X}
X
X/* END CODE */
END_OF_FILE
if test 2281 -ne `wc -c <'mini-x/server/keyboard.c'`; then
    echo shar: \"'mini-x/server/keyboard.c'\" unpacked with wrong size!
fi
# end of 'mini-x/server/keyboard.c'
fi
if test -f 'mini-x/server/makefile' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'mini-x/server/makefile'\"
else
echo shar: Extracting \"'mini-x/server/makefile'\" \(965 characters\)
sed "s/^X//" >'mini-x/server/makefile' <<'END_OF_FILE'
XCFLAGS = -i -O
XLDFLAGS = -i
XLIBDIR = /usr/local/lib/i386
X
XLIBFILES = client.o serv_main.o serv_func.o serv_util.o serv_event.o \
X	serv_dev.o mouse.o mousedev.o keyboard.o
X
Xall:	libgraph.a
X
Xinstall:	libgraph.a
X	cp libgraph.a $(LIBDIR)/libgraph.a
X	chmod 644 $(LIBDIR)/libgraph.a
X
Xclean:
X	rm -rf $(LIBFILES) libgraph.a
X
Xlibgraph.a:	$(LIBFILES)
X	rm -f libgraph.a
X	ar qc libgraph.a $(LIBFILES)
X
Xclient.o:	/usr/include/graphics.h
Xclient.o:	graph_serv.h
X
Xkeyboard.o:	/usr/include/graphics.h
Xkeyboard.o:	graph_serv.h
X
Xmouse.o:	/usr/include/graphics.h
Xmouse.o:	graph_serv.h
X
Xmousedev.o:	/usr/include/graphics.h
X
Xserv_dev.o:	/usr/include/graphics.h
Xserv_dev.o:	/usr/include/minix/graph_msg.h
Xserv_dev.o:	graph_serv.h
X
Xserv_event.o:	/usr/include/graphics.h
Xserv_event.o:	graph_serv.h
X
Xserv_func.o:	/usr/include/graphics.h
Xserv_func.o:	graph_serv.h
X
Xserv_main.o:	/usr/include/graphics.h
Xserv_main.o:	graph_serv.h
X
Xserv_util.o:	/usr/include/graphics.h
Xserv_util.o:	graph_serv.h
END_OF_FILE
if test 965 -ne `wc -c <'mini-x/server/makefile'`; then
    echo shar: \"'mini-x/server/makefile'\" unpacked with wrong size!
fi
# end of 'mini-x/server/makefile'
fi
if test -f 'mini-x/server/mouse.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'mini-x/server/mouse.c'\"
else
echo shar: Extracting \"'mini-x/server/mouse.c'\" \(4826 characters\)
sed "s/^X//" >'mini-x/server/mouse.c' <<'END_OF_FILE'
X/*
X * Copyright (c) 1991 David I. Bell
X * Permission is granted to use, distribute, or modify this source,
X * provided that this copyright notice remains intact.
X *
X * Mouse server routines.
X * Reads data from mouse driver and tracks real position on the screen.
X */
X#include <stdio.h>
X#include "graph_serv.h"
X
X
X#define	SCALE	3		/* default scaling factor for acceleration */
X#define	THRESH	5		/* default threshhold for acceleration */
X
X
Xstatic GR_COORD		xpos;		/* current x position of mouse */
Xstatic GR_COORD		ypos;		/* current y position of mouse */
Xstatic GR_COORD		minx;		/* minimum allowed x position */
Xstatic GR_COORD		maxx;		/* maximum allowed x position */
Xstatic GR_COORD		miny;		/* minimum allowed y position */
Xstatic GR_COORD		maxy;		/* maximum allowed y position */
Xstatic GR_SIZE		scale;		/* acceleration scale factor */
Xstatic GR_SIZE		thresh;		/* acceleration threshhold */
Xstatic GR_BUTTON	buttons;	/* current state of buttons */
Xstatic GR_BOOL		changed;	/* mouse state has changed */
X
X
Xextern	int	GdOpenMouse();
Xextern	int	GdReadMouse();
Xextern	void	GdGetButtonInfo();
Xextern	void	GdCloseMouse();
X
X
X/*
X * Initialize the mouse.
X * This sets its position to (0, 0) with no boundaries and no buttons pressed.
X * Returns nonzero on error.
X */
XGsOpenMouse()
X{
X	if (GdOpenMouse(NULL, NULL) < 0)
X		return -1;
X	thresh = THRESH;
X	scale = SCALE;
X	buttons = 0;
X	xpos = 0;
X	ypos = 0;
X	minx = GR_COORD_MIN;
X	miny = GR_COORD_MIN;
X	maxx = GR_COORD_MAX;
X	maxy = GR_COORD_MAX;
X	changed = GR_TRUE;
X	return 0;
X}
X
X
X/*
X * Return which mouse buttons are implemented.
X */
Xvoid
XGsGetButtonInfo(buttons)
X	GR_BUTTON	*buttons;	/* buttons which are implemented */
X{
X	GdGetButtonInfo(buttons);
X}
X
X
X/*
X * Terminate the use of the mouse.
X */
Xvoid
XGsCloseMouse()
X{
X	GdCloseMouse();
X}
X
X
X/*
X * Restrict the coordinates of the mouse to the specified coordinates.
X */
Xvoid
XGsRestrictMouse(newminx, newminy, newmaxx, newmaxy)
X	GR_COORD	newminx;	/* new minimum x position */
X	GR_COORD	newminy;	/* new minimum y position */
X	GR_COORD	newmaxx;	/* new maximum x position */
X	GR_COORD	newmaxy;	/* new maximum y position */
X{
X	minx = newminx;
X	miny = newminy;
X	maxx = newmaxx;
X	maxy = newmaxy;
X	GsMoveMouse(xpos, ypos);
X}
X
X
X/*
X * Set the acceleration threshhold and scale factors.
X * Acceleration makes the cursor move further for faster movements.
X * Basically, at mouse speeds above the threshold, the excess distance
X * moved is multiplied by the scale factor.  For example, with a threshhold
X * of 5 and a scale of 3, the following gives examples of the original and
X * modified mouse movements:
X *	input:		0	4	5	6	9	20
X *	output:		0	4	5	8	17	50
X */
Xvoid
XGsSetAccelMouse(newthresh, newscale)
X	GR_SIZE		newthresh;	/* new acceleration threshhold */
X	GR_SIZE		newscale;	/* new acceleration scale factor */
X{
X	if (newthresh < 0)
X		newthresh = 0;
X	if (newscale < 0)
X		newscale = 0;
X	thresh = newthresh;
X	scale = newscale;
X}
X
X
X/*
X * Move the mouse to the specified coordinates.
X * The location is limited by the current mouse coordinate restrictions.
X */
Xvoid
XGsMoveMouse(newx, newy)
X	GR_COORD	newx;		/* desired new x position of mouse */
X	GR_COORD	newy;		/* desired new y position of mouse */
X{
X	if (newx < minx)
X		newx = minx;
X	if (newx > maxx)
X		newx = maxx;
X	if (newy < miny)
X		newy = miny;
X	if (newy > maxy)
X		newy = maxy;
X	if ((newx != xpos) || (newy != ypos))
X		changed = GR_TRUE;
X	xpos = newx;
X	ypos = newy;
X}
X
X
X/*
X * Read the current location and button states of the mouse.
X * Returns -1 on read error, 0 if nothing new has happened, and 1 if a
X * new position was read.  The current mouse position and buttons are
X * returned even if the position hasn't changed.  This routine does
X * not block.
X */
Xint
XGsReadMouse(xp, yp, bp)
X	GR_COORD	*xp;		/* returned x position */
X	GR_COORD	*yp;		/* returned y position */
X	GR_BUTTON	*bp;		/* returned button state */
X{
X	GR_COORD	deltax;		/* change in x position */
X	GR_COORD	deltay;		/* change in y position */
X	GR_BUTTON	newbuttons;	/* new button state */
X	int		sign;		/* sign of change */
X	int		status;		/* status of reading mouse */
X
X	*xp = xpos;
X	*yp = ypos;
X	*bp = buttons;
X
X	if (changed) {
X		changed = GR_FALSE;
X		return 1;
X	}
X
X	status = GdReadMouse(&deltax, &deltay, &newbuttons);
X	if (status < 0)
X		return -1;
X
X	if (status == 0)
X		return 0;
X
X	if (buttons != newbuttons) {
X		changed = GR_TRUE;
X		buttons = newbuttons;
X	}
X
X	sign = 1;
X	if (deltax < 0) {
X		sign = -1;
X		deltax = -deltax;
X	}
X	if (deltax > thresh)
X		deltax = thresh + (deltax - thresh) * scale;
X	deltax *= sign;
X
X	sign = 1;
X	if (deltay < 0) {
X		sign = -1;
X		deltay = -deltay;
X	}
X	if (deltay > thresh)
X		deltay = thresh + (deltay - thresh) * scale;
X	deltay *= sign;
X
X	GsMoveMouse(xpos + deltax, ypos + deltay);
X
X	if (!changed)
X		return 0;
X
X	changed = GR_FALSE;
X	*xp = xpos;
X	*yp = ypos;
X	*bp = buttons;
X	return 1;
X}
X
X/* END CODE */
END_OF_FILE
if test 4826 -ne `wc -c <'mini-x/server/mouse.c'`; then
    echo shar: \"'mini-x/server/mouse.c'\" unpacked with wrong size!
fi
# end of 'mini-x/server/mouse.c'
fi
if test -f 'mini-x/server/serv_main.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'mini-x/server/serv_main.c'\"
else
echo shar: Extracting \"'mini-x/server/serv_main.c'\" \(5039 characters\)
sed "s/^X//" >'mini-x/server/serv_main.c' <<'END_OF_FILE'
X/*
X * Copyright (c) 1991 David I. Bell
X * Permission is granted to use, distribute, or modify this source,
X * provided that this copyright notice remains intact.
X *
X * Main module of graphics server.
X */
X#include <stdio.h>
X#include "graph_serv.h"
X
X
X/*
X * External definitions defined here.
X */
Xchar *		curfunc;		/* current function name */
XGR_WINDOW_ID	cachewindowid;		/* cached window id */
XGR_GC_ID	cachegcid;		/* cached graphics context id */
XGR_WINDOW	*cachewp;		/* cached window pointer */
XGR_GC		*cachegcp;		/* cached graphics context */
XGR_WINDOW	*listwp;		/* list of all windows */
XGR_WINDOW	*rootwp;		/* root window pointer */
XGR_GC		*listgcp;		/* list of all gc */
XGR_GC		*curgcp;		/* currently enabled gc */
XGR_WINDOW	*clipwp;		/* window clipping is set for */
XGR_WINDOW	*focuswp;		/* focus window for keyboard */
XGR_WINDOW	*mousewp;		/* window mouse is currently in */
XGR_WINDOW	*grabbuttonwp;		/* window grabbed by button */
XGR_CURSOR	*curcursor;		/* currently enabled cursor */
XGR_COORD	cursorx;		/* current x position of cursor */
XGR_COORD	cursory;		/* current y position of cursor */
XGR_BUTTON	curbuttons;		/* current state of buttons */
XGR_CLIENT	*curclient;		/* client currently executing for */
XGR_EVENT_LIST	*eventfree;		/* list of free events */
XGR_EVENT_NUMBER	eventnumber;		/* current event number */
XGR_BOOL		inited;			/* TRUE if been initialized */
XGR_BOOL		focusfixed;		/* TRUE if focus is fixed on a window */
XGR_SCREEN_INFO	sinfo;			/* screen information */
XGR_FONT_INFO	curfont;		/* current font information */
XGR_CLIENT	clients[GR_MAX_CLIENTS];	/* table of clients */
X
X
Xstatic	int	connectcount;		/* number of connections to server */
X
X
X/*
X * When the server is a separate process from the client,
X * then this main would be executed, and would drive the whole
X * server loop.
X */
X#if 0
Xmain(argc, argv)
X	char	**argv;
X{
X	if (GsInitialize())
X		exit(1);
X
X	/* read initialization file to start up default clients */
X
X	/* let clients connect and service them until all are gone */
X
X	GsTerminate();
X}
X#endif
X
X
X/*
X * Initialize the graphics and mouse devices at startup.
X * Returns nonzero with a message printed if the initialization failed.
X */
Xint
XGsInitialize()
X{
X	GR_WINDOW	*wp;		/* root window */
X	GR_CURSOR	*cp;		/* cursor for root window */
X
X	if (connectcount > 0) {
X		connectcount++;
X		return 0;
X	}
X
X	wp = (GR_WINDOW *) malloc(sizeof(GR_WINDOW));
X	if (wp == NULL) {
X		fprintf(stderr, "Cannot allocate root window\n");
X		return -1;
X	}
X
X	cp = (GR_CURSOR *) malloc(sizeof(GR_CURSOR));
X	if (cp == NULL) {
X		fprintf(stderr, "Cannot allocate cursor\n");
X		return -1;
X	}
X
X	if (GsOpenMouse() < 0) {
X		fprintf(stderr, "Cannot initialize mouse: ");
X		perror("");
X		free(wp);
X		free(cp);
X		return -1;
X	}
X
X	if (GsOpenKeyboard() < 0) {
X		fprintf(stderr, "Cannot initialize keyboard: ");
X		perror("");
X		GsCloseMouse();
X		free(wp);
X		free(cp);
X		return -1;
X	}
X
X	if (GdOpenScreen(0, 0, 0) < 0) {
X		fprintf(stderr, "Cannot initialize screen: ");
X		perror("");
X		GsCloseMouse();
X		GsCloseKeyboard();
X		free(wp);
X		free(cp);
X		return -1;
X	}
X
X	/*
X	 * Get screen dimensions for our own and the client's use,
X	 * and the information about the default font.
X	 */
X	GdGetScreenInfo(&sinfo);
X	GdGetFontInfo(0, &curfont);
X	GsGetModifierInfo(&sinfo.modifiers);
X	GsGetButtonInfo(&sinfo.buttons);
X
X	/*
X	 * Initialize the default cursor.
X	 */
X	cp->usecount = 1;
X	cp->foreground = sinfo.white;
X	cp->background = sinfo.black;
X	cp->width = 5;
X	cp->height = 5;
X	cp->hotx = 2;
X	cp->hoty = 2;
X	cp->fgbitmap[0] = 0x8800;	/* X---X */
X	cp->fgbitmap[1] = 0x5000;	/* -X-X- */
X	cp->fgbitmap[2] = 0x2000;	/* --X-- */
X	cp->fgbitmap[3] = 0x5000;	/* -X-X- */
X	cp->fgbitmap[4] = 0x8800;	/* X---X */
X
X	cp->bgbitmap[0] = 0xd800;	/* XX-XX */
X	cp->bgbitmap[1] = 0xf800;	/* XXXXX */
X	cp->bgbitmap[2] = 0x7000;	/* -XXX- */
X	cp->bgbitmap[3] = 0xf800;	/* XXXXX */
X	cp->bgbitmap[4] = 0xd800;	/* XX-XX */
X
X	curcursor = NULL;
X	cursorx = -1;
X	cursory = -1;
X
X	/*
X	 * Initialize the root window.
X	 */
X	wp->id = GR_ROOT_WINDOW_ID;
X	wp->parent = wp;
X	wp->children = NULL;
X	wp->siblings = NULL;
X	wp->next = NULL;
X	wp->x = 0;
X	wp->y = 0;
X	wp->width = sinfo.cols;
X	wp->height = sinfo.rows;
X	wp->bordersize = 0;
X	wp->background = sinfo.black;
X	wp->bordercolor = sinfo.black;
X	wp->nopropmask = 0;
X	wp->eventclients = NULL;
X	wp->cursor = cp;
X	wp->mapped = GR_TRUE;
X	wp->unmapcount = 0;
X	wp->output = GR_TRUE;
X	listwp = wp;
X	rootwp = wp;
X	focuswp = wp;
X	mousewp = wp;
X	focusfixed = GR_FALSE;
X
X	/*
X	 * Finally tell the mouse driver some things and tell the
X	 * screen driver where the cursor should go.
X	 */
X	curbuttons = 0;
X	GsSetAccelMouse(5, 3);
X	GsRestrictMouse(0, 0, sinfo.cols - 1, sinfo.rows - 1);
X	GsMoveMouse(sinfo.cols / 2, sinfo.rows / 2);
X	GsMoveCursor(sinfo.cols / 2, sinfo.rows / 2);
X	GsFlush();
X
X	/*
X	 * All done.
X	 */
X	connectcount = 1;
X	inited = GR_TRUE;
X
X	return 0;
X}
X
X
X/*
X * Here to close down the server.
X */
Xvoid
XGsTerminate()
X{
X	if (--connectcount == 0) {
X		GdCloseScreen();
X		GsCloseMouse();
X		GsCloseKeyboard();
X		inited = GR_FALSE;
X	}
X}
X
X/* END CODE */
END_OF_FILE
if test 5039 -ne `wc -c <'mini-x/server/serv_main.c'`; then
    echo shar: \"'mini-x/server/serv_main.c'\" unpacked with wrong size!
fi
# end of 'mini-x/server/serv_main.c'
fi
echo shar: End of archive 1 \(of 9\).
cp /dev/null ark1isdone
MISSING=""
for I in 1 2 3 4 5 6 7 8 9 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked all 9 archives.
    rm -f ark[1-9]isdone ark[1-9][0-9]isdone
else
    echo You still need to unpack the following archives:
    echo "        " ${MISSING}
fi
##  End of shell archive.
exit 0

dbell@pdact.pd.necisa.oz.au (David I. Bell) (04/22/91)

#! /bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of archive 2 (of 9)."
# Contents:  mini-x/clients/demo.c mini-x/include/graph_msg.h
#   mini-x/kernel/cursor_gen.c mini-x/kernel/graph_clip.c
#   mini-x/server/graph_serv.h mini-x/server/mousedev.c
# Wrapped by dbell@elm on Mon Apr 22 11:21:43 1991
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'mini-x/clients/demo.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'mini-x/clients/demo.c'\"
else
echo shar: Extracting \"'mini-x/clients/demo.c'\" \(9582 characters\)
sed "s/^X//" >'mini-x/clients/demo.c' <<'END_OF_FILE'
X/*
X * Demonstration program for mini-X graphics.
X */
X#include <stdio.h>
X#include <graphics.h>
X
X/*
X * Definitions to make it easy to define cursors
X */
X#define	_	((unsigned) 0)		/* off bits */
X#define	X	((unsigned) 1)		/* on bits */
X#define	MASK(a,b,c,d,e,f,g) \
X	(((((((((((((a * 2) + b) * 2) + c) * 2) + d) * 2) \
X	+ e) * 2) + f) * 2) + g) << 9)
X
X#define	W2_WIDTH	70
X#define	W2_HEIGHT	40
X
X
Xstatic	GR_WINDOW_ID	w1;		/* id for large window */
Xstatic	GR_WINDOW_ID	w2;		/* id for small window */
Xstatic	GR_WINDOW_ID	w3;		/* id for third window */
Xstatic	GR_WINDOW_ID	w4;		/* id for grabbable window */
Xstatic	GR_WINDOW_ID	w5;		/* id for testing enter/exit window */
Xstatic	GR_GC_ID	gc1;		/* graphics context for text */
Xstatic	GR_GC_ID	gc2;		/* graphics context for rectangle */
Xstatic	GR_GC_ID	gc3;		/* graphics context for circles */
Xstatic	GR_GC_ID	gc4;		/* graphics context for lines */
Xstatic	GR_COORD	begxpos;	/* beginning x position */
Xstatic	GR_COORD	xpos;		/* x position for text drawing */
Xstatic	GR_COORD	ypos;		/* y position for text drawing */
Xstatic	GR_COORD	linexpos;	/* x position for line drawing */
Xstatic	GR_COORD	lineypos;	/* y position for line drawing */
Xstatic	GR_COORD	xorxpos;	/* x position for xor line */
Xstatic	GR_COORD	xorypos;	/* y position for xor line */
Xstatic	GR_BOOL		lineok;		/* ok to draw line */
Xstatic	GR_SCREEN_INFO	si;		/* information about screen */
X
Xvoid	errorcatcher();			/* routine to handle errors */
X
X
Xmain(argc, argv)
X	char	**argv;
X{
X	GR_EVENT	event;		/* current event */
X	GR_BITMAP	bitmap1fg[7];	/* bitmaps for first cursor */
X	GR_BITMAP	bitmap1bg[7];
X	GR_BITMAP	bitmap2fg[7];	/* bitmaps for second cursor */
X	GR_BITMAP	bitmap2bg[7];
X
X	if (GrOpen() < 0) {
X		fprintf(stderr, "cannot open graphics\n");
X		exit(1);
X	}
X	GrGetScreenInfo(&si);
X
X	GrSetErrorHandler(errorcatcher);
X
X	w1 = GrNewWindow(GR_ROOT_WINDOW_ID, 100, 50, si.cols - 120,
X		si.rows - 60, 1, 6, 15);
X	w2 = GrNewWindow(GR_ROOT_WINDOW_ID, 6, 6, W2_WIDTH, W2_HEIGHT, 2, 2, 15);
X	w3 = GrNewWindow(GR_ROOT_WINDOW_ID, 250, 30, 80, 100, 1, 7, 2);
X	w4 = GrNewWindow(GR_ROOT_WINDOW_ID, 350, 20, 200, 150, 5, 0, 15);
X	w5 = GrNewWindow(GR_ROOT_WINDOW_ID, 11, 143, 209, 100, 1, 1, 2);
X
X	GrSelectEvents(w1, GR_EVENT_MASK_BUTTON_DOWN |
X		GR_EVENT_MASK_KEY_DOWN | GR_EVENT_MASK_EXPOSURE |
X		GR_EVENT_MASK_FOCUS_IN | GR_EVENT_MASK_FOCUS_OUT);
X	GrSelectEvents(w2, GR_EVENT_MASK_BUTTON_UP);
X	GrSelectEvents(w3, GR_EVENT_MASK_BUTTON_DOWN |
X		GR_EVENT_MASK_MOUSE_MOTION);
X	GrSelectEvents(w4, GR_EVENT_MASK_BUTTON_DOWN |
X		GR_EVENT_MASK_BUTTON_UP | GR_EVENT_MASK_MOUSE_POSITION |
X		GR_EVENT_MASK_KEY_DOWN);
X	GrSelectEvents(w5, GR_EVENT_MASK_MOUSE_ENTER |
X		GR_EVENT_MASK_MOUSE_EXIT);
X	GrSelectEvents(GR_ROOT_WINDOW_ID, GR_EVENT_MASK_BUTTON_DOWN);
X
X	GrMapWindow(w1);
X	GrMapWindow(w2);
X	GrMapWindow(w3);
X	GrMapWindow(w4);
X	GrMapWindow(w5);
X
X	gc1 = GrNewGC();
X	gc2 = GrNewGC();
X	gc3 = GrNewGC();
X	gc4 = GrNewGC();
X
X	GrSetGCForeground(gc1, 4);
X	GrSetGCBackground(gc1, 6);
X	GrSetGCForeground(gc2, 5);
X	GrSetGCMode(gc4, GR_MODE_XOR);
X
X	bitmap1fg[0] = MASK(_,_,_,X,_,_,_);
X	bitmap1fg[1] = MASK(_,_,_,X,_,_,_);
X	bitmap1fg[2] = MASK(_,_,_,X,_,_,_);
X	bitmap1fg[3] = MASK(X,X,X,X,X,X,X);
X	bitmap1fg[4] = MASK(_,_,_,X,_,_,_);
X	bitmap1fg[5] = MASK(_,_,_,X,_,_,_);
X	bitmap1fg[6] = MASK(_,_,_,X,_,_,_);
X
X	bitmap1bg[0] = MASK(_,_,X,X,X,_,_);
X	bitmap1bg[1] = MASK(_,_,X,X,X,_,_);
X	bitmap1bg[2] = MASK(X,X,X,X,X,X,X);
X	bitmap1bg[3] = MASK(X,X,X,X,X,X,X);
X	bitmap1bg[4] = MASK(X,X,X,X,X,X,X);
X	bitmap1bg[5] = MASK(_,_,X,X,X,_,_);
X	bitmap1bg[6] = MASK(_,_,X,X,X,_,_);
X
X	bitmap2fg[0] = MASK(_,_,X,X,X,_,_);
X	bitmap2fg[1] = MASK(_,X,_,_,_,X,_);
X	bitmap2fg[2] = MASK(X,_,_,_,_,_,X);
X	bitmap2fg[3] = MASK(X,_,_,_,_,_,X);
X	bitmap2fg[4] = MASK(_,X,_,_,_,X,_);
X	bitmap2fg[5] = MASK(_,_,X,X,X,_,_);
X
X	bitmap2bg[0] = MASK(_,_,X,X,X,_,_);
X	bitmap2bg[1] = MASK(_,X,X,X,X,X,_);
X	bitmap2bg[2] = MASK(X,X,X,X,X,X,X);
X	bitmap2bg[3] = MASK(X,X,X,X,X,X,X);
X	bitmap2bg[4] = MASK(_,X,X,X,X,X,_);
X	bitmap2bg[5] = MASK(_,_,X,X,X,_,_);
X
X	GrSetCursor(w1, 7, 7, 3, 3, si.white, si.black, bitmap1fg, bitmap1bg);
X	GrSetCursor(w2, 7, 7, 3, 3, si.white, si.black, bitmap2fg, bitmap2bg);
X
X	GrRect(GR_ROOT_WINDOW_ID, gc1, 0, 0, si.cols, si.rows);
X
X	while (1) {
X		GrCheckNextEvent(&event);
X
X		switch (event.type) {
X			case GR_EVENT_TYPE_BUTTON_DOWN:
X				do_buttondown(&event.button);
X				break;
X
X			case GR_EVENT_TYPE_BUTTON_UP:
X				do_buttonup(&event.button);
X				break;
X
X			case GR_EVENT_TYPE_MOUSE_POSITION:
X			case GR_EVENT_TYPE_MOUSE_MOTION:
X				do_motion(&event.mouse);
X				break;
X
X			case GR_EVENT_TYPE_KEY_DOWN:
X				do_keystroke(&event.keystroke);
X				break;
X
X			case GR_EVENT_TYPE_EXPOSURE:
X				do_exposure(&event.exposure);
X				break;
X
X			case GR_EVENT_TYPE_FOCUS_IN:
X				do_focusin(&event.general);
X				break;
X
X			case GR_EVENT_TYPE_FOCUS_OUT:
X				do_focusout(&event.general);
X				break;
X
X			case GR_EVENT_TYPE_MOUSE_ENTER:
X				do_enter(&event.general);
X				break;
X
X			case GR_EVENT_TYPE_MOUSE_EXIT:
X				do_exit(&event.general);
X				break;
X
X			case GR_EVENT_TYPE_NONE:
X				do_idle();
X				break;
X		}
X	}
X}
X
X
X/*
X * Here when a button is pressed.
X */
Xdo_buttondown(bp)
X	GR_EVENT_BUTTON	*bp;
X{
X	GR_COLOR8	intable[W2_WIDTH * W2_HEIGHT];
X	GR_COLOR8	outtable[W2_WIDTH * W2_HEIGHT * 4];
X	GR_COLOR8	*inp;
X	GR_COLOR8	*outp;
X	GR_COLOR8	*oldinp;
X	GR_COORD	row;
X	GR_COORD	col;
X
X	if (bp->wid == w3) {
X		GrRaiseWindow(w3);
X		GrReadArea8(w2, 0, 0, W2_WIDTH, W2_HEIGHT, intable);
X		inp = intable;
X		outp = outtable;
X		for (row = 0; row < W2_HEIGHT; row++) {
X			oldinp = inp;
X			for (col = 0; col < W2_WIDTH; col++) {
X				*outp++ = *inp;
X				*outp++ = *inp++;
X			}
X			inp = oldinp;
X			for (col = 0; col < W2_WIDTH; col++) {
X				*outp++ = *inp;
X				*outp++ = *inp++;
X			}
X		}
X		GrArea8(w1, gc1, 0, 0, W2_WIDTH * 2, W2_HEIGHT * 2, outtable);
X		return;
X	}
X
X	if (bp->wid == w4) {
X		GrRaiseWindow(w4);
X		linexpos = bp->x;
X		lineypos = bp->y;
X		xorxpos = bp->x;
X		xorypos = bp->y;
X		GrLine(w4, gc4, xorxpos, xorypos, linexpos, lineypos);
X		lineok = GR_TRUE;
X		return;
X	}
X
X	if (bp->wid != w1) {
X		/*
X		 * Cause a fatal error for testing if more than one
X		 * button is pressed.
X		 */
X		if ((bp->buttons & -((int) bp->buttons)) != bp->buttons)
X			GrClearWindow(-1, 0);
X		return;
X	}
X
X	GrRaiseWindow(w1);
X
X	if (bp->buttons & GR_BUTTON_1) {
X		GrClearWindow(w1, GR_TRUE);
X		return;
X	}
X
X	begxpos = bp->x;
X	xpos = bp->x;
X	ypos = bp->y;
X}
X
X
X/*
X * Here when a button is released.
X */
Xdo_buttonup(bp)
X	GR_EVENT_BUTTON	*bp;
X{
X	if (bp->wid == w4) {
X		if (lineok) {
X			GrLine(w4, gc4, xorxpos, xorypos, linexpos, lineypos);
X			GrLine(w4, gc3, bp->x, bp->y, linexpos, lineypos);
X		}
X		lineok = GR_FALSE;
X		return;
X	}
X
X	if (bp->wid == w2) {
X		GrClose();
X		exit(0);
X	}
X}
X
X
X/*
X * Here when the mouse has a motion event.
X */
Xdo_motion(mp)
X	GR_EVENT_MOUSE	*mp;
X{
X	if (mp->wid == w4) {
X		if (lineok) {
X			GrLine(w4, gc4, xorxpos, xorypos, linexpos, lineypos);
X			xorxpos = mp->x;
X			xorypos = mp->y;
X			GrLine(w4, gc4, xorxpos, xorypos, linexpos, lineypos);
X		}
X		return;
X	}
X
X	if (mp->wid == w3) {
X		GrPoint(w3, gc3, mp->x, mp->y);
X		return;
X	}
X}
X
X
X/*
X * Here when a keyboard press occurs.
X */
Xdo_keystroke(kp)
X	GR_EVENT_KEYSTROKE	*kp;
X{
X	GR_SIZE		width;		/* width of character */
X	GR_SIZE		height;		/* height of character */
X	GR_SIZE		base;		/* height of baseline */
X
X	if (kp->wid == w4) {
X		if (lineok) {
X			GrLine(w4, gc4, xorxpos, xorypos, linexpos, lineypos);
X			lineok = GR_FALSE;
X		}
X		return;
X	}
X
X	GrGetGCTextSize(gc1, &kp->ch, 1, &width, &height, &base);
X	if ((kp->ch == '\r') || (kp->ch == '\n')) {
X		xpos = begxpos;
X		ypos += height;
X		return;
X	}
X	if (kp->ch == '\b') {		/* assumes fixed width font!! */
X		if (xpos <= begxpos)
X			return;
X		xpos -= width;
X		GrSetGCForeground(gc3, 6);
X		GrFillRect(w1, gc3, xpos, ypos - height + base + 1,
X			width, height);
X		return;
X	}
X	GrText(w1, gc1, xpos, ypos + base, &kp->ch, 1);
X	xpos += width;
X}
X
X
X/*
X * Here when an exposure event occurs.
X */
Xdo_exposure(ep)
X	GR_EVENT_EXPOSURE	*ep;
X{
X	GR_POINT	points[3];
X
X	if (ep->wid != w1)
X		return;
X	points[0].x = 311;
X	points[0].y = 119;
X	points[1].x = 350;
X	points[1].y = 270;
X	points[2].x = 247;
X	points[2].y = 147;
X
X	GrFillRect(w1, gc2, 50, 50, 150, 200);
X	GrFillPoly(w1, gc2, 3, points);
X}
X
X
X/*
X * Here when a focus in event occurs.
X */
Xdo_focusin(gp)
X	GR_EVENT_GENERAL	*gp;
X{
X	if (gp->wid != w1)
X		return;
X	GrSetBorderColor(w1, 15);
X}
X
X
X/*
X * Here when a focus out event occurs.
X */
Xdo_focusout(gp)
X	GR_EVENT_GENERAL	*gp;
X{
X	if (gp->wid != w1)
X		return;
X	GrSetBorderColor(w1, 7);
X}
X
X
X/*
X * Here when a enter window event occurs.
X */
Xdo_enter(gp)
X	GR_EVENT_GENERAL	*gp;
X{
X	if (gp->wid != w5)
X		return;
X	GrSetBorderColor(w5, 15);
X	GrRaiseWindow(w5);
X}
X
X
X/*
X * Here when a exit window event occurs.
X */
Xdo_exit(gp)
X	GR_EVENT_GENERAL	*gp;
X{
X	if (gp->wid != w5)
X		return;
X	GrSetBorderColor(w5, 2);
X	GrLowerWindow(w5);
X}
X
X
X/*
X * Here to do an idle task when nothing else is happening.
X * Just draw a randomly colored filled circle in the small window.
X */
Xdo_idle()
X{
X	GR_COORD	x;
X	GR_COORD	y;
X	GR_SIZE		rx;
X	GR_SIZE		ry;
X	GR_COLOR	color;
X
X	x = rand() % 70;
X	y = rand() % 40;
X	rx = (rand() % 10) + 5;
X	ry = (rx * si.ydpcm) / si.xdpcm;	/* make it appear circular */
X	color = rand() % (si.maxcolor + 1);
X
X	GrSetGCForeground(gc3, color);
X	GrFillEllipse(w2, gc3, x, y, rx, ry);	
X}
X
X
X/*
X * Here on an unrecoverable error.
X */
Xvoid
Xerrorcatcher(code, name, id)
X	GR_ERROR	code;		/* error code */
X	GR_FUNC_NAME	name;		/* function name which failed */
X	GR_ID		id;		/* resource id */
X{
X	GrClose();
X	fprintf(stderr, "DEMO ERROR: code %d, function %s, resource id %d\n",
X		code, name, id);
X	exit(1);
X}
END_OF_FILE
if test 9582 -ne `wc -c <'mini-x/clients/demo.c'`; then
    echo shar: \"'mini-x/clients/demo.c'\" unpacked with wrong size!
fi
# end of 'mini-x/clients/demo.c'
fi
if test -f 'mini-x/include/graph_msg.h' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'mini-x/include/graph_msg.h'\"
else
echo shar: Extracting \"'mini-x/include/graph_msg.h'\" \(5685 characters\)
sed "s/^X//" >'mini-x/include/graph_msg.h' <<'END_OF_FILE'
X/* Copyright (c) 1991 David I. Bell
X * Permission is granted to use, distribute, or modify this source,
X * provided that this copyright notice remains intact.
X *
X * mini-X graphics - message interface between server and device driver
X */
X
X#ifndef	GRAPH_MSG_H
X#define	GRAPH_MSG_H
X
X#include <graphics.h>
X
X
X/* Flag definitions. */
Xtypedef unsigned short GR_FLAGS;	/* flag values */
X
X#define	GR_FLAG_FILLAREA	((GR_FLAGS) 0x01)	/* fill areas */
X
X
X/* Messages for drawing primitives. */
Xtypedef struct {
X  GR_FUNC func;			/* function code */
X  GR_COUNT count;		/* count of items */
X  GR_FLAGS flags;		/* flags to modify function */
X  short pad;			/* padding */
X} GR_MSG_HEADER;
X
X
Xtypedef struct {
X  GR_MSG_HEADER head;
X  long magic;			/* magic number (and version) */
X  GR_SIZE rows;			/* number of rows (or 0) */
X  GR_SIZE cols;			/* number of columns (or 0) */
X  long colors;			/* number of colors (or 0) */
X} GR_MSG_INIT;
X
X
Xtypedef struct {
X  GR_MSG_HEADER head;
X} GR_MSG_TERM;
X
X
Xtypedef struct {
X  GR_MSG_HEADER head;
X  GR_POINT points[1];
X} GR_MSG_POINTS;
X
X
Xtypedef struct {
X  GR_MSG_HEADER head;
X  GR_LINE lines[1];
X} GR_MSG_LINES;
X
X
Xtypedef struct {
X  GR_MSG_HEADER head;
X  GR_RECT rects[1];
X} GR_MSG_RECTS;
X
X
Xtypedef struct {
X  GR_MSG_HEADER head;
X  GR_ELLIPSE ellips[1];
X} GR_MSG_ELLIPS;
X
X
Xtypedef struct {
X  GR_MSG_HEADER head;
X  GR_POINT points[1];
X} GR_MSG_POLY;
X
X
Xtypedef struct {
X  GR_MSG_HEADER head;
X  GR_COLOR foreground;
X} GR_MSG_SETFOREGROUND;
X
X
Xtypedef struct {
X  GR_MSG_HEADER head;
X  GR_COLOR background;
X} GR_MSG_SETBACKGROUND;
X
X
Xtypedef struct {
X  GR_MSG_HEADER head;
X  GR_BOOL flag;
X} GR_MSG_SETUSEBACKGROUND;
X
X
Xtypedef struct {
X  GR_MSG_HEADER head;
X  GR_RECT cliprects[1];
X} GR_MSG_SETCLIPRECTS;
X
X
Xtypedef struct {
X  GR_MSG_HEADER head;
X  GR_MODE mode;
X} GR_MSG_SETMODE;
X
X
Xtypedef struct {
X  GR_MSG_HEADER head;
X  GR_COORD x;
X  GR_COORD y;
X  GR_SIZE width;
X  GR_SIZE height;
X  GR_COLOR8 colors[1];
X} GR_MSG_AREA8;
X
X
Xtypedef struct {
X  GR_MSG_HEADER head;
X  GR_COORD x;
X  GR_COORD y;
X  GR_SIZE width;
X  GR_SIZE height;
X  GR_BITMAP bitmaps[1];
X} GR_MSG_BITMAP;
X
X
Xtypedef struct {
X  GR_MSG_HEADER head;
X  GR_COORD x;
X  GR_COORD y;
X  GR_CHAR chars[1];
X} GR_MSG_TEXT;
X
X
Xtypedef struct {
X  GR_MSG_HEADER head;
X  GR_COORD sx;
X  GR_COORD sy;
X  GR_COORD dx;
X  GR_COORD dy;
X  GR_SIZE width;
X  GR_SIZE height;
X} GR_MSG_COPYAREA;
X
X
Xtypedef struct {
X  GR_MSG_HEADER head;
X  GR_SIZE width;
X  GR_SIZE height;
X  GR_COLOR foreground;
X  GR_COLOR background;
X  GR_BITMAP bitmaps[1];
X} GR_MSG_SETCURSOR;
X
X
Xtypedef struct {
X  GR_MSG_HEADER head;
X  GR_COORD x;
X  GR_COORD y;
X} GR_MSG_MOVECURSOR;
X
X
Xtypedef struct {
X  GR_MSG_HEADER head;
X  GR_COORD x;
X  GR_COORD y;
X  GR_SIZE width;
X  GR_SIZE height;
X} GR_MSG_READAREA8;
X
X
Xtypedef struct {
X  GR_MSG_HEADER head;
X} GR_MSG_GETSCREENINFO;
X
X
Xtypedef struct {
X  GR_MSG_HEADER head;
X  GR_FONT font;
X} GR_MSG_GETFONTINFO;
X
X
X/* Rounding function to make sure that each message in a buffer begins
X * on a word boundary.  Some machines will trap if this is not done.
X */
X#define	GR_ROUND(len)	(((len) + 3) & ~3)
X
X
X/* Sizes of some messages, according to the number of items in the message. */
X#define	GR_SIZEOF_MSG_POINTS(count) GR_ROUND(sizeof(GR_MSG_POINTS) + \
X  (((long) (count)) - 1) * sizeof(GR_POINT))
X
X#define	GR_SIZEOF_MSG_LINES(count) GR_ROUND(sizeof(GR_MSG_LINES) + \
X  (((long) (count)) - 1) * sizeof(GR_LINE))
X
X#define	GR_SIZEOF_MSG_RECTS(count) GR_ROUND(sizeof(GR_MSG_RECTS) + \
X  (((long) (count)) - 1) * sizeof(GR_RECT))
X
X#define	GR_SIZEOF_MSG_ELLIPS(count) GR_ROUND(sizeof(GR_MSG_ELLIPS) + \
X  (((long) (count)) - 1) * sizeof(GR_ELLIPSE))
X
X#define	GR_SIZEOF_MSG_POLY(count) GR_ROUND(sizeof(GR_MSG_POLY) + \
X  (((long) (count)) - 1) * sizeof(GR_POINT))
X
X#define	GR_SIZEOF_MSG_AREA8(count) GR_ROUND(sizeof(GR_MSG_AREA8) + \
X  (((long) (count)) - 1) * sizeof(GR_COLOR8))
X
X#define	GR_SIZEOF_MSG_BITMAP(count) GR_ROUND(sizeof(GR_MSG_BITMAP) + \
X  (((long) (count)) - 1) * sizeof(GR_BITMAP))
X
X#define	GR_SIZEOF_MSG_TEXT(count) GR_ROUND(sizeof(GR_MSG_TEXT) + \
X  (((long) (count)) - 1) * sizeof(GR_CHAR))
X
X#define	GR_SIZEOF_MSG_SETCLIPRECTS(count) GR_ROUND(sizeof(GR_MSG_SETCLIPRECTS) + \
X  (((long) (count)) - 1) * sizeof(GR_RECT))
X
X#define	GR_SIZEOF_MSG_SETCURSOR(count) GR_ROUND(sizeof(GR_MSG_SETCURSOR) + \
X  (((long) (count)) - 1) * sizeof(GR_BITMAP))
X
X
X/* Macro to convert from a number of adjacent bits to the number of
X * bitmap words needed to hold that many bits.
X */
X#define	BITMAP_WORDS(bits) (((bits) + (sizeof(GR_BITMAP) * 8) - 1) \
X  / (sizeof(GR_BITMAP) * 8))
X
X
X/* Maximum values */
X#define	GR_MAX_SIZEOF_MSG	2000
X#define	GR_MAX_COUNT		1000
X
X
X/* Magic value to prevent accidental use of the graphics device, and also to
X * verify that the device driver and graphics library structures are in sync.
X * Incrementing this value allows for new versions of the structures to be used.
X * It also allows the word and byte order of messages to be determined if
X * that ever becomes necessary (networks).
X */
X#define	GR_INIT_MAGIC		0x99880001L
X
X
X/* Function codes */
X#define	GR_FUNC_NOP		0
X#define	GR_FUNC_INIT		1
X#define	GR_FUNC_SETFOREGROUND	2
X#define	GR_FUNC_SETCLIPRECTS	3
X#define	GR_FUNC_DRAWPOINTS	4
X#define	GR_FUNC_DRAWLINES	5
X#define	GR_FUNC_DRAWRECTS	6
X#define	GR_FUNC_DRAWPOLY	7
X#define	GR_FUNC_DRAWELLIPS	8
X#define	GR_FUNC_DRAWTEXT	9
X#define	GR_FUNC_DRAWAREA8	10
X#define	GR_FUNC_DRAWBITMAP	11
X#define	GR_FUNC_COPYAREA	12
X#define	GR_FUNC_SETCURSOR	13
X#define	GR_FUNC_MOVECURSOR	14
X#define	GR_FUNC_SETBACKGROUND	15
X#define	GR_FUNC_SETMODE		16
X#define	GR_FUNC_TERM		17
X#define	GR_FUNC_READAREA8	18
X#define	GR_FUNC_GETSCREENINFO	19
X#define	GR_FUNC_SETUSEBACKGROUND 20
X#define	GR_FUNC_GETFONTINFO	21
X
X#endif
X
X/* END CODE */
END_OF_FILE
if test 5685 -ne `wc -c <'mini-x/include/graph_msg.h'`; then
    echo shar: \"'mini-x/include/graph_msg.h'\" unpacked with wrong size!
fi
# end of 'mini-x/include/graph_msg.h'
fi
if test -f 'mini-x/kernel/cursor_gen.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'mini-x/kernel/cursor_gen.c'\"
else
echo shar: Extracting \"'mini-x/kernel/cursor_gen.c'\" \(8077 characters\)
sed "s/^X//" >'mini-x/kernel/cursor_gen.c' <<'END_OF_FILE'
X/* Copyright (c) 1991 David I. Bell
X * Permission is granted to use, distribute, or modify this source,
X * provided that this copyright notice remains intact.
X *
X * Generic routines to keep track of the cursor.
X * This implements totally software driven graphics cursors.
X * If your system has hardware cursors, then none of this is
X * needed, and a set of functions for your hardware will suffice.
X */
X
X#include "kernel.h"
X#include "graph_dev.h"
X#include <minix/graph_msg.h>
X
X
X/* The following definition is used to save old colors for the cursor.
X * For space reasons, this is defined to be 8 bit colors.  If your colors
X * are more than 8 bits, then redefine this.
X */
X#ifndef GR_COLORN
X#define	GR_COLORN	GR_COLOR8
X#endif
X
X
X/* Cursor size, position, colors, and bitmap. */
XPRIVATE GR_BOOL curenabled;	/* TRUE if cursor is visible */
XPRIVATE GR_BOOL curneedfix;	/* TRUE if cursor needs fixing */
XPRIVATE GR_COORD curminx;	/* minimum x value of cursor */
XPRIVATE GR_COORD curminy;	/* minimum y value of cursor */
XPRIVATE GR_COORD curmaxx;	/* maximum x value of cursor */
XPRIVATE GR_COORD curmaxy;	/* maximum y value of cursor */
XPRIVATE GR_COLOR curfg;		/* foreground color of cursor */
XPRIVATE GR_COLOR curbg;		/* background color of cursor */
XPRIVATE GR_BITMAP curfgbitmap[GR_MAX_CURSOR_SIZE];	/* foreground bitmap */
XPRIVATE GR_BITMAP curbgbitmap[GR_MAX_CURSOR_SIZE];	/* background bitmap */
X
X
X/* Saved pixels from graphics screen so they can be restored later.
X * The only pixels that are actually saved are the ones where the foreground
X * or background bitmaps are nonzero.
X */
XPRIVATE GR_COLORN savedpoints[GR_MAX_CURSOR_SIZE * GR_MAX_CURSOR_SIZE];
X
X
XFORWARD removecursor();
XFORWARD showcursor();
X
X
X/*===========================================================================*
X *				gen_initcursor				     *
X *===========================================================================*/
XPUBLIC void gen_initcursor()
X{
X/* Initialize the cursor when graphics is initialized.  This just indicates
X * that the cursor is not being show.
X */
X  curenabled = GR_FALSE;
X  curneedfix = GR_FALSE;
X}
X
X
X/*===========================================================================*
X *				gen_setcursor				     *
X *===========================================================================*/
XPUBLIC void gen_setcursor(width, height, foreground, background, fgbitmap, bgbitmap)
XGR_SIZE width;			/* width of cursor */
XGR_SIZE height;			/* height of cursor */
XGR_COLOR foreground;		/* foreground color */
XGR_COLOR background;		/* background color */
XGR_BITMAP *fgbitmap;		/* foreground bitmap table */
XGR_BITMAP *bgbitmap;		/* background bitmap table */
X{
X/* Set the size, shape, and colors of the cursor.
X * This first removes the old cursor if there was one visible.
X * The new cursor is only drawn if the old one was too.
X */
X  GR_BOOL saveenabled;		/* saved enabled flag */
X  int bytes;			/* number of bytes to copy */
X
X  if ((width <= 0) || (width > GR_MAX_CURSOR_SIZE)
X      || (height <= 0) || (height > GR_MAX_CURSOR_SIZE))
X	return;
X
X  saveenabled = removecursor();
X  curfg = foreground;
X  curbg = background;
X  curmaxx = curminx + width - 1;
X  curmaxy = curminy + height - 1;
X  bytes = BITMAP_WORDS(width) * height * sizeof(GR_BITMAP);
X  memcpy(curfgbitmap, fgbitmap, bytes);
X  memcpy(curbgbitmap, bgbitmap, bytes);
X  if (saveenabled) showcursor();
X}
X
X
X/*===========================================================================*
X *				gen_movecursor				     *
X *===========================================================================*/
XPUBLIC void gen_movecursor(x, y)
XGR_COORD x;			/* new x position of cursor */
XGR_COORD y;			/* new y position of cursor */
X{
X/* Change the position of the cursor to the specified coordinates.
X * This makes the cursor visible if it was not previously visible.
X * The cursor can be made invisible by moving it off of the screen.
X */
X  GR_COORD shiftx;
X  GR_COORD shifty;
X
X  shiftx = x - curminx;
X  shifty = y - curminy;
X  if ((shiftx == 0) && (shifty == 0)) return;
X  removecursor();
X  curminx += shiftx;
X  curmaxx += shiftx;
X  curminy += shifty;
X  curmaxy += shifty;
X  if ((curmaxx >= 0) && (curminx < gr_dev.cols) && (curmaxy >= 0)
X      && (curminy < gr_dev.rows))
X	showcursor();
X}
X
X
X/*===========================================================================*
X *				removecursor				     *
X *===========================================================================*/
XPRIVATE int removecursor()
X{
X/* Remove the cursor from the screen.
X * This just restores the pixels that were saved before the cursor was put
X * on the screen.  Returns the previous state of the cursor enabled flag.
X */
X  GR_COLORN *saveptr;
X  GR_BITMAP *fgbitptr;
X  GR_BITMAP *bgbitptr;
X  GR_COORD x;
X  GR_COORD y;
X  GR_BITMAP allbits;
X  GR_BITMAP curbit;
X
X  if (!curenabled) return GR_FALSE;
X
X  if (gr_mode != GR_MODE_SET) (*gr_dev.setmode) (GR_MODE_SET);
X
X  saveptr = savedpoints;
X  fgbitptr = curfgbitmap;
X  bgbitptr = curbgbitmap;
X
X  for (y = curminy; y <= curmaxy; y++) {
X	curbit = 0;
X	for (x = curminx; x <= curmaxx; x++) {
X		if (curbit == 0) {
X			allbits = *fgbitptr++ | *bgbitptr++;
X			curbit = GR_FIRSTBIT;
X		}
X		if (curbit & allbits) (*gr_dev.drawpoint) (x, y, *saveptr++);
X		curbit = GR_NEXTBIT(curbit);
X	}
X  }
X  if (gr_mode != GR_MODE_SET) (*gr_dev.setmode) (gr_mode);
X
X  curenabled = GR_FALSE;
X
X  return GR_TRUE;
X}
X
X
X/*===========================================================================*
X *				showcursor				     *
X *===========================================================================*/
XPRIVATE int showcursor()
X{
X/* Show the cursor on the screen.
X * This must first save the pixel values on the screen that will be
X * overwritten by the cursor, so that they can be restored later.
X * Returns the previous state of the cursor enabled flag.
X */
X  GR_COLORN *saveptr;
X  GR_BITMAP *fgbitptr;
X  GR_BITMAP *bgbitptr;
X  GR_COORD x;
X  GR_COORD y;
X  GR_BITMAP fgbits;
X  GR_BITMAP bgbits;
X  GR_BITMAP curbit;
X  GR_COLOR oldcolor;
X  GR_COLOR newcolor;
X  GR_BOOL dosave;
X
X  if (curenabled) return GR_TRUE;
X
X  if (gr_mode != GR_MODE_SET) (*gr_dev.setmode) (GR_MODE_SET);
X
X  saveptr = savedpoints;
X  fgbitptr = curfgbitmap;
X  bgbitptr = curbgbitmap;
X
X  for (y = curminy; y <= curmaxy; y++) {
X	curbit = 0;
X	for (x = curminx; x <= curmaxx; x++) {
X		if (curbit == 0) {
X			fgbits = *fgbitptr++;
X			bgbits = *bgbitptr++;
X			curbit = GR_FIRSTBIT;
X		}
X		dosave = GR_FALSE;
X		if (curbit & fgbits) {
X			newcolor = curfg;
X			dosave = GR_TRUE;
X		} else if (curbit & bgbits) {
X			newcolor = curbg;
X			dosave = GR_TRUE;
X		}
X		if (dosave) {
X			oldcolor = (*gr_dev.readpoint) (x, y);
X			if (oldcolor != newcolor)
X				(*gr_dev.drawpoint) (x, y, newcolor);
X			*saveptr++ = oldcolor;
X		}
X		curbit = GR_NEXTBIT(curbit);
X	}
X  }
X
X  if (gr_mode != GR_MODE_SET) (*gr_dev.setmode) (gr_mode);
X
X  curenabled = GR_TRUE;
X  curneedfix = GR_FALSE;
X
X  return GR_FALSE;
X}
X
X
X/*===========================================================================*
X *				gen_checkcursor				     *
X *===========================================================================*/
XPUBLIC void gen_checkcursor(x1, y1, x2, y2)
XGR_COORD x1;
XGR_COORD y1;
XGR_COORD x2;
XGR_COORD y2;
X{
X/* Check to see if the cursor is about to be overwritten.
X * If so, then remove the cursor so that the graphics operation
X * works correctly.  If the cursor is removed, then this fact will
X * be remembered and a later call to fixcursor will restore it.
X */
X  GR_COORD temp;
X
X  if (!curenabled) return;
X
X  if (x1 > x2) {
X	temp = x1;
X	x1 = x2;
X	x2 = temp;
X  }
X  if (y1 > y2) {
X	temp = y1;
X	y1 = y2;
X	y2 = temp;
X  }
X  if ((x1 > curmaxx) || (x2 < curminx) ||
X      (y1 > curmaxy) || (y2 < curminy))
X	return;
X
X  removecursor();
X  curneedfix = GR_TRUE;
X  return;
X}
X
X
X/*===========================================================================*
X *				gen_fixcursor				     *
X *===========================================================================*/
XPUBLIC void gen_fixcursor()
X{
X/* Fix back up the cursor if it was removed because of a graphics operation. */
X  if (curneedfix) showcursor();
X}
X
X/* END CODE */
END_OF_FILE
if test 8077 -ne `wc -c <'mini-x/kernel/cursor_gen.c'`; then
    echo shar: \"'mini-x/kernel/cursor_gen.c'\" unpacked with wrong size!
fi
# end of 'mini-x/kernel/cursor_gen.c'
fi
if test -f 'mini-x/kernel/graph_clip.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'mini-x/kernel/graph_clip.c'\"
else
echo shar: Extracting \"'mini-x/kernel/graph_clip.c'\" \(8352 characters\)
sed "s/^X//" >'mini-x/kernel/graph_clip.c' <<'END_OF_FILE'
X/* Copyright (c) 1991 David I. Bell
X * Permission is granted to use, distribute, or modify this source,
X * provided that this copyright notice remains intact.
X *
X * Routines to determine clipping regions.
X */
X
X#include "kernel.h"
X#include "graph_dev.h"
X
X
X/* Clip cache rectangle information.
X * After calling clippoint, this rectangle is guaranteed to contain the
X * specified point (among others), and all points in the rectangle are
X * plottable or not according to the value of clipresult.
X */
XGR_COORD clipminx;		/* minimum x value of cache rectangle */
XGR_COORD clipminy;		/* minimum y value of cache rectangle */
XGR_COORD clipmaxx;		/* maximum x value of cache rectangle */
XGR_COORD clipmaxy;		/* maximum y value of cache rectangle */
XGR_BOOL clipresult;		/* whether clip rectangle is plottable */
X
X
XPRIVATE GR_COUNT clipcount;	/* number of clip rectangles */
XPRIVATE GR_RECT cliprects[GR_MAX_CLIPRECTS];	/* clip rectangles */
X
X
X/*===========================================================================*
X *				clipinit				     *
X *===========================================================================*/
XPUBLIC void clipinit(count, table)
XGR_COUNT count;			/* number of clip rectangles */
XGR_RECT *table;			/* rectangle table */
X{
X/* Specify a new set of clip rectangles.
X * This should only be called after the device has been initialized.
X * If zero clip rectangles are specified, then clipping is done to the
X * full device area.  All clip rectangles are modified if necessary to
X * lie within the device area.
X */
X  register GR_RECT *rp;		/* current rectangle */
X
X  /* If there are no clip rectangles, then default to the full device area. */
X  if (count <= 0) {
X	clipminx = 0;
X	clipminy = 0;
X	clipmaxx = gr_dev.cols - 1;
X	clipmaxy = gr_dev.rows - 1;
X	clipcount = 0;
X	clipresult = GR_TRUE;
X	return;
X  }
X
X  /* Copy the clip table to our own static array, modifying each
X   * rectangle as necesary to fit within the device area.  If the clip
X   * rectangle lies entirely outside of the device area, then skip it.
X   */
X  rp = cliprects;
X  clipcount = 0;
X  if (count > GR_MAX_CLIPRECTS) count = GR_MAX_CLIPRECTS;
X  while (count-- > 0) {
X	*rp = *table++;
X	if (rp->x < 0) {
X		rp->width += rp->x;
X		rp->x = 0;
X	}
X	if (rp->y < 0) {
X		rp->height += rp->y;
X		rp->y = 0;
X	}
X	if ((rp->x >= gr_dev.cols) || (rp->width <= 0) ||
X	    (rp->y >= gr_dev.rows) || (rp->height <= 0))
X		continue;
X	if (rp->x + rp->width > gr_dev.cols) rp->width = gr_dev.cols - rp->x;
X	if (rp->y + rp->height > gr_dev.rows)
X		rp->height = gr_dev.rows - rp->y;
X	rp++;
X	clipcount++;
X  }
X
X  /* If there were no surviving clip rectangles, then set the clip
X   * cache to prevent all drawing.
X   */
X  if (clipcount == 0) {
X	clipminx = GR_COORD_MIN;
X	clipminy = GR_COORD_MIN;
X	clipmaxx = GR_COORD_MAX;
X	clipmaxy = GR_COORD_MAX;
X	clipresult = GR_FALSE;
X	return;
X  }
X
X  /* There was at least one valid clip rectangle. Default the clip
X   * cache to be the first clip rectangle.
X   */
X  clipminx = cliprects[0].x;
X  clipminy = cliprects[0].y;
X  clipmaxx = clipminx + cliprects[0].width - 1;
X  clipmaxy = clipminy + cliprects[0].height - 1;
X  clipresult = GR_TRUE;
X}
X
X
X/*===========================================================================*
X *				clippoint				     *
X *===========================================================================*/
XPUBLIC GR_BOOL
X clippoint(x, y)
XGR_COORD x;
XGR_COORD y;
X{
X/* Check a point against the list of clip rectangles.
X * Returns TRUE if the point is within one or more rectangles and thus
X * can be plotted, or FALSE if the point is not within any rectangle and
X * thus cannot be plotted.  Also remembers the coordinates of a clip cache
X * rectangle containing the specified point such that every point in the
X * rectangle would give the same result.  By examining this clip cache
X * rectangle after a call to this routine, the caller can efficiently
X * check many nearby points without needing any further calls.  If the
X * point lies within the cursor, then the cursor is removed.
X */
X  GR_COUNT count;
X  GR_RECT *rp;
X  GR_COORD temp;
X
X  /* First see whether the point lies within the current clip cache
X   * rectangle.  If so, then we already know the result.
X   */
X  if ((x >= clipminx) && (x <= clipmaxx) &&
X      (y >= clipminy) && (y <= clipmaxy)) {
X	if (clipresult) (*gr_dev.checkcursor) (x, y, x, y);
X	return clipresult;
X  }
X
X  /* If the point is outside of the screen area, then it is not
X   * plottable, and the clip cache rectangle is the whole half-plane
X   * outside of the screen area.
X   */
X  if (x < 0) {
X	clipminx = GR_COORD_MIN;
X	clipmaxx = -1;
X	clipminy = GR_COORD_MIN;
X	clipmaxy = GR_COORD_MAX;
X	clipresult = GR_FALSE;
X	return GR_FALSE;
X  }
X  if (y < 0) {
X	clipminx = GR_COORD_MIN;
X	clipmaxx = GR_COORD_MAX;
X	clipminy = GR_COORD_MIN;
X	clipmaxy = -1;
X	clipresult = GR_FALSE;
X	return GR_FALSE;
X  }
X  if (x >= gr_dev.cols) {
X	clipminx = gr_dev.cols;
X	clipmaxx = GR_COORD_MAX;
X	clipminy = GR_COORD_MIN;
X	clipmaxy = GR_COORD_MAX;
X	clipresult = GR_FALSE;
X	return GR_FALSE;
X  }
X  if (y >= gr_dev.rows) {
X	clipminx = GR_COORD_MIN;
X	clipmaxx = GR_COORD_MAX;
X	clipminy = gr_dev.rows;
X	clipmaxy = GR_COORD_MAX;
X	clipresult = GR_FALSE;
X	return GR_FALSE;
X  }
X
X  /* The point is within the screen area. If there are no clip
X   * rectangles, then the point is plottable and the rectangle is the
X   * whole screen.
X   */
X  count = clipcount;
X  if (count <= 0) {
X	clipminx = 0;
X	clipmaxx = gr_dev.cols - 1;
X	clipminy = 0;
X	clipmaxy = gr_dev.rows - 1;
X	clipresult = GR_TRUE;
X	(*gr_dev.checkcursor) (x, y, x, y);
X	return GR_TRUE;
X  }
X
X  /* We need to scan the list of clip rectangles to calculate a new
X   * clip cache rectangle containing this point, and the result. First
X   * see if the point lies within any of the clip rectangles. If so,
X   * then it is plottable and use that clip rectangle as the cache
X   * rectangle.  This is not necessarily the best result, but works ok
X   * and is fast.
X   */
X  for (rp = cliprects; count-- > 0; rp++) {
X	if ((x >= rp->x) && (y >= rp->y) && (x < rp->x + rp->width)
X	    && (y < rp->y + rp->height)) {
X		clipminx = rp->x;
X		clipminy = rp->y;
X		clipmaxx = rp->x + rp->width - 1;
X		clipmaxy = rp->y + rp->height - 1;
X		clipresult = GR_TRUE;
X		(*gr_dev.checkcursor) (x, y, x, y);
X		return GR_TRUE;
X	}
X  }
X
X  /* The point is not plottable. Scan the clip rectangles again to
X   * determine a rectangle containing more non-plottable points.
X   * Simply pick the largest rectangle whose area doesn't contain any
X   * of the same coordinates as appropriate sides of the clip
X   * rectangles.  This is not necessarily the best result, but works ok
X   * and is fast.
X   */
X  clipminx = GR_COORD_MIN;
X  clipminy = GR_COORD_MIN;
X  clipmaxx = GR_COORD_MAX;
X  clipmaxy = GR_COORD_MAX;
X  count = clipcount;
X  for (rp = cliprects; count-- > 0; rp++) {
X	if ((x < rp->x) && (rp->x <= clipmaxx)) clipmaxx = rp->x - 1;
X	temp = rp->x + rp->width - 1;
X	if ((x > temp) && (temp >= clipminx)) clipminx = temp + 1;
X	if ((y < rp->y) && (rp->y <= clipmaxy)) clipmaxy = rp->y - 1;
X	temp = rp->y + rp->height - 1;
X	if ((y > temp) && (temp >= clipminy)) clipminy = temp + 1;
X  }
X  clipresult = GR_FALSE;
X  return GR_FALSE;
X}
X
X
X/*===========================================================================*
X *				cliparea				     *
X *===========================================================================*/
XPUBLIC int cliparea(x1, y1, x2, y2)
XGR_COORD x1;
XGR_COORD y1;
XGR_COORD x2;
XGR_COORD y2;
X{
X/* Check the area determined by the specified pair of points against the
X * list of clip rectangles.  The area will either be totally visible,
X * totally visible, or possibly partially visible.  This routine updates
X * the clip cache rectangle, and returns one of the following values:
X *	GR_CLIP_VISIBLE		The whole rectangle is visible
X *	GR_CLIP_INVISIBLE	The whole rectangle is invisible
X *	GR_CLIP_PARTIAL		The rectangle may be partially visible
X * In the case that the area is totally visible, the cursor is removed
X * if it overlaps the clip area.
X */
X  if ((x1 < clipminx) || (x1 > clipmaxx) ||
X      (y1 < clipminy) || (y1 > clipmaxy))
X	clippoint(x1, y1);
X
X  if ((x2 >= clipminx) && (x2 <= clipmaxx) &&
X      (y2 >= clipminy) && (y2 <= clipmaxy)) {
X	if (!clipresult) return GR_CLIP_INVISIBLE;
X	(*gr_dev.checkcursor) (x1, y1, x2, y2);
X	return GR_CLIP_VISIBLE;
X  }
X  return GR_CLIP_PARTIAL;
X}
X
X/* END CODE */
END_OF_FILE
if test 8352 -ne `wc -c <'mini-x/kernel/graph_clip.c'`; then
    echo shar: \"'mini-x/kernel/graph_clip.c'\" unpacked with wrong size!
fi
# end of 'mini-x/kernel/graph_clip.c'
fi
if test -f 'mini-x/server/graph_serv.h' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'mini-x/server/graph_serv.h'\"
else
echo shar: Extracting \"'mini-x/server/graph_serv.h'\" \(9325 characters\)
sed "s/^X//" >'mini-x/server/graph_serv.h' <<'END_OF_FILE'
X/*
X * Copyright (c) 1991 David I. Bell
X * Permission is granted to use, distribute, or modify this source,
X * provided that this copyright notice remains intact.
X *
X * Private definitions for the graphics server.
X * These definitions are not to be used by the clients.
X * Clients must call the GrXXXX routines instead of these GsXXXX routines.
X */
X
X#ifndef	GRAPH_SERV_H
X#define	GRAPH_SERV_H
X
X#include <graphics.h>
X
X
X/*
X * Drawing types.
X */
Xtypedef	int	GR_DRAW_TYPE;
X
X#define	GR_DRAW_TYPE_NONE	((GR_DRAW_TYPE) 0)	/* none or error */
X#define	GR_DRAW_TYPE_WINDOW	((GR_DRAW_TYPE) 1)	/* windows */
X#define	GR_DRAW_TYPE_PIXMAP	((GR_DRAW_TYPE) 2)	/* pixmaps */
X
X
X/*
X * Maximum number of clients that can be simultaneously run by the server.
X * This is limited to 255 because of resource ids, but the number of
X * file descriptor can also limit it.
X */
X#define	GR_MAX_CLIENTS	1	/* maximum number of clients */
X
X
X/*
X * The following is used to determine whether a client has already been
X * given an event.  For each event, a global value is incremented, and
X * this value is saved in the client structure when it is delivered
X * to the client.
X */
Xtypedef	unsigned long GR_EVENT_NUMBER;
X
X
X/*
X * List of elements for events.
X */
Xtypedef	struct gr_event_list GR_EVENT_LIST;
Xstruct gr_event_list {
X	GR_EVENT_LIST	*next;		/* next element in list */
X	GR_EVENT	event;		/* event */
X};
X
X
X/*
X * Data structure to keep track of state of clients.
X */
Xtypedef	struct {
X	int	infd;			/* handle for input from client */
X	int	outfd;			/* handle for output to client */
X	int	num;			/* client number */
X	GR_ID	allocid;		/* next resource id to allocate */
X	GR_EVENT_NUMBER	eventnumber;	/* event number delivered to client */
X	GR_EVENT_LIST	*eventhead;	/* head of event chain (or NULL) */
X	GR_EVENT_LIST	*eventtail;	/* tail of event chain (or NULL) */
X	GR_EVENT_ERROR	errorevent;	/* waiting error event to deliver */
X} GR_CLIENT;
X
X
X/*
X * Structure to remember clients associated with events.
X */
Xtypedef	struct gr_event_client	GR_EVENT_CLIENT;
Xstruct gr_event_client	{
X	GR_EVENT_CLIENT	*next;		/* next interested client or NULL */
X	GR_EVENT_MASK	eventmask;	/* events client wants to see */
X	GR_CLIENT	*client;	/* client who is interested */
X};
X
X
X/*
X * Structure to remember graphics contexts.
X */
Xtypedef	struct gr_gc	GR_GC;
Xstruct gr_gc {
X	GR_GC_ID	id;		/* graphics context id */
X	GR_MODE		mode;		/* drawing mode */
X	GR_FONT		font;		/* current font number */
X	GR_COLOR	foreground;	/* foreground color */
X	GR_COLOR	background;	/* background color */
X	GR_BOOL		usebackground;	/* actually display the background */
X	GR_BOOL		changed;	/* graphics context has been changed */
X	GR_GC		*next;		/* next graphics context */
X	int		usecount;	/* usecount */
X};
X
X
X/*
X * Structure to remember cursor definitions.
X */
Xtypedef	struct {
X	int		usecount;	/* use counter */
X	GR_SIZE		width;		/* width of cursor */
X	GR_SIZE		height;		/* height of cursor */
X	GR_COORD	hotx;		/* relative x position of hot spot */
X	GR_COORD	hoty;		/* relative y position of hot spot */
X	GR_COLOR	foreground;	/* foreground color */
X	GR_COLOR	background;	/* background color */
X	GR_BITMAP	fgbitmap[GR_MAX_BITMAP_SIZE];	/* foreground bitmap */
X	GR_BITMAP	bgbitmap[GR_MAX_BITMAP_SIZE];	/* background bitmap */
X} GR_CURSOR;
X
X
X/*
X * Window structure
X */
Xtypedef struct gr_window GR_WINDOW;
Xstruct gr_window {
X	GR_WINDOW_ID	id;		/* window id */
X	GR_WINDOW	*parent;	/* parent window */
X	GR_WINDOW	*children;	/* first child window */
X	GR_WINDOW	*siblings;	/* next sibling window */
X	GR_WINDOW	*next;		/* next window in complete list */
X	GR_COORD	x;		/* absolute x position */
X	GR_COORD	y;		/* absolute y position */
X	GR_SIZE		width;		/* width */
X	GR_SIZE		height;		/* height */
X	GR_SIZE		bordersize;	/* size of border */
X	GR_COLOR	bordercolor;	/* color of border */
X	GR_COLOR	background;	/* background color */
X	GR_EVENT_MASK	nopropmask;	/* events not to be propagated */
X	GR_EVENT_CLIENT	*eventclients;	/* clients interested in events */
X	GR_CURSOR	*cursor;	/* cursor for this window */
X	GR_BOOL		mapped;		/* TRUE if explicitly mapped */
X	GR_COUNT	unmapcount;	/* count of reasons not really mapped */
X	GR_BOOL		output;		/* TRUE if window can do output */
X};
X
X
X/*
X * Pixmap structure (not yet implemented).
X * Pixmaps of 2 colors use bitmaps, otherwise they use color values.
X */
Xtypedef struct gr_pixmap	GR_PIXMAP;
Xstruct gr_pixmap {
X	GR_PIXMAP_ID	id;		/* pixmap id */
X	GR_PIXMAP	*next;		/* next pixmap in list */
X	GR_SIZE		width;		/* width of pixmap */
X	GR_SIZE		height;		/* height of pixmap */
X	GR_COLOR	maxcolor;	/* maximum color used in pixmap */
X	GR_COLOR	*colors;	/* table of color values */
X	GR_COLOR8	*color8;	/* OR: table of 8 bit color values */
X	GR_BITMAP	*bitmap;	/* OR: table of bitmap values */
X};
X
X
X/*
X * Macros to obtain the client number from a resource id, and to
X * produce the first resource id to be used for a client number.
X * Client numbers must not be zero.  This allows for 255 clients.
X */
X#define	GR_ID_CLIENT(n)	(((unsigned long) (n)) >> 24)
X#define	GR_ID_BASE(n)	(((unsigned long) (n)) << 24)
X
X
X/*
X * Graphics server routines.
X */
Xextern	int		GdOpenScreen();
Xextern	void		GdCloseScreen();
Xextern	void		GdGetScreenInfo();
Xextern	void		GdGetFontInfo();
Xextern	void		GdTextMode();
Xextern	void		GdFlush();
Xextern	GR_BOOL		GdCheckError();
X
Xextern	int		GsInitialize();
Xextern	void		GsTerminate();
Xextern	GR_ID		GsOpen();
Xextern	void		GsClose();
Xextern	void		GsFlush();
Xextern	void		GsError();
Xextern	GR_WINDOW_ID	GsNewWindow();
Xextern	GR_WINDOW_ID	GsNewInputWindow();
Xextern	void		GsDestroyWindow();
Xextern	void		GsGetWindowInfo();
Xextern	GR_GC_ID	GsNewGC();
Xextern	GR_GC_ID	GsCopyGC();
Xextern	void		GsDestroyGC();
Xextern	void		GsSetGCForeground();
Xextern	void		GsSetGCBackground();
Xextern	void		GsSetGCUseBackground();
Xextern	void		GsSetGCMode();
Xextern	void		GsSetGCFont();
Xextern	void		GsGetGCTextSize();
Xextern	void		GsGetScreenInfo();
Xextern	void		GsClearWindow();
Xextern	void		GsSelectEvents();
Xextern	void		GsPoint();
Xextern	void		GsPoly();
Xextern	void		GsFillPoly();
Xextern	void		GsLine();
Xextern	void		GsEllipse();
Xextern	void		GsFillEllipse();
Xextern	void		GsRect();
Xextern	void		GsFillRect();
Xextern	void		GsBitmap();
Xextern	void		GsArea8();
Xextern	void		GsReadArea8();
Xextern	void		GsText();
Xextern	void		GsSetCursor();
Xextern	void		GsMoveCursor();
Xextern	void		GsDrawBorder();
Xextern	void		GsMapWindow();
Xextern	void		GsUnmapWindow();
Xextern	void		GsRaiseWindow();
Xextern	void		GsLowerWindow();
Xextern	void		GsMoveWindow();
Xextern	void		GsResizeWindow();
Xextern	void		GsSetFocus();
Xextern	void		GsSetBorderColor();
Xextern	void		GsGetNextEvent();
Xextern	void		GsPeekEvent();
Xextern	void		GsCheckEvent();
X
Xextern	int		GsReadMouse();
Xextern	int		GsReadKeyboard();
Xextern	void		GsMoveMouse();
Xextern	int		GsOpenMouse();
Xextern	int		GsOpenKeyboard();
Xextern	void		GsCloseMouse();
Xextern	void		GsCloseKeyboard();
Xextern	void		GsSetAccelMouse();
Xextern	void		GsRestrictMouse();
X
Xextern	void		GsExposeArea();
Xextern	void		GsCheckCursor();
Xextern	void		GsWpSetFocus();
Xextern	void		GsWpClearWindow();
Xextern	void		GsWpUnmapWindow();
Xextern	void		GsWpDestroyWindow();
Xextern	void		GsSetClipWindow();
Xextern	GR_COUNT	GsSplitClipRect();
Xextern	void		GsHandleMouseStatus();
Xextern	void		GsFreePositionEvent();
Xextern	void		GsDeliverButtonEvent();
Xextern	void		GsDeliverMotionEvent();
Xextern	void		GsDeliverKeyboardEvent();
Xextern	void		GsDeliverExposureEvent();
Xextern	void		GsDeliverGeneralEvent();
Xextern	void		GsCheckMouseWindow();
Xextern	void		GsCheckFocusWindow();
Xextern	GR_DRAW_TYPE	GsPrepareDrawing();
Xextern	GR_BOOL		GsCheckOverlap();
Xextern	GR_EVENT	*GsAllocEvent();
Xextern	GR_WINDOW	*GsFindWindow();
Xextern	GR_GC		*GsFindGC();
Xextern	GR_WINDOW	*GsPrepareWindow();
Xextern	GR_WINDOW	*GsFindVisibleWindow();
Xextern	void		GsDrawBorder();
Xextern	void		GsMoveMouse();
X
X
X/*
X * External data definitions.
X */
Xextern	char *		curfunc;		/* current function name */
Xextern	GR_WINDOW_ID	cachewindowid;		/* cached window id */
Xextern	GR_GC_ID	cachegcid;		/* cached graphics context id */
Xextern	GR_GC		*cachegcp;		/* cached graphics context */
Xextern	GR_GC		*listgcp;		/* list of all gc */
Xextern	GR_GC		*curgcp;		/* current graphics context */
Xextern	GR_WINDOW	*cachewp;		/* cached window pointer */
Xextern	GR_WINDOW	*listwp;		/* list of all windows */
Xextern	GR_WINDOW	*rootwp;		/* root window pointer */
Xextern	GR_WINDOW	*clipwp;		/* window clipping is set for */
Xextern	GR_WINDOW	*focuswp;		/* focus window for keyboard */
Xextern	GR_WINDOW	*mousewp;		/* window mouse is currently in */
Xextern	GR_WINDOW	*grabbuttonwp;		/* window grabbed by button */
Xextern	GR_CURSOR	*curcursor;		/* currently enabled cursor */
Xextern	GR_COORD	cursorx;		/* x position of cursor */
Xextern	GR_COORD	cursory;		/* y position of cursor */
Xextern	GR_BUTTON	curbuttons;		/* current state of buttons */
Xextern	GR_CLIENT	*curclient;		/* current client */
Xextern	GR_EVENT_LIST	*eventfree;		/* list of free events */
Xextern	GR_EVENT_NUMBER	eventnumber;		/* current event number */
Xextern	GR_BOOL		inited;			/* TRUE if been initialized */
Xextern	GR_BOOL		focusfixed;		/* TRUE if focus is fixed */
Xextern	GR_SCREEN_INFO	sinfo;			/* screen information */
Xextern	GR_FONT_INFO	curfont;		/* current font information */
Xextern	GR_CLIENT	clients[GR_MAX_CLIENTS];	/* table of clients */
X
X#endif
X
X/* END CODE */
END_OF_FILE
if test 9325 -ne `wc -c <'mini-x/server/graph_serv.h'`; then
    echo shar: \"'mini-x/server/graph_serv.h'\" unpacked with wrong size!
fi
# end of 'mini-x/server/graph_serv.h'
fi
if test -f 'mini-x/server/mousedev.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'mini-x/server/mousedev.c'\"
else
echo shar: Extracting \"'mini-x/server/mousedev.c'\" \(6673 characters\)
sed "s/^X//" >'mini-x/server/mousedev.c' <<'END_OF_FILE'
X/*
X * Copyright (c) 1991 David I. Bell
X * Permission is granted to use, distribute, or modify this source,
X * provided that this copyright notice remains intact.
X *
X * Serial mouse user-level device driver.
X */
X#include <stdio.h>
X#include <errno.h>
X#include <sgtty.h>
X#include <fcntl.h>
X#include <graphics.h>
X
X
X/*
X * Configuration for mouse.
X */
X#ifndef	MOUSE_TYPE
X#define	MOUSE_TYPE	"ms"		/* default mouse type ("ms" or "pc") */
X#endif
X
X#ifndef	MOUSE_PORT
X#define	MOUSE_PORT	"/dev/tty64"	/* default mouse tty port */
X#endif
X
X#define MAX_BYTES	128		/* number of bytes for buffer */
X
X
X/*
X * States for the mouse.
X */ 
X#define	IDLE			0		/* start of byte sequence */
X#define	XSET			1		/* setting x delta */
X#define	YSET			2		/* setting y delta */
X#define	XADD			3		/* adjusting x delta */
X#define	YADD			4		/* adjusting y delta */
X
X
X/*
X * Values in the bytes returned by the mouse for the buttons.
X */
X#define	PC_LEFT_BUTTON		4
X#define PC_RIGHT_BUTTON		1
X#define PC_MIDDLE_BUTTON	2
X
X#define	MS_LEFT_BUTTON		2
X#define MS_RIGHT_BUTTON		1
X
X
X/*
X * Bit fields in the bytes sent by the mouse.
X */
X#define TOP_FIVE_BITS		0xf8
X#define BOTTOM_THREE_BITS	0x07
X#define TOP_BIT			0x80
X#define SIXTH_BIT		0x40
X#define BOTTOM_TWO_BITS		0x03
X#define THIRD_FOURTH_BITS	0x0c
X#define BOTTOM_SIX_BITS  	0x3f
X
X
Xstatic int		(*parse)();	/* parse routine */
Xstatic int		fd;		/* file descriptor for mouse */
Xstatic int		state;		/* IDLE, XSET, ... */
Xstatic GR_BUTTON	buttons;	/* bits 1, 2 and 3 are buttons l, r and m */
Xstatic GR_BUTTON	availbuttons;	/* which buttons are available */
Xstatic GR_COORD		xd;		/* change in x */
Xstatic GR_COORD		yd;		/* change in y */
X
Xstatic int		left;		/* because the button values change */
Xstatic int		middle;		/* between mice, the buttons are */
Xstatic int		right;		/* redefined */
X
Xstatic char		*bp;		/* buffer pointer */
Xstatic int		nbytes;		/* number of bytes left */
Xstatic unsigned char	buffer[MAX_BYTES];	/* data bytes read */
X
X
X/*
X * Parse routines.
X */
Xstatic	int	ParsePC();		/* routine to interpret PC mouse */
Xstatic	int	ParseMS();		/* routine to interpret MS mouse */
X
X
Xextern	char	*getenv();
X
X
X/*
X * Open up the mouse device.
X * The mouse can either be a Microsoft serial mouse or a PC serial mouse.
X * Arguments are the type of mouse, and the tty device name the mouse is on.
X * Type is either "pc" or "ms".  If arguments are NULL, then the environment
X * variables are used for the values.  If there are none, then defaults are
X * used.  Returns zero if successful, or negative if unsuccessful.
X */
Xint
XGdOpenMouse(type, port)
X	char	*type;			/* type of mouse */
X	char	*port;			/* tty port name */
X{
X	struct sgttyb	sgttyb;		/* terminal modes */
X
X	if ((type == NULL) || (*type == '\0')) {
X		type = getenv("MOUSE_TYPE");
X		if (type == NULL)
X			type = MOUSE_TYPE;
X	}
X
X	if ((port == NULL) || (*port == '\0')) {
X		port = getenv("MOUSE_PORT");
X		if (port == NULL)
X			port = MOUSE_PORT;
X	}
X
X	if (strcmp(type, "pc") == 0) {			/* PC */
X		left = PC_LEFT_BUTTON;
X		middle = PC_MIDDLE_BUTTON;
X		right = PC_RIGHT_BUTTON;
X		parse = ParsePC;
X	} else if (strcmp(type, "ms") == 0) {		/* Microsoft */
X		left = MS_LEFT_BUTTON;
X		right = MS_RIGHT_BUTTON;
X		middle = 0;
X		parse = ParseMS;
X	} else
X		return -1;
X
X	fd = open(port, O_NONBLOCK);
X	if (fd < 0)
X		return -1;
X
X	if (ioctl(fd, TIOCGETP, &sgttyb) == -1)
X		return -1;
X
X	sgttyb.sg_flags |= RAW;
X	sgttyb.sg_flags &= ~(EVENP | ODDP | ECHO | XTABS | CRMOD);
X
X	if (ioctl(fd, TIOCSETP, &sgttyb) == -1)
X		return -1;
X
X	if (ioctl(fd, TIOCFLUSH, 0) < 0)
X		return -1;
X
X	availbuttons = left | middle | right;
X	state = IDLE;
X	nbytes = 0;
X	buttons = 0;
X	xd = 0;
X	yd = 0;
X
X	return 0;
X}
X
X
X/*
X * Return which buttons are available.
X */
Xvoid
XGdGetButtonInfo(buttons)
X	GR_BUTTON	*buttons;		/* implemented buttons */
X{
X	*buttons = availbuttons;
X}
X
X
X/*
X * Close the mouse device.
X */
Xvoid
XGdCloseMouse()
X{
X	if (fd > 0)
X		close(fd);
X	fd = 0;
X}
X
X
X/*
X * Attempt to read bytes from the mouse and interpret them.
X * Returns -1 on error, 0 if either no bytes were read or not enough
X * was read for a complete state, or 1 if the new state was read.
X * When a new state is read, the current buttons and x and y deltas
X * are returned.  This routine does not block.
X */
Xint
XGdReadMouse(xdptr, ydptr, bptr)
X	GR_COORD	*xdptr;			/* returned X delta */
X	GR_COORD	*ydptr;			/* returned Y delta */
X	GR_BUTTON	*bptr;			/* returned buttons */
X{
X	*xdptr = 0;
X	*ydptr = 0;
X	*xdptr = buttons;
X
X	/*
X	 * If there are no more bytes left, then read some more,
X	 * waiting for them to arrive.  On a signal or a non-blocking
X	 * error, return saying there is no new state available yet.
X	 */
X	if (nbytes <= 0) {
X		bp = buffer;
X		nbytes = read(fd, bp, MAX_BYTES);
X		if (nbytes < 0) {
X			if ((errno == EINTR) || (errno == EAGAIN))
X				return 0;
X			return -1;
X		}
X	}
X
X	/*
X	 * Loop over all the bytes read in the buffer, parsing them.
X	 * When a complete state has been read, return the results,
X	 * leaving further bytes in the buffer for later calls.
X	 */
X	while (nbytes-- > 0) {
X		if ((*parse)((int) *bp++)) {
X			*xdptr = xd;
X			*ydptr = yd;
X			*bptr = buttons;
X			return 1;
X		}
X	}
X
X	return 0;
X}
X
X
X/*
X * Input routine for PC mouse.
X * Returns nonzero when a new mouse state has been completed.
X */
Xstatic int
XParsePC(byte)
X	int	byte;			/* current byte read */
X{
X	int	sign;			/* sign of movement */
X
X	switch (state) {
X		case IDLE:
X			if ((byte & TOP_FIVE_BITS) == TOP_BIT) {
X				buttons = ~byte & BOTTOM_THREE_BITS;
X				state = XSET;
X			}
X			break;
X
X		case XSET:
X			sign = 1;
X			if (byte > 127) {
X				byte = 256 - byte;
X				sign = -1;
X			}
X			xd = byte * sign;
X			state = YSET;
X			break;
X
X		case YSET:
X			sign = 1;
X			if (byte > 127) {
X				byte = 256 - byte;
X				sign = -1;
X			}
X			yd = -byte * sign;
X			state = XADD;
X			break;
X
X		case XADD:
X			sign = 1;
X			if (byte > 127) {
X				byte = 256 - byte;
X				sign = -1;
X			}
X			xd += byte;
X			state = YADD;
X			break;
X
X		case YADD:
X			sign = 1;
X			if (byte > 127) {
X				byte = 256 - byte;
X				sign = -1;
X			}
X			yd -= byte;
X			state = IDLE;
X			return 1;
X	}
X	return 0;
X}
X
X
X/*
X * Input routine for Microsoft mouse.
X * Returns nonzero when a new mouse state has been completed.
X */
Xstatic int
XParseMS(byte)
X	int	byte;			/* current byte from buffer */
X{
X	switch (state) {
X		case IDLE:
X			if (byte & SIXTH_BIT) {
X				buttons = (byte >> 4) & BOTTOM_TWO_BITS;
X				yd = ((byte & THIRD_FOURTH_BITS) << 4);
X				xd = ((byte & BOTTOM_TWO_BITS) << 6);
X				state = XADD;
X			}
X			break;
X
X		case XADD:
X			xd |= (byte & BOTTOM_SIX_BITS);
X			state = YADD;
X			break;
X
X		case YADD:
X			yd |= (byte & BOTTOM_SIX_BITS);
X			state = IDLE;
X			if (xd > 127)
X				xd -= 256;
X			if (yd > 127)
X				yd -= 256;
X			return 1;
X	}
X	return 0;
X}
X
X/* END CODE */
END_OF_FILE
if test 6673 -ne `wc -c <'mini-x/server/mousedev.c'`; then
    echo shar: \"'mini-x/server/mousedev.c'\" unpacked with wrong size!
fi
# end of 'mini-x/server/mousedev.c'
fi
echo shar: End of archive 2 \(of 9\).
cp /dev/null ark2isdone
MISSING=""
for I in 1 2 3 4 5 6 7 8 9 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked all 9 archives.
    rm -f ark[1-9]isdone ark[1-9][0-9]isdone
else
    echo You still need to unpack the following archives:
    echo "        " ${MISSING}
fi
##  End of shell archive.
exit 0

dbell@pdact.pd.necisa.oz.au (David I. Bell) (04/22/91)

#! /bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of archive 3 (of 9)."
# Contents:  mini-x/include/graphics.h mini-x/kernel/graph_ega.c
#   mini-x/kernel/graph_gen.c
# Wrapped by dbell@elm on Mon Apr 22 11:21:44 1991
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'mini-x/include/graphics.h' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'mini-x/include/graphics.h'\"
else
echo shar: Extracting \"'mini-x/include/graphics.h'\" \(14242 characters\)
sed "s/^X//" >'mini-x/include/graphics.h' <<'END_OF_FILE'
X/* Copyright (c) 1991 David I. Bell
X * Permission is granted to use, distribute, or modify this source,
X * provided that this copyright notice remains intact.
X *
X * mini-X graphics - public definitions
X */
X
X#ifndef	GRAPHICS_H
X#define	GRAPHICS_H
X
X/* Basic typedefs. */
Xtypedef short GR_COORD;		/* coordinate value */
Xtypedef short GR_SIZE;		/* size value */
Xtypedef short GR_COUNT;		/* number of items */
Xtypedef unsigned short GR_COLOR;/* full color value */
Xtypedef unsigned char GR_COLOR8;/* eight bit color value */
Xtypedef unsigned short GR_BITMAP;	/* bitmap unit */
Xtypedef unsigned short GR_MODE;	/* drawing mode */
Xtypedef unsigned char GR_CHAR;	/* text character */
Xtypedef unsigned char GR_CHAR_WIDTH;	/* width of character */
Xtypedef unsigned long GR_ID;	/* resource ids */
Xtypedef GR_ID GR_DRAW_ID;	/* drawable id */
Xtypedef GR_DRAW_ID GR_WINDOW_ID;/* window id */
Xtypedef GR_DRAW_ID GR_PIXMAP_ID;/* pixmap id (not yet used) */
Xtypedef GR_ID GR_GC_ID;		/* graphics context id */
Xtypedef unsigned short GR_FONT;	/* font number */
Xtypedef unsigned short GR_BOOL;	/* boolean value */
Xtypedef unsigned short GR_FUNC;	/* function codes */
Xtypedef int GR_ERROR;		/* error value */
Xtypedef short GR_EVENT_TYPE;	/* event types */
Xtypedef unsigned short GR_BUTTON;	/* button flags */
Xtypedef unsigned short GR_MODIFIER;	/* modifier flags (CTRL, SHIFT, etc) */
Xtypedef unsigned long GR_EVENT_MASK;	/* event masks */
Xtypedef char GR_FUNC_NAME[20];	/* function name */
Xtypedef void (*GR_ERROR_FUNC) ();	/* error function */
X
X
X/* Limits */
X#define	GR_COORD_MIN	((GR_COORD) -32768)	/* minimum coordinate value */
X#define	GR_COORD_MAX	((GR_COORD) 32767)	/* maximum coordinate value */
X#define	GR_MAX_CLIPRECTS ((GR_COUNT) 200)	/* maximum clip rectangles */
X#define	GR_MAX_CURSOR_SIZE ((GR_SIZE) 16)	/* maximum cursor size */
X
X
X/* Size of bitmaps. */
X#define	GR_BITMAP_SIZE(width, height)	((height) * \
X  (((width) + sizeof(GR_BITMAP) * 8 - 1) / (sizeof(GR_BITMAP) * 8)))
X
X#define	GR_MAX_BITMAP_SIZE \
X  GR_BITMAP_SIZE(GR_MAX_CURSOR_SIZE, GR_MAX_CURSOR_SIZE)
X
X
X/* The root window id. */
X#define	GR_ROOT_WINDOW_ID	((GR_WINDOW_ID) 1)
X
X
X/* Drawing mode (used with GrSetGCMode). */
X#define	GR_MODE_SET	((GR_MODE) 0)	/* draw pixels as given (default) */
X#define	GR_MODE_XOR	((GR_MODE) 1)	/* draw pixels using XOR */
X#define	GR_MODE_OR	((GR_MODE) 2)	/* draw pixels using OR */
X#define	GR_MODE_AND	((GR_MODE) 3)	/* draw pixels using AND */
X#define	GR_MAX_MODE	((GR_MODE) 3)	/* maximum legal mode */
X
X
X/* Booleans. */
X#define	GR_FALSE	((GR_BOOL) 0)
X#define	GR_TRUE		((GR_BOOL) 1)
X
X
X/* Definition of a point. */
Xtypedef struct {
X  GR_COORD x;			/* x coordinate */
X  GR_COORD y;			/* y coordinate */
X} GR_POINT;
X
X
X/* Definition of a line. */
Xtypedef struct {
X  GR_COORD x1;			/* x coordinate of first point */
X  GR_COORD y1;			/* y coordinate of first point */
X  GR_COORD x2;			/* x coordinate of second point */
X  GR_COORD y2;			/* y coordinate of second point */
X} GR_LINE;
X
X
X/* Definition of an ellipse. */
Xtypedef struct {
X  GR_COORD x;			/* x coordinate of center */
X  GR_COORD y;			/* y coordinate of center */
X  GR_SIZE rx;			/* radius in x direction */
X  GR_SIZE ry;			/* radius in y direction */
X} GR_ELLIPSE;
X
X
X/* Definition of a rectangle. */
Xtypedef struct {
X  GR_COORD x;			/* x coordinate of top left corner */
X  GR_COORD y;			/* y coordinate of top left corner */
X  GR_SIZE width;		/* width of rectangle */
X  GR_SIZE height;		/* height of rectangle */
X} GR_RECT;
X
X
X/* Screen properties returned by the GrGetScreenInfo call.
X * This describes the size of the screen and relative dots/cm of the pixels.
X * The actual dots/mm vary depending on the actual monitor in use, but the
X * relative sizes are still useful to compensate for non-square pixels for
X * drawing perfect circles.  (I am avoiding the use of floating point.)
X */
Xtypedef struct {
X  GR_SIZE rows;			/* number of rows on screen */
X  GR_SIZE cols;			/* number of columns on screen */
X  GR_SIZE xdpcm;		/* dots/centimeter in x direction */
X  GR_SIZE ydpcm;		/* dots/centimeter in y direction */
X  GR_COLOR maxcolor;		/* maximum legal color value */
X  GR_COLOR black;		/* the color black */
X  GR_COLOR white;		/* the color white */
X  GR_BUTTON buttons;		/* buttons which are implemented */
X  GR_MODIFIER modifiers;	/* modifiers which are implemented */
X  GR_COUNT fonts;		/* number of built-in fonts */
X} GR_SCREEN_INFO;
X
X
X/* Window properties returned by the GrGetWindowInfo call. */
Xtypedef struct {
X  GR_WINDOW_ID wid;		/* window id (or 0 if no such window) */
X  GR_WINDOW_ID parent;		/* parent window id */
X  GR_WINDOW_ID child;		/* first child window id (or 0) */
X  GR_WINDOW_ID sibling;		/* next sibling window id (or 0) */
X  GR_BOOL inputonly;		/* TRUE if window is input only */
X  GR_BOOL mapped;		/* TRUE if window is mapped */
X  GR_COUNT unmapcount;		/* reasons why window is unmapped */
X  GR_COORD x;			/* absolute x position of window */
X  GR_COORD y;			/* absolute y position of window */
X  GR_SIZE width;		/* width of window */
X  GR_SIZE height;		/* height of window */
X  GR_SIZE bordersize;		/* size of border */
X  GR_COLOR bordercolor;		/* color of border */
X  GR_COLOR background;		/* background color */
X  GR_EVENT_MASK eventmask;	/* current event mask for this client */
X} GR_WINDOW_INFO;
X
X
X/* Graphics context properties returned by the GrGetGCInfo call. */
Xtypedef struct {
X  GR_GC_ID gcid;		/* GC id (or 0 if no such GC) */
X  GR_MODE mode;			/* drawing mode */
X  GR_FONT font;			/* font number */
X  GR_COLOR foreground;		/* foreground color */
X  GR_COLOR background;		/* background color */
X  GR_BOOL usebackground;	/* use background in bitmaps */
X} GR_GC_INFO;
X
X
X/* Font information. */
Xtypedef struct {
X  GR_FONT font;			/* font number */
X  GR_SIZE height;		/* height of font */
X  GR_SIZE maxwidth;		/* maximum width of any char */
X  GR_SIZE baseline;		/* baseline of font */
X  GR_BOOL fixed;		/* TRUE if font is fixed width */
X  GR_CHAR_WIDTH widths[256];	/* table of character widths */
X} GR_FONT_INFO;
X
X
X/* Error codes */
X#define	GR_ERROR_BAD_WINDOW_ID		((GR_ERROR) 1)
X#define	GR_ERROR_BAD_GC_ID		((GR_ERROR) 2)
X#define	GR_ERROR_BAD_CURSOR_SIZE	((GR_ERROR) 3)
X#define	GR_ERROR_MALLOC_FAILED		((GR_ERROR) 4)
X#define	GR_ERROR_BAD_WINDOW_SIZE	((GR_ERROR) 5)
X#define	GR_ERROR_KEYBOARD_ERROR		((GR_ERROR) 6)
X#define	GR_ERROR_MOUSE_ERROR		((GR_ERROR) 7)
X#define	GR_ERROR_INPUT_ONLY_WINDOW	((GR_ERROR) 8)
X#define	GR_ERROR_ILLEGAL_ON_ROOT_WINDOW	((GR_ERROR) 9)
X#define	GR_ERROR_TOO_MUCH_CLIPPING	((GR_ERROR) 10)
X#define	GR_ERROR_SCREEN_ERROR		((GR_ERROR) 11)
X#define	GR_ERROR_UNMAPPED_FOCUS_WINDOW	((GR_ERROR) 12)
X#define	GR_ERROR_BAD_DRAWING_MODE	((GR_ERROR) 13)
X
X
X/* Event types.
X * Mouse motion is generated for every motion of the mouse, and is used to
X * track the entire history of the mouse (many events and lots of overhead).
X * Mouse position ignores the history of the motion, and only reports the
X * latest position of the mouse by only queuing the latest such event for
X * any single client (good for rubber-banding).
X */
X#define	GR_EVENT_TYPE_ERROR		((GR_EVENT_TYPE) -1)
X#define	GR_EVENT_TYPE_NONE		((GR_EVENT_TYPE) 0)
X#define	GR_EVENT_TYPE_EXPOSURE		((GR_EVENT_TYPE) 1)
X#define	GR_EVENT_TYPE_BUTTON_DOWN	((GR_EVENT_TYPE) 2)
X#define	GR_EVENT_TYPE_BUTTON_UP		((GR_EVENT_TYPE) 3)
X#define	GR_EVENT_TYPE_MOUSE_ENTER	((GR_EVENT_TYPE) 4)
X#define	GR_EVENT_TYPE_MOUSE_EXIT	((GR_EVENT_TYPE) 5)
X#define	GR_EVENT_TYPE_MOUSE_MOTION	((GR_EVENT_TYPE) 6)
X#define	GR_EVENT_TYPE_MOUSE_POSITION	((GR_EVENT_TYPE) 7)
X#define	GR_EVENT_TYPE_KEY_DOWN		((GR_EVENT_TYPE) 8)
X#define	GR_EVENT_TYPE_KEY_UP		((GR_EVENT_TYPE) 9)
X#define	GR_EVENT_TYPE_FOCUS_IN		((GR_EVENT_TYPE) 10)
X#define	GR_EVENT_TYPE_FOCUS_OUT		((GR_EVENT_TYPE) 11)
X
X
X/* Event masks */
X#define	GR_EVENTMASK(n)			(((GR_EVENT_MASK) 1) << (n))
X
X#define	GR_EVENT_MASK_NONE		GR_EVENTMASK(GR_EVENT_TYPE_NONE)
X#define	GR_EVENT_MASK_ERROR		GR_EVENTMASK(GR_EVENT_TYPE_ERROR)
X#define	GR_EVENT_MASK_EXPOSURE		GR_EVENTMASK(GR_EVENT_TYPE_EXPOSURE)
X#define	GR_EVENT_MASK_BUTTON_DOWN	GR_EVENTMASK(GR_EVENT_TYPE_BUTTON_DOWN)
X#define	GR_EVENT_MASK_BUTTON_UP		GR_EVENTMASK(GR_EVENT_TYPE_BUTTON_UP)
X#define	GR_EVENT_MASK_MOUSE_ENTER	GR_EVENTMASK(GR_EVENT_TYPE_MOUSE_ENTER)
X#define	GR_EVENT_MASK_MOUSE_EXIT	GR_EVENTMASK(GR_EVENT_TYPE_MOUSE_EXIT)
X#define	GR_EVENT_MASK_MOUSE_MOTION	GR_EVENTMASK(GR_EVENT_TYPE_MOUSE_MOTION)
X#define	GR_EVENT_MASK_MOUSE_POSITION	GR_EVENTMASK(GR_EVENT_TYPE_MOUSE_POSITION)
X#define	GR_EVENT_MASK_KEY_DOWN		GR_EVENTMASK(GR_EVENT_TYPE_KEY_DOWN)
X#define	GR_EVENT_MASK_KEY_UP		GR_EVENTMASK(GR_EVENT_TYPE_KEY_UP)
X#define	GR_EVENT_MASK_FOCUS_IN		GR_EVENTMASK(GR_EVENT_TYPE_FOCUS_IN)
X#define	GR_EVENT_MASK_FOCUS_OUT		GR_EVENTMASK(GR_EVENT_TYPE_FOCUS_OUT)
X#define	GR_EVENT_MASK_ALL		((GR_EVENT_MASK) -1L)
X
X
X/* Modifiers generated by special keyboard shift-like keys.
X * The state of these keys can be read as up or down, and don't
X * generate any characters by themselves.
X */
X#define	GR_MODIFIER_SHIFT	((GR_MODIFIER) 0x01)	/* shift */
X#define	GR_MODIFIER_CTRL	((GR_MODIFIER) 0x02)	/* control */
X#define	GR_MODIFIER_META	((GR_MODIFIER) 0x03)	/* meta or alt */
X#define	GR_MODIFIER_ANY		((GR_MODIFIER) 0x07)	/* any modifier */
X
X
X/* Button flags. */
X#define	GR_BUTTON_1	((GR_BUTTON) 0x01)	/* button 1 */
X#define	GR_BUTTON_2	((GR_BUTTON) 0x02)	/* button 2 */
X#define	GR_BUTTON_3	((GR_BUTTON) 0x04)	/* button 3 */
X#define	GR_BUTTON_ANY	((GR_BUTTON) 0x07)	/* any button */
X
X
X/* Event for errors detected by the server.
X * These events are not delivered to GrGetNextEvent, but instead call
X * the user supplied error handling function.  Only the first one of
X * these errors at a time is saved for delivery to the client since
X * there is not much to be done about errors anyway except complain
X * and exit.
X */
Xtypedef struct {
X  GR_EVENT_TYPE type;		/* event type */
X  GR_FUNC_NAME name;		/* function name which failed */
X  GR_ERROR code;		/* error code */
X  GR_ID id;			/* resource id (maybe useless) */
X} GR_EVENT_ERROR;
X
X
X/* Event for a mouse button pressed down or released. */
Xtypedef struct {
X  GR_EVENT_TYPE type;		/* event type */
X  GR_WINDOW_ID wid;		/* window id event delivered to */
X  GR_WINDOW_ID subwid;		/* sub-window id (pointer was in) */
X  GR_COORD rootx;		/* root window x coordinate */
X  GR_COORD rooty;		/* root window y coordinate */
X  GR_COORD x;			/* window x coordinate of mouse */
X  GR_COORD y;			/* window y coordinate of mouse */
X  GR_BUTTON buttons;		/* current state of all buttons */
X  GR_BUTTON changebuttons;	/* buttons which went down or up */
X  GR_MODIFIER modifiers;	/* modifiers (SHIFT, CTRL, etc) */
X} GR_EVENT_BUTTON;
X
X
X/* Event for a keystroke typed for the window with has focus. */
Xtypedef struct {
X  GR_EVENT_TYPE type;		/* event type */
X  GR_WINDOW_ID wid;		/* window id event delived to */
X  GR_WINDOW_ID subwid;		/* sub-window id (pointer was in) */
X  GR_COORD rootx;		/* root window x coordinate */
X  GR_COORD rooty;		/* root window y coordinate */
X  GR_COORD x;			/* window x coordinate of mouse */
X  GR_COORD y;			/* window y coordinate of mouse */
X  GR_BUTTON buttons;		/* current state of buttons */
X  GR_MODIFIER modifiers;	/* modifiers (SHIFT, CTRL, etc) */
X  GR_CHAR ch;			/* keystroke or function key */
X} GR_EVENT_KEYSTROKE;
X
X
X/* Event for exposure for a region of a window. */
Xtypedef struct {
X  GR_EVENT_TYPE type;		/* event type */
X  GR_WINDOW_ID wid;		/* window id */
X  GR_COORD x;			/* window x coordinate of exposure */
X  GR_COORD y;			/* window y coordinate of exposure */
X  GR_SIZE width;		/* width of exposure */
X  GR_SIZE height;		/* height of exposure */
X} GR_EVENT_EXPOSURE;
X
X
X/* General events for focus in or focus out for a window, or mouse enter
X * or mouse exit from a window, or window unmapping or mapping, etc.
X */
Xtypedef struct {
X  GR_EVENT_TYPE type;		/* event type */
X  GR_WINDOW_ID wid;		/* window id */
X} GR_EVENT_GENERAL;
X
X
X/* Events for mouse motion or mouse position. */
Xtypedef struct {
X  GR_EVENT_TYPE type;		/* event type */
X  GR_WINDOW_ID wid;		/* window id event delivered to */
X  GR_WINDOW_ID subwid;		/* sub-window id (pointer was in) */
X  GR_COORD rootx;		/* root window x coordinate */
X  GR_COORD rooty;		/* root window y coordinate */
X  GR_COORD x;			/* window x coordinate of mouse */
X  GR_COORD y;			/* window y coordinate of mouse */
X  GR_BUTTON buttons;		/* current state of buttons */
X  GR_MODIFIER modifiers;	/* modifiers (ALT, SHIFT, etc) */
X} GR_EVENT_MOUSE;
X
X
X/* Union of all possible event structures.
X * This is the structure returned by the GrGetNextEvent and similar routines.
X */
Xtypedef union {
X  GR_EVENT_TYPE type;		/* event type */
X  GR_EVENT_ERROR error;		/* error event */
X  GR_EVENT_GENERAL general;	/* general window events */
X  GR_EVENT_BUTTON button;	/* button events */
X  GR_EVENT_KEYSTROKE keystroke;	/* keystroke events */
X  GR_EVENT_EXPOSURE exposure;	/* exposure events */
X  GR_EVENT_MOUSE mouse;		/* mouse motion events */
X} GR_EVENT;
X
X
X/* Public graphics routines. */
Xextern int GrOpen();
Xextern void GrClose();
Xextern void GrGetScreenInfo();
Xextern GR_ERROR_FUNC GrSetErrorHandler();
Xextern GR_WINDOW_ID GrNewWindow();
Xextern GR_WINDOW_ID GrNewInputWindow();
Xextern void GrDestroyWindow();
Xextern GR_GC_ID GrNewGC();
Xextern void GrGetGCInfo();
Xextern void GrDestroyGC();
Xextern void GrMapWindow();
Xextern void GrUnmapWindow();
Xextern void GrRaiseWindow();
Xextern void GrLowerWindow();
Xextern void GrMoveWindow();
Xextern void GrResizeWindow();
Xextern void GrGetWindowInfo();
Xextern void GrGetFontInfo();
Xextern void GrSetFocus();
Xextern void GrSetBorderColor();
Xextern void GrClearWindow();
Xextern void GrSelectEvents();
Xextern void GrGetNextEvent();
Xextern void GrCheckNextEvent();
Xextern void GrPeekEvent();
Xextern void GrFlush();
Xextern void GrLine();
Xextern void GrPoint();
Xextern void GrRect();
Xextern void GrFillRect();
Xextern void GrPoly();
Xextern void GrFillPoly();
Xextern void GrEllipse();
Xextern void GrFillEllipse();
Xextern void GrSetGCForeground();
Xextern void GrSetGCBackground();
Xextern void GrSetGCUseBackground();
Xextern void GrSetGCMode();
Xextern void GrSetGCFont();
Xextern void GrGetGCTextSize();
Xextern void GrReadArea8();
Xextern void GrArea8();
Xextern void GrBitmap();
Xextern void GrText();
Xextern void GrSetCursor();
Xextern void GrMoveCursor();
X
X#endif
X
X/* END CODE */
END_OF_FILE
if test 14242 -ne `wc -c <'mini-x/include/graphics.h'`; then
    echo shar: \"'mini-x/include/graphics.h'\" unpacked with wrong size!
fi
# end of 'mini-x/include/graphics.h'
fi
if test -f 'mini-x/kernel/graph_ega.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'mini-x/kernel/graph_ega.c'\"
else
echo shar: Extracting \"'mini-x/kernel/graph_ega.c'\" \(14152 characters\)
sed "s/^X//" >'mini-x/kernel/graph_ega.c' <<'END_OF_FILE'
X/* Copyright (c) 1991 David I. Bell
X * Permission is granted to use, distribute, or modify this source,
X * provided that this copyright notice remains intact.
X *
X * Low level graphics mode for ega.
X * Since these are "device level" routines, there is no need to check
X * clipping since the higher level routines should have already done this.
X * However, checking for values outside the screen memory is reasonable
X * for safety.
X */
X
X#include "kernel.h"
X#include "protect.h"
X#include "graph_dev.h"
X
X
X#define	COLS	640		/* columns */
X#define	ROWS	350		/* rows */
X#define	COLORS	16		/* number of colors */
X#define	BLACK	0		/* black */
X#define	WHITE	15		/* white */
X
X#define	DONE	0
X#define	IN	1
X#define	OUT	2
X
X#define	ROM_SCAN_LINES	14	/* number of scan lines in fonts in ROM */
X#define	RAM_SCAN_LINES	32	/* number of scan lines in fonts in RAM */
X#define	FONT_CHARS	256	/* number of characters in font tables */
X#define	CHAR_WIDTH	8	/* number of pixels for character width */
X#define	EGA_BASE	0xa0000	/* location of enhanced display memory */
X
X
X
X#define	PALREG	0x3c0
X#define	SEQREG	0x3c4
X#define	SEQVAL	0x3c5
X#define	GRREG	0x3ce
X#define	GRVAL	0x3cf
X#define	ATTRREG	0x3da
X#define	CRTCREG	0x3d4
X#define	CRTCVAL	0x3d5
X
X#define	GENREG1	0x3c2
X#define	GENREG2	0x3cc
X#define	GENREG3	0x3ca
X
X#define	DATA_ROTATE	3	/* register number for data rotate */
X
X
XFORWARD int ega_init();
XFORWARD void ega_term();
XFORWARD void ega_setmode();
XFORWARD void ega_drawrow();
XFORWARD void ega_drawcol();
XFORWARD void ega_drawtext();
XFORWARD void ega_sizetext();
XFORWARD void ega_getscreeninfo();
XFORWARD void ega_getfontinfo();
X
Xextern void ega_drawpoint();
Xextern void ega_drawline();
Xextern void ega_setgraphics();
Xextern void ega_getcharbits();
Xextern GR_COLOR ega_readpoint();
X
X
XGR_DEV gr_dev = {
X  ega_init, ega_term, ega_setmode, ega_drawpoint, ega_drawline,
X  ega_drawrow, ega_drawcol, gen_fillrect, gen_drawellipse,
X  gen_fillellipse, ega_drawtext, ega_sizetext, gen_drawarea8,
X  gen_drawbitmap, ega_readpoint, gen_setcursor, gen_movecursor,
X  gen_checkcursor, gen_fixcursor, gen_copyarea, ega_getcharbits,
X  ega_getscreeninfo, ega_getfontinfo, ROWS, COLS, COLORS, BLACK, WHITE
X};
X
Xtypedef struct {
X  int action;
X  int port1;
X  int data1;
X  int port2;
X  int data2;
X} REGIO;
X
X
XPRIVATE REGIO graphics_on[] = {
X  /* Reset attr F/F */
X  IN, ATTRREG, 0, 0, 0,
X
X  /* Disable palette */
X  OUT, PALREG, 0, 0, 0,
X
X  /* Reset sequencer regs */
X  OUT, SEQREG, 0, SEQVAL, 0,
X  OUT, SEQREG, 1, SEQVAL, 1,
X  OUT, SEQREG, 2, SEQVAL, 0x0f,
X  OUT, SEQREG, 3, SEQVAL, 0,
X  OUT, SEQREG, 4, SEQVAL, 6,
X
X  /* Misc out reg */
X  OUT, GENREG1, 0xa7, 0, 0,
X
X  /* Sequencer enable */
X  OUT, SEQREG, 0, SEQVAL, 0x03,
X
X  /* Unprotect crtc regs 0-7 */
X  OUT, CRTCREG, 0x11, CRTCVAL, 0,
X
X  /* Crtc */
X  OUT, CRTCREG, 0, CRTCVAL, 0x5b,
X  OUT, CRTCREG, 1, CRTCVAL, 0x4f,
X  OUT, CRTCREG, 2, CRTCVAL, 0x53,
X  OUT, CRTCREG, 3, CRTCVAL, 0x37,
X  OUT, CRTCREG, 4, CRTCVAL, 0x52,
X  OUT, CRTCREG, 5, CRTCVAL, 0x00,
X  OUT, CRTCREG, 6, CRTCVAL, 0x6c,
X  OUT, CRTCREG, 7, CRTCVAL, 0x1f,
X  OUT, CRTCREG, 8, CRTCVAL, 0x00,
X  OUT, CRTCREG, 9, CRTCVAL, 0x00,
X  OUT, CRTCREG, 10, CRTCVAL, 0x00,
X  OUT, CRTCREG, 11, CRTCVAL, 0x00,
X  OUT, CRTCREG, 12, CRTCVAL, 0x00,
X  OUT, CRTCREG, 13, CRTCVAL, 0x00,
X  OUT, CRTCREG, 14, CRTCVAL, 0x00,
X  OUT, CRTCREG, 15, CRTCVAL, 0x00,
X  OUT, CRTCREG, 16, CRTCVAL, 0x5e,
X  OUT, CRTCREG, 17, CRTCVAL, 0x2b,
X  OUT, CRTCREG, 18, CRTCVAL, 0x5d,
X  OUT, CRTCREG, 19, CRTCVAL, 0x28,
X  OUT, CRTCREG, 20, CRTCVAL, 0x0f,
X  OUT, CRTCREG, 21, CRTCVAL, 0x5f,
X  OUT, CRTCREG, 22, CRTCVAL, 0x0a,
X  OUT, CRTCREG, 23, CRTCVAL, 0xe3,
X  OUT, CRTCREG, 24, CRTCVAL, 0xff,
X
X  /* Graphics controller */
X  OUT, GENREG2, 0x00, 0, 0,
X  OUT, GENREG3, 0x01, 0, 0,
X  OUT, GRREG, 0, GRVAL, 0x00,
X  OUT, GRREG, 1, GRVAL, 0x00,
X  OUT, GRREG, 2, GRVAL, 0x00,
X  OUT, GRREG, 3, GRVAL, 0x00,
X  OUT, GRREG, 4, GRVAL, 0x00,
X  OUT, GRREG, 5, GRVAL, 0x00,
X  OUT, GRREG, 6, GRVAL, 0x05,
X  OUT, GRREG, 7, GRVAL, 0x0f,
X  OUT, GRREG, 8, GRVAL, 0xff,
X
X  /* Reset attribute flip/flop */
X  IN, ATTRREG, 0, 0, 0,
X
X  /* Palette */
X  OUT, PALREG, 0, PALREG, 0x00,
X  OUT, PALREG, 1, PALREG, 0x01,
X  OUT, PALREG, 2, PALREG, 0x02,
X  OUT, PALREG, 3, PALREG, 0x03,
X  OUT, PALREG, 4, PALREG, 0x04,
X  OUT, PALREG, 5, PALREG, 0x05,
X  OUT, PALREG, 6, PALREG, 0x06,
X  OUT, PALREG, 7, PALREG, 0x07,
X  OUT, PALREG, 8, PALREG, 0x38,
X  OUT, PALREG, 9, PALREG, 0x39,
X  OUT, PALREG, 10, PALREG, 0x3a,
X  OUT, PALREG, 11, PALREG, 0x3b,
X  OUT, PALREG, 12, PALREG, 0x3c,
X  OUT, PALREG, 13, PALREG, 0x3d,
X  OUT, PALREG, 14, PALREG, 0x3e,
X  OUT, PALREG, 15, PALREG, 0x3f,
X  OUT, PALREG, 16, PALREG, 0x01,
X  OUT, PALREG, 17, PALREG, 0x00,
X  OUT, PALREG, 18, PALREG, 0x0f,
X  OUT, PALREG, 19, PALREG, 0x00,
X
X  /* Enable palette */
X  OUT, PALREG, 0x20, 0, 0,
X
X  /* End of table */
X  DONE, 0, 0, 0, 0
X};
X
X
XPRIVATE REGIO graph_off[] = {
X  /* Reset attr F/F */
X  IN, ATTRREG, 0, 0, 0,
X
X  /* Disable palette */
X  OUT, PALREG, 0, 0, 0,
X
X  /* Reset sequencer regs */
X  OUT, SEQREG, 0, SEQVAL, 1,
X  OUT, SEQREG, 1, SEQVAL, 1,
X  OUT, SEQREG, 2, SEQVAL, 3,
X  OUT, SEQREG, 3, SEQVAL, 0,
X  OUT, SEQREG, 4, SEQVAL, 3,
X
X  /* Misc out reg */
X  OUT, GENREG1, 0xa7, 0, 0,
X
X  /* Sequencer enable */
X  OUT, SEQREG, 0, SEQVAL, 3,
X
X  /* Crtc */
X  OUT, CRTCREG, 0, CRTCVAL, 0x5b,	/* horiz total */
X  OUT, CRTCREG, 1, CRTCVAL, 0x4f,	/* horiz end */
X  OUT, CRTCREG, 2, CRTCVAL, 0x53,	/* horiz blank */
X  OUT, CRTCREG, 3, CRTCVAL, 0x37,	/* end blank */
X  OUT, CRTCREG, 4, CRTCVAL, 0x51,	/* horiz retrace */
X  OUT, CRTCREG, 5, CRTCVAL, 0x5b,	/* end retrace */
X  OUT, CRTCREG, 6, CRTCVAL, 0x6c,	/* vert total */
X  OUT, CRTCREG, 7, CRTCVAL, 0x1f,	/* overflows */
X  OUT, CRTCREG, 8, CRTCVAL, 0x00,	/* row scan */
X  OUT, CRTCREG, 9, CRTCVAL, 0x0d,	/* max scan line */
X  OUT, CRTCREG, 10, CRTCVAL, 0x00,	/* cursor start */
X  OUT, CRTCREG, 11, CRTCVAL, 0x0f,	/* cursor end */
X  OUT, CRTCREG, 12, CRTCVAL, 0x00,	/* start high addr */
X  OUT, CRTCREG, 13, CRTCVAL, 0x00,	/* low addr */
X  OUT, CRTCREG, 14, CRTCVAL, 0x00,	/* cursor high */
X  OUT, CRTCREG, 15, CRTCVAL, 0x00,	/* cursor low */
X  OUT, CRTCREG, 16, CRTCVAL, 0x5e,	/* vert retrace */
X  OUT, CRTCREG, 17, CRTCVAL, 0x2b,	/* retrace end */
X  OUT, CRTCREG, 18, CRTCVAL, 0x5d,	/* vert end */
X  OUT, CRTCREG, 19, CRTCVAL, 0x28,	/* offset */
X  OUT, CRTCREG, 20, CRTCVAL, 0x0f,	/* underline */
X  OUT, CRTCREG, 21, CRTCVAL, 0x5e,	/* vert blank */
X  OUT, CRTCREG, 22, CRTCVAL, 0x0a,	/* end blank */
X  OUT, CRTCREG, 23, CRTCVAL, 0xa3,	/* crt mode */
X  OUT, CRTCREG, 24, CRTCVAL, 0xff,	/* line compare */
X
X  /* Graphics controller */
X  OUT, GENREG2, 0x00, 0, 0,
X  OUT, GENREG3, 0x01, 0, 0,
X  OUT, GRREG, 0, GRVAL, 0x00,
X  OUT, GRREG, 1, GRVAL, 0x00,
X  OUT, GRREG, 2, GRVAL, 0x00,
X  OUT, GRREG, 3, GRVAL, 0x00,
X  OUT, GRREG, 4, GRVAL, 0x00,
X  OUT, GRREG, 5, GRVAL, 0x10,
X  OUT, GRREG, 6, GRVAL, 0x0e,
X  OUT, GRREG, 7, GRVAL, 0x00,
X  OUT, GRREG, 8, GRVAL, 0xff,
X
X  /* Reset attribute flip/flop */
X  IN, ATTRREG, 0, 0, 0,
X
X  /* Palette */
X  OUT, PALREG, 0, PALREG, 0x00,
X  OUT, PALREG, 1, PALREG, 0x01,
X  OUT, PALREG, 2, PALREG, 0x02,
X  OUT, PALREG, 3, PALREG, 0x03,
X  OUT, PALREG, 4, PALREG, 0x04,
X  OUT, PALREG, 5, PALREG, 0x05,
X  OUT, PALREG, 6, PALREG, 0x14,
X  OUT, PALREG, 7, PALREG, 0x07,
X  OUT, PALREG, 8, PALREG, 0x38,
X  OUT, PALREG, 9, PALREG, 0x39,
X  OUT, PALREG, 10, PALREG, 0x3a,
X  OUT, PALREG, 11, PALREG, 0x3b,
X  OUT, PALREG, 12, PALREG, 0x3c,
X  OUT, PALREG, 13, PALREG, 0x3d,
X  OUT, PALREG, 14, PALREG, 0x3e,
X  OUT, PALREG, 15, PALREG, 0x3f,
X  OUT, PALREG, 16, PALREG, 0x08,
X  OUT, PALREG, 17, PALREG, 0x00,
X  OUT, PALREG, 18, PALREG, 0x0f,
X  OUT, PALREG, 19, PALREG, 0x00,
X
X  /* Enable palette */
X  OUT, PALREG, 0x20, 0, 0,
X
X  /* End of table */
X  DONE, 0, 0, 0, 0
X};
X
X
X/* Values for the data rotate register to implement drawing modes. */
XPRIVATE unsigned char mode_table[GR_MAX_MODE + 1] = {
X  0x00, 0x18, 0x10, 0x08
X};
X
X
X/*===========================================================================*
X *				writeregs				     *
X *===========================================================================*/
XPRIVATE void writeregs(rp)
Xregister REGIO *rp;
X{
X/* Set the graphics registers as indicated by the given table */
X  for (; rp->action != DONE; rp++) {
X	switch (rp->action) {
X	    case IN:	in_byte(rp->port1);	break;
X	    case OUT:
X		out_byte(rp->port1, rp->data1);
X		if (rp->port2) out_byte(rp->port2, rp->data2);
X		break;
X	}
X  }
X}
X
X
X/*===========================================================================*
X *				out_word				     *
X *===========================================================================*/
XPRIVATE void out_word(p, d)
Xunsigned int p;
Xunsigned int d;
X{
X/* Output a word to an I/O port. */
X  out_byte(p, d & 0xff);
X  out_byte(p + 1, (d >> 8) & 0xff);
X}
X
X
X/*===========================================================================*
X *				ega_init				     *
X *===========================================================================*/
XPRIVATE int ega_init(rows, cols, colors)
XGR_SIZE rows;
XGR_SIZE cols;
Xlong colors;
X{
X/* Setup for drawing to the ega.
X * Returns nonzero if the parameters are illegal.
X */
X  if ((rows && (rows != ROWS)) || (cols && (cols != COLS))
X      || (colors && (colors != COLORS)))
X	return -1;
X  writeregs(graphics_on);
X  for (rows = 0; rows < ROWS; rows++) ega_drawrow(0, COLS - 1, rows, BLACK);
X  return 0;
X}
X
X
X/*===========================================================================*
X *				ega_term				     *
X *===========================================================================*/
XPRIVATE void ega_term()
X{
X/* Terminate graphics mode for the EGA.
X * This resets back to normal text mode.
X */
X  long srcoffset;
X  long destoffset;
X  int data;
X  int ch;
X  int row;
X
X  ega_setmode(GR_MODE_SET);
X  for (row = 0; row < ROWS; row++) ega_drawrow(0, COLS - 1, row, BLACK);
X
X  /* Copy character table from ROM back into bit plane 2 before turning
X   * off graphics.
X   */
X  out_word(SEQREG, 0x0100);	/* syn reset */
X  out_word(SEQREG, 0x0402);	/* cpu writes only to map 2 */
X  out_word(SEQREG, 0x0704);	/* sequential addressing */
X  out_word(SEQREG, 0x0300);	/* clear synchronous reset */
X
X  out_word(GRREG, 0x0204);	/* select map 2 for CPU reads */
X  out_word(GRREG, 0x0005);	/* disable odd-even addressing */
X
X  srcoffset = rom_char_addr;
X  destoffset = EGA_BASE;
X  for (ch = 0; ch < FONT_CHARS; ch++) {
X	for (row = 0; row < ROM_SCAN_LINES; row++) {
X		data = get_byte(FLAT_DS_SELECTOR, srcoffset++);
X		put_byte(FLAT_DS_SELECTOR, destoffset++, data);
X	}
X	destoffset += (RAM_SCAN_LINES - ROM_SCAN_LINES);
X  }
X
X  /* Finally set the registers back for text mode. */
X  writeregs(graph_off);
X}
X
X
X/*===========================================================================*
X *				ega_setmode				     *
X *===========================================================================*/
XPRIVATE void ega_setmode(mode)
XGR_MODE mode;			/* drawing mode */
X{
X/* Set the drawing mode.
X * This is either SET, OR, AND, or XOR.
X */
X  if (mode > GR_MAX_MODE) return;
X  out_byte(GRREG, DATA_ROTATE);
X  out_byte(GRVAL, mode_table[mode]);
X}
X
X
X/*===========================================================================*
X *				ega_drawrow				     *
X *===========================================================================*/
XPRIVATE void ega_drawrow(x1, x2, y, color)
XGR_COORD x1;
XGR_COORD x2;
XGR_COORD y;
XGR_COLOR color;
X{
X  ega_drawline(x1, y, x2, y, color);
X}
X
X
X/*===========================================================================*
X *				ega_drawcol				     *
X *===========================================================================*/
XPRIVATE void ega_drawcol(x, y1, y2, color)
XGR_COORD x;
XGR_COORD y1;
XGR_COORD y2;
XGR_COLOR color;
X{
X  ega_drawline(x, y1, x, y2, color);
X}
X
X
X/*===========================================================================*
X *				ega_drawtext				     *
X *===========================================================================*/
XPRIVATE void ega_drawtext(x, y, str, cc, fg)
XGR_COORD x, y;			/* bottom left location */
XGR_CHAR *str;			/* character string */
XGR_SIZE cc;			/* length of string */
XGR_COLOR fg;			/* foreground color */
X{
X  GR_SIZE width;		/* width of character */
X  GR_SIZE height;		/* height of character */
X  GR_BITMAP bitmap[ROM_SCAN_LINES];	/* bitmap for character */
X
X  y -= (ROM_SCAN_LINES - 1);
X  while (cc-- > 0) {
X	ega_getcharbits(*str++, bitmap, &width, &height);
X	gen_drawbitmap(x, y, width, height, bitmap, fg);
X	x += width;
X  }
X}
X
X
X/*===========================================================================*
X *				ega_sizetext				     *
X *===========================================================================*/
XPRIVATE void ega_sizetext(buf, cc, retx, rety)
XGR_CHAR *buf;
XGR_SIZE cc;
XGR_SIZE *retx;
XGR_SIZE *rety;
X{
X  *retx = CHAR_WIDTH * cc;
X  *rety = ROM_SCAN_LINES;
X}
X
X
X/*===========================================================================*
X *				ega_getscreeninfo			     *
X *===========================================================================*/
XPRIVATE void ega_getscreeninfo(ip)
XGR_SCREEN_INFO *ip;		/* where to return result */
X{
X/* Return the screen configuration information for the ega. */
X  ip->rows = gr_dev.rows;
X  ip->cols = gr_dev.cols;
X  ip->xdpcm = 27;		/* assumes screen width of 24 cm */
X  ip->ydpcm = 19;		/* assumes screen height of 18 cm */
X  ip->maxcolor = gr_dev.colors - 1;
X  ip->black = gr_dev.black;
X  ip->white = gr_dev.white;
X  ip->fonts = 1;		/* only 1 builtin font */
X}
X
X
X/*===========================================================================*
X *				ega_getfontinfo				     *
X *===========================================================================*/
XPRIVATE void ega_getfontinfo(font, fip)
XGR_FONT font;			/* font number */
XGR_FONT_INFO *fip;		/* where to return result */
X{
X/* Return the font information about a font in the ega.
X * Currently we only support one font.
X */
X  int i;
X
X  fip->font = font;
X  if (font != 0) {
X	fip->height = 1;
X	fip->maxwidth = 1;
X	fip->baseline = 0;
X	fip->fixed = GR_TRUE;
X	for (i = 0; i < 256; i++) fip->widths[i] = 1;
X  }
X  fip->height = ROM_SCAN_LINES;
X  fip->maxwidth = CHAR_WIDTH;
X  fip->baseline = 3;
X  fip->fixed = GR_TRUE;
X  for (i = 0; i < 256; i++) fip->widths[i] = CHAR_WIDTH;
X}
X
X/* END CODE */
END_OF_FILE
if test 14152 -ne `wc -c <'mini-x/kernel/graph_ega.c'`; then
    echo shar: \"'mini-x/kernel/graph_ega.c'\" unpacked with wrong size!
fi
# end of 'mini-x/kernel/graph_ega.c'
fi
if test -f 'mini-x/kernel/graph_gen.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'mini-x/kernel/graph_gen.c'\"
else
echo shar: Extracting \"'mini-x/kernel/graph_gen.c'\" \(11017 characters\)
sed "s/^X//" >'mini-x/kernel/graph_gen.c' <<'END_OF_FILE'
X/* Copyright (c) 1991 David I. Bell
X * Permission is granted to use, distribute, or modify this source,
X * provided that this copyright notice remains intact.
X *
X * Generic device dependent routines.
X * All of these routines use other device routines to perform their work,
X * eventually getting to real device routines.  In the worst case, the
X * only real device routine implemented is drawpoint.  In the best case,
X * none of these generic routines are needed since the device can do
X * them all efficiently.  Since these are "device" level routines, no
X * clip rectangle checks are necessary since they should have already been
X * done by the calling routines, but clip checks against the device
X * area is reasonable.
X */
X
X#include "kernel.h"
X#include "graph_dev.h"
X
XFORWARD void draw4points();
X
X
X/*===========================================================================*
X *				gen_drawline				     *
X *===========================================================================*/
XPUBLIC void gen_drawline(x1, y1, x2, y2, color)
XGR_COORD x1;
XGR_COORD y1;
XGR_COORD x2;
XGR_COORD y2;
XGR_COLOR color;
X{
X/* Generic draw line routine. */
X  GR_COORD temp;
X  int xdelta;
X  int ydelta;
X  int xinc;
X  int yinc;
X  int rem;
X
X  if (y1 == y2) {
X	(*gr_dev.drawrow) (x1, x2, y1, color);
X	return;
X  }
X  if (x1 == x2) {
X	(*gr_dev.drawcol) (x1, y1, y2, color);
X	return;
X  }
X  xdelta = x2 - x1;
X  ydelta = y2 - y1;
X  if (xdelta < 0) xdelta = -xdelta;
X  if (ydelta < 0) ydelta = -ydelta;
X  xinc = (x2 > x1) ? 1 : -1;
X  yinc = (y2 > y1) ? 1 : -1;
X  (*gr_dev.drawpoint) (x1, y1, color);
X  if (xdelta >= ydelta) {
X	rem = xdelta / 2;
X	do {
X		x1 += xinc;
X		rem += ydelta;
X		if (rem >= xdelta) {
X			rem -= xdelta;
X			y1 += yinc;
X		}
X		(*gr_dev.drawpoint) (x1, y1, color);
X	} while (x1 != x2);
X  } else {
X	rem = ydelta / 2;
X	do {
X		y1 += yinc;
X		rem += xdelta;
X		if (rem >= ydelta) {
X			rem -= ydelta;
X			x1 += xinc;
X		}
X		(*gr_dev.drawpoint) (x1, y1, color);
X	} while (y1 != y2);
X  }
X}
X
X
X/*===========================================================================*
X *				gen_drawrow				     *
X *===========================================================================*/
XPUBLIC void gen_drawrow(x1, x2, y, color)
XGR_COORD x1;
XGR_COORD x2;
XGR_COORD y;
XGR_COLOR color;
X{
X/* Generic draw row routine. */
X  while (x1 <= x2) (*gr_dev.drawpoint) (x1++, y, color);
X}
X
X
X/*===========================================================================*
X *				gen_drawcol				     *
X *===========================================================================*/
XPUBLIC void gen_drawcol(x, y1, y2, color)
XGR_COORD x;
XGR_COORD y1;
XGR_COORD y2;
XGR_COLOR color;
X{
X/* Generic draw column routine. */
X  while (y1 <= y2) (*gr_dev.drawpoint) (x, y1++, color);
X}
X
X
X/*===========================================================================*
X *				gen_fillrect				     *
X *===========================================================================*/
XPUBLIC void gen_fillrect(x1, y1, x2, y2, color)
XGR_COORD x1;
XGR_COORD y1;
XGR_COORD x2;
XGR_COORD y2;
XGR_COLOR color;
X{
X/* Generic fill rectangle routine. */
X  while (y1 <= y2) (*gr_dev.drawrow) (x1, x2, y1++, color);
X}
X
X
X/*===========================================================================*
X *				gen_drawellipse				     *
X *===========================================================================*/
XPUBLIC void gen_drawellipse(x, y, rx, ry, color)
XGR_COORD x, y;			/* coordinates of center of ellipse */
XGR_SIZE rx;			/* radius along x axis */
XGR_SIZE ry;			/* radius along y axis */
X{
X/* Generic ellipse drawing routine. */
X  int xp, yp;			/* current point (based on center) */
X  long Asquared;		/* square of x semi axis */
X  long TwoAsquared;
X  long Bsquared;		/* square of y semi axis */
X  long TwoBsquared;
X  long d;
X  long dx, dy;
X
X  if ((rx < 0) || (ry < 0)) return;
X
X  xp = 0;
X  yp = ry;
X  Asquared = rx * rx;
X  TwoAsquared = 2 * Asquared;
X  Bsquared = ry * ry;
X  TwoBsquared = 2 * Bsquared;
X  d = Bsquared - Asquared * ry + (Asquared >> 2);
X  dx = 0;
X  dy = TwoAsquared * ry;
X
X  while (dx < dy) {
X	draw4points(x, y, xp, yp, color);
X	if (d > 0) {
X		yp--;
X		dy -= TwoAsquared;
X		d -= dy;
X	}
X	xp++;
X	dx += TwoBsquared;
X	d += (Bsquared + dx);
X  }
X  d += ((3L * (Asquared - Bsquared) / 2L - (dx + dy)) >> 1);
X  while (yp >= 0) {
X	draw4points(x, y, xp, yp, color);
X	if (d < 0) {
X		xp++;
X		dx += TwoBsquared;
X		d += dx;
X	}
X	yp--;
X	dy -= TwoAsquared;
X	d += (Asquared - dy);
X  }
X}
X
X
X/*===========================================================================*
X *				draw4points				     *
X *===========================================================================*/
XPRIVATE void draw4points(x, y, px, py, color)
XGR_COORD x, y;			/* center of the points */
XGR_SIZE px, py;			/* point to plot (based on center) */
XGR_COLOR color;
X{
X/* Set four points symmetrically situated around a point. */
X  (*gr_dev.drawpoint) (x + px, y + py, color);
X  (*gr_dev.drawpoint) (x - px, y + py, color);
X  (*gr_dev.drawpoint) (x + px, y - py, color);
X  (*gr_dev.drawpoint) (x - px, y - py, color);
X}
X
X
X/*===========================================================================*
X *				gen_fillellipse				     *
X *===========================================================================*/
XPUBLIC void gen_fillellipse(x, y, rx, ry, color)
XGR_COORD x, y;			/* coordinates of center of ellipse */
XGR_SIZE rx;			/* radius along x axis */
XGR_SIZE ry;			/* radius along y axis */
XGR_COLOR color;
X{
X/* Generic fill ellipse routine. */
X  int xp, yp;			/* current point (based on center) */
X  long Asquared;		/* square of x semi axis */
X  long TwoAsquared;
X  long Bsquared;		/* square of y semi axis */
X  long TwoBsquared;
X  long d;
X  long dx, dy;
X
X  if ((rx < 0) || (ry < 0)) return;
X
X  xp = 0;
X  yp = ry;
X  Asquared = rx * rx;
X  TwoAsquared = 2 * Asquared;
X  Bsquared = ry * ry;
X  TwoBsquared = 2 * Bsquared;
X  d = Bsquared - Asquared * ry + (Asquared >> 2);
X  dx = 0;
X  dy = TwoAsquared * ry;
X
X  while (dx < dy) {
X	(*gr_dev.drawrow) (x - xp, x + xp, y - yp, color);
X	(*gr_dev.drawrow) (x - xp, x + xp, y + yp, color);
X	if (d > 0) {
X		yp--;
X		dy -= TwoAsquared;
X		d -= dy;
X	}
X	xp++;
X	dx += TwoBsquared;
X	d += (Bsquared + dx);
X  }
X  d += ((3L * (Asquared - Bsquared) / 2L - (dx + dy)) >> 1);
X  while (yp >= 0) {
X	(*gr_dev.drawrow) (x - xp, x + xp, y - yp, color);
X	(*gr_dev.drawrow) (x - xp, x + xp, y + yp, color);
X	if (d < 0) {
X		xp++;
X		dx += TwoBsquared;
X		d += dx;
X	}
X	yp--;
X	dy -= TwoAsquared;
X	d += (Asquared - dy);
X  }
X}
X
X
X/*===========================================================================*
X *				gen_drawarea8				     *
X *===========================================================================*/
XPUBLIC void gen_drawarea8(x, y, width, height, table)
XGR_COORD x;			/* leftmost column of area */
XGR_COORD y;			/* topmost row of area */
XGR_SIZE width;			/* width of area */
XGR_SIZE height;			/* height of area */
XGR_COLOR8 *table;		/* table of 8 bit color values */
X{
X/* Generic drawing of rectangular area with 8 bit color values.
X * The rectangle is composed of 8 bit color values so that each color
X * only uses one character.  If a color matches the background color,
X * that that pixel is only drawn if the gr_usebg flag is set.
X */
X  long cellstodo;		/* remaining number of cells */
X  long count;			/* number of cells of same color */
X  long cc;			/* current cell count */
X  long rows;			/* number of complete rows */
X  GR_COORD minx;		/* minimum x value */
X  GR_COORD maxx;		/* maximum x value */
X  GR_COLOR color;		/* color of these pixels */
X  GR_BOOL dodraw;		/* TRUE if draw these points */
X
X  minx = x;
X  maxx = x + width - 1;
X  cellstodo = width * height;
X  while (cellstodo > 0) {
X	/* See how many of the adjacent remaining points have the
X	 * same color as the next point.
X	 */
X	color = *table++;
X	dodraw = (gr_usebg || (color != gr_background));
X	count = 1;
X	cellstodo--;
X	while ((cellstodo > 0) && (color == *table)) {
X		table++;
X		count++;
X		cellstodo--;
X	}
X
X	/* If there is only one point with this color, then draw it
X	 * by itself.
X	 */
X	if (count == 1) {
X		if (dodraw) (*gr_dev.drawpoint) (x, y, color);
X		if (++x > maxx) {
X			x = minx;
X			y++;
X		}
X		continue;
X	}
X
X	/* There are multiple points with the same color. If we are
X	 * not at the start of a row of the rectangle, then draw this
X	 * first row specially.
X	 */
X	if (x != minx) {
X		cc = count;
X		if (x + cc - 1 > maxx) cc = maxx - x + 1;
X		if (dodraw) (*gr_dev.drawrow) (x, x + cc - 1, y, color);
X		count -= cc;
X		x += cc;
X		if (x > maxx) {
X			x = minx;
X			y++;
X		}
X	}
X
X	/* Now the x value is at the beginning of a row if there are
X	 * any points left to be drawn.  Draw all the complete rows
X	 * with one call.
X	 */
X	rows = count / width;
X	if (rows > 0) {
X		if (dodraw)
X			(*gr_dev.fillrect) (x, y, maxx, y + rows - 1, color);
X		count %= width;
X		y += rows;
X	}
X
X	/* If there is a final partial row of pixels left to be
X	 * drawn, then do that.
X	 */
X	if (count > 0) {
X		if (dodraw) (*gr_dev.drawrow) (x, x + count - 1, y, color);
X		x += count;
X	}
X  }
X}
X
X
X/*===========================================================================*
X *				gen_drawbitmap				     *
X *===========================================================================*/
XPUBLIC void gen_drawbitmap(x, y, width, height, table, fgcolor)
XGR_COORD x;			/* leftmost column of area */
XGR_COORD y;			/* topmost row of area */
XGR_SIZE width;			/* width of area */
XGR_SIZE height;			/* height of area */
XGR_BITMAP *table;		/* table of bitmaps */
XGR_COLOR fgcolor;		/* foreground color */
X{
X/* Draw a rectanglular array of pixels in the foreground color as
X * determined by the specified bitmap.  This does not affect the
X * background pixels.
X */
X  GR_COORD minx;
X  GR_COORD maxx;
X  GR_BITMAP bitvalue;		/* bitmap word value */
X  int bitcount;			/* number of bits left in bitmap word */
X
X  minx = x;
X  maxx = x + width - 1;
X  bitcount = 0;
X  while (height > 0) {
X	if (bitcount <= 0) {
X		bitcount = GR_BITMAPBITS;
X		bitvalue = *table++;
X	}
X	if (GR_TESTBIT(bitvalue)) (*gr_dev.drawpoint) (x, y, fgcolor);
X	bitvalue = GR_SHIFTBIT(bitvalue);
X	bitcount--;
X	if (x++ == maxx) {
X		x = minx;
X		y++;
X		height--;
X		bitcount = 0;
X	}
X  }
X}
X
X
X/*===========================================================================*
X *				gen_copyarea				     *
X *===========================================================================*/
XPUBLIC void gen_copyarea(srcx, srcy, width, height, destx, desty)
XGR_COORD srcx;			/* leftmost column of area to copy */
XGR_COORD srcy;			/* topmost row of area to copy */
XGR_SIZE width;			/* width of area to copy */
XGR_SIZE height;			/* height of area to copy */
XGR_COORD destx;			/* leftmost column of destination */
XGR_COORD desty;			/* topmost row of destination */
X{
X/* Generic copy of an area from one rectangle to another.
X * This bypasses clipping.
X */
X  GR_COORD row;
X  GR_COORD col;
X  GR_COLOR color;
X
X  for (row = 0; row < height; row++) {
X	for (col = 0; col < width; col++) {
X		color = (*gr_dev.readpoint) (srcx + col, srcy + row);
X		(*gr_dev.drawpoint) (destx + col, desty + row, color);
X	}
X  }
X}
X
X/* END CODE */
END_OF_FILE
if test 11017 -ne `wc -c <'mini-x/kernel/graph_gen.c'`; then
    echo shar: \"'mini-x/kernel/graph_gen.c'\" unpacked with wrong size!
fi
# end of 'mini-x/kernel/graph_gen.c'
fi
echo shar: End of archive 3 \(of 9\).
cp /dev/null ark3isdone
MISSING=""
for I in 1 2 3 4 5 6 7 8 9 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked all 9 archives.
    rm -f ark[1-9]isdone ark[1-9][0-9]isdone
else
    echo You still need to unpack the following archives:
    echo "        " ${MISSING}
fi
##  End of shell archive.
exit 0

dbell@pdact.pd.necisa.oz.au (David I. Bell) (04/22/91)

#! /bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of archive 4 (of 9)."
# Contents:  mini-x/kernel/ega.x mini-x/server/client.c
#   mini-x/server/serv_event.c
# Wrapped by dbell@elm on Mon Apr 22 11:21:46 1991
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'mini-x/kernel/ega.x' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'mini-x/kernel/ega.x'\"
else
echo shar: Extracting \"'mini-x/kernel/ega.x'\" \(18881 characters\)
sed "s/^X//" >'mini-x/kernel/ega.x' <<'END_OF_FILE'
X/* Copyright (c) 1991 David I. Bell
X * Permission is granted to use, distribute, or modify this source,
X * provided that this copyright notice remains intact.
X *
X * The algorithms for some of these routines are taken from the book:
X * Programmer's Guide to PC and PS/2 Video Systems by Richard Wilton.
X *
X * Routines to draw pixels and lines for EGA/VGA resolutions.
X * The drawing mode in the data/rotate register is not changed in this
X * module, and must be changed as necessary by the callers.
X */
X
X#include "protect.h"
X
X
X#define	PIXCOLS		640		/* number of pixels across */
X#define	PIXROWS		350		/* number of pixels down */
X#define	PIXBYTES	80		/* number of bytes across */
X#define	CHARROWS	14		/* number of pixels in char heights */
X#define	CHARCOLS	8		/* number of pixels in char widths */
X#define	BITMAPSIZE	2		/* number of bytes in GR_BITMAP */
X
X#define	BUFFERADDR	0xa000		/* EGA buffer segment address */
X#define	MEMADDR		0xa0000		/* physical memory address of buffer */
X#define	PORTADDR	0x03ce		/* graphics controller port address */
X#define	BITMASKREG	0x08		/* bit mask register */
X#define	INITBITMASK	0xff08		/* set full bit mask output value */
X#define	WRITEMODE2	0x0205		/* select write mode 2 output value */
X#define	INITWRITEMODE	0x0005		/* restore default write mode 0 */
X#define	PIXSHIFT	3		/* convert pixels to byte offset */
X
X
X	.globl	_ega_getcharbits	/* read bitmap for a character */
X	.globl	_ega_drawline		/* draw a line */
X	.globl	_ega_drawpoint		/* set an individual pixel */
X	.globl	_ega_drawtext		/* draw text string */
X	.globl	_ega_readpoint		/* read an individual pixel */
X
X	.bss
X	.extern	_rom_char_addr		/* ROM char bitmap physical address */
X	.text
X
X
X/*
X * Routine to return the bitmap for a character from the ROM.
X * Called from C:
X *	ega_getcharbits(char, retbitmap, retwidth, retheight);
X *		GR_CHAR		char;
X *		GR_BITMAP	*retbitmap;
X *		GR_SIZE		*retwidth;
X *		GR_SIZE		*retheight;
X * The retbitmap is a pointer to an array of GR_BITMAP values (shorts),
X * of length CHARROWS.  Retwidth and retheight are the returned
X * width and height of the character.
X */
X
X#define	char		8		/* character to get bitmap of */
X#define	retaddr		12		/* returned address of bitmap */
X#define	retwidth	16		/* returned width of character */
X#define	retheight	20		/* returned height of character */
X
X
X_ega_getcharbits:
X	push	ebp		/* setup stack frame and preserve registers */
X	mov	ebp, esp
X	push	es
X
X	xor	eax, eax	/* get character code */
X	movb	al, char(ebp)
X	mov	ecx, #CHARROWS	/* get number of bytes of data for chars */
X	mul	ecx		/* make offset into ROM bitmap table */
X	add	eax, _rom_char_addr	/* physical addr of bitmap for char */
X	mov	bx, #FLAT_DS_SELECTOR	/* flat address space selector */
X	mov	es, bx
X	mov	ebx, retaddr(ebp)	/* address for returned bits */
X	xor	edx, edx	/* clear low order part of bitmap values */
X
Xgetcharloop:
X	seg	es		/* get next byte of bitmap */
X	movb	dh, (eax)
X	mov	(ebx), dx	/* store in caller's buffer */
X	inc	eax		/* advance ROM address */
X	add	ebx, #BITMAPSIZE	/* and buffer address */
X	loop	getcharloop	/* loop until did all rows of char */
X
X	mov	ax, #CHARCOLS	/* return width of character */
X	mov	ebx, retwidth(ebp)
X	mov	(ebx), ax
X	mov	ax, #CHARROWS	/* return height of character */
X	mov	ebx, retheight(ebp)
X	mov	(ebx), ax
X
X	pop	es		/* restore registers and return */
X	pop	ebp
X	ret
X
X
X/*
X * Routine to draw an arbitrary line.
X * Called from C:
X *	_ega_drawline(x1, y1, x2, y2, color);
X */
X
X/* argument offsets, starting with 8 bytes (eip + ebp) */
X#define	x1	8		/* first X coordinate */
X#define	y1	12		/* first Y coordinate */
X#define	x2	16		/* second X coordinate */
X#define	y2	20		/* second Y coordinate */
X#define	color	24		/* pixel value */
X
X/* local variable offsets from ebp */
X#define	rowincr	-4		/* byte increment between rows */
X#define	incr1	-8		/* first increment */
X#define	incr2	-12		/* second increment */
X#define	routine	-16		/* routine to jump to */
X
X
X_ega_drawline:
X	push	ebp		/* setup stack frame and preserve registers */
X	mov	ebp, esp
X
X	/*
X	 * Make sure that the line is totally within the screen area.
X	 * If not, we are allowed to completely ignore the line.
X	 */
X	mov	eax, x1(ebp)	/* EAX := x1 */
X	cmp	eax, #PIXCOLS	/* if ((x1<0) || (x1>=PIXCOLS)) return */
X	jae	badline
X	mov	eax, x2(ebp)	/* EAX := x2 */
X	cmp	eax, #PIXCOLS	/* if ((x2<0) || (x2>=PIXCOLS)) return */
X	jae	badline
X	mov	eax, y1(ebp)	/* EAX := y1 */
X	cmp	eax, #PIXROWS	/* if ((y1<0) || (y1>=PIXROWS)) return */
X	jae	badline
X	mov	eax, y2(ebp)	/* EAX := y2 */
X	cmp	eax, #PIXROWS	/* if ((y2<0) || (y2>=PIXROWS)) return */
X	jae	badline
X	j	lineok
X
Xbadline:
X	pop	ebp
X	ret
X
X	/*
X	 * Here when we know the line is totally drawable.
X	 */
Xlineok:
X	sub	esp, #16
X	push	esi
X	push	edi
X	push	es
X
X	/* configure the graphics controller */
X
X	mov	dx, #PORTADDR	/* DX := Graphics Controller port address */
X	movb	ah, color(ebp)	/* pixel value */
X	xorb	al, al		/* Set/Reset register number (0) */
X	out	dx, ax
X
X	mov	ax, #0x0f01	/* AH := bit plane mask for Enable Set/Reset */
X	out	dx, ax		/* AL := Enable Set/Reset register number */
X
X	/* check for vertical line */
X
X	mov	esi, #PIXBYTES	/* increment for video buffer */
X	mov	ecx, x2(ebp)
X	sub	ecx, x1(ebp)	/* CX := x2 - x1 */
X	jnz	L117		/* jump if vertical line */
X	jmp	VertLine
XL117:
X	/* force x1 < x2 */
X
X	jns	L01		/* jump if x2 > x1 */
X
X	neg	ecx		/* CX := x1 - x2 */
X
X	mov	ebx, x2(ebp)	/* exchange x1 and x2 */
X	xchg	ebx, x1(ebp)
X	mov	x2(ebp), ebx
X
X	mov	ebx, y2(ebp)	/* exchange y1 and y2 */
X	xchg	ebx, y1(ebp)
X	mov	y2(ebp), ebx
X
X	/* calculate dy = ABS(y2 - y1) */
X
XL01:	mov	ebx, y2(ebp)
X	sub	ebx, y1(ebp)	/* BX := y2 - y1 */
X	jnz	L115		/* jump if horizontal line */
X	jmp	HorizLine
XL115:
X	jns	L03		/* jump if slope is positive */
X
X	neg	ebx		/* BX := y1 - y2 */
X	neg	esi		/* negate increment for buffer interleave */
X
X	/* select appropriate routine for slope of line */
X
XL03:	mov	rowincr(ebp), esi	/* save vertical increment */
X	mov	routine(ebp), #LowSlope
X	cmp	ebx, ecx
X	jle	L04		/* jump if dy <= dx (slope <= 1) */
X	mov	routine(ebp), #HighSlope
X	xchg	ebx, ecx	/* exchange dy and dx */
X
X	/* calculate initial decision variable and increments */
X
XL04:	shl	ebx, #1		/* BX := 2 * dy */
X	mov	incr1(ebp), ebx	/* incr1 := 2 * dy */
X	sub	ebx, ecx
X	mov	esi, ebx	/* SI := d = 2 * dy - dx */
X	sub	ebx, ecx
X	mov	incr2(ebp), ebx	/* incr2 := 2 * (dy - dx) */
X
X	/* calculate first pixel address */
X
X	push	ecx		/* preserve register */
X	mov	eax, y1(ebp)	/* AX := y */
X	mov	ebx, x1(ebp)	/* BX := x */
X	call	PixelAddr	/* AH := bit mask */
X				/* ES:BX -> buffer */
X				/* CL := bits to shift left */
X
X	mov	edi, ebx	/* es:di -> buffer */
X	shlb	ah, cl		/* AH := bit mask in proper position */
X	movb	bl, ah		/* AH,BL := bit mask */
X	movb	al, #BITMASKREG	/* AL := Bit Mask Register number */
X
X	pop	ecx		/* restore register */
X	inc	ecx		/* CX := number of pixels to draw */
X
X	jmp	#routine(ebp)	/* jump to appropriate routine for slope */
X
X
X/*
X * Routine for vertical lines
X */
XVertLine:
X	mov	eax, y1(ebp)	/* AX := y1 */
X	mov	ebx, y2(ebp)	/* BX := y2 */
X	mov	ecx, ebx
X	sub	ecx, eax	/* CX := dy */
X	jge	L31		/* jump if dy >= 0 */
X
X	neg	ecx		/* force dy >= 0 */
X	mov	eax, ebx	/* AX := y2 */
X
XL31:	inc	ecx		/* CX := number of pixels to draw */
X	mov	ebx, x1(ebp)	/* BX := x */
X	push	ecx		/* save register */
X	call	PixelAddr	/* AH := bit mask */
X				/* ES:BX -> video buffer */
X				/* CL := number bits to shift left */
X
X/* set up Graphics controller */
X
X	shlb	ah, cl		/* AH := bit mask in proper position */
X	movb	al, #BITMASKREG	/* AL := Bit Mask register number */
X	out	dx, ax
X
X	pop	ecx		/* restore register */
X
X/* draw the line */
X
X	push	ds
X	push	es
X	pop	ds
XL111:	orb	(ebx), al	/* set pixel */
X	add	ebx, esi	/* increment to next line */
X	loop	L111
X	pop	ds
X	jmp	Lexit
X
X
X/*
X * Routine for horizontal lines (slope = 0)
X */
XHorizLine:
X	push	ds		/* preserve DS */
X
X	mov	eax, y1(ebp)
X	mov	ebx, x1(ebp)
X	call	PixelAddr	/* AH := bit mask */
X				/* ES:BX -> video buffer */
X				/* CL := number bits to shift left */
X	mov	edi, ebx	/* ES:DI -> buffer */
X	movb	dh, ah		/* DH := unshifted bit mask for left byte */
X
X	notb	dh
X	shlb	dh, cl		/* DH := reverse bit mask for first byte */
X	notb	dh		/* DH := bit mask for first byte */
X
X	mov	ecx, x2(ebp)
X	andb	cl, #0x07
X	xorb	cl, #0x07	/* CL := number of bits to shift left */
X	movb	dl, #0xff	/* DL := unshifted bit mask for right byte */
X	shlb	dl, cl		/* DL := bit mask for last byte */
X
X	/* determine byte offset of first and last pixel in the line */
X
X	mov	eax, x2(ebp)	/* AX := x2 */
X	mov	ebx, x1(ebp)	/* BX := x1 */
X
X	movb	cl, #PIXSHIFT	/* bits to convert pixels to bytes */
X
X	shr	eax, cl		/* AX := byte offset of X2 */
X	shr	ebx, cl		/* BX := byte offset of X1 */
X	mov	ecx, eax
X	sub	ecx, ebx	/* CX := (number of bytes in line) - 1 */
X
X	/* get Graphics Controller port address into DX */
X
X	mov	ebx, edx	/* BH := bit mask for first byte */
X				/* BL := bit mask for last byte */
X	mov	dx, #PORTADDR	/* DX := Graphics Controller port */
X	movb	al, #BITMASKREG	/* AL := Bit mask Register number */
X
X	/* make video buffer addressable through DS:SI */
X
X	push	es
X	pop	ds
X	mov	esi, edi	/* DS:SI -> video buffer */
X
X	/* set pixels in leftmost byte of the line */
X
X	orb	bh, bh
X	js	L43		/* jump if byte-aligned (x1 is leftmost) */
X
X	or	ecx, ecx
X	jnz	L42		/* jump if more than one byte in the line */
X
X	andb	bl, bh		/* BL := bit mask for the line */
X	jmp	L44
X
XL42:	movb	ah, bh		/* AH := bit mask for first byte */
X	out	dx, ax		/* update graphics controller */
X
X	movsb			/* update bit planes */
X	dec	ecx
X
X	/* use a fast 8086 machine instruction to draw the remainder of the line */
X
XL43:	movb	ah, #0xff	/* AH := bit mask */
X	out	dx, ax		/* update Bit Mask register */
X	rep
X	movsb			/* update all pixels in the line */
X
X	/* set pixels in the rightmost byte of the line */
X
XL44:	movb	ah, bl		/* AH := bit mask for last byte */
X	out	dx, ax		/* update Graphics Controller */
X	movsb			/* update bit planes */
X
X	pop	ds		/* restore ds */
X	jmp	Lexit
X
X
X/*
X * Routine for dy >= dx (slope <= 1)
X * ES:DI -> video buffer
X * AL = Bit Mask Register number
X * BL = bit mask for first pixel
X * CX = number of pixels to draw
X * DX = Graphics Controller port address
X * SI = decision variable
X */
XLowSlope:
X
XL10:	movb	ah, bl		/* AH := bit mask for next pixel */
X
XL11:	orb	ah, bl		/* mask current bit position */
X	rorb	bl, #1		/* rotate pixel value */
X	jc	L14		/* jump if bit mask rotated to leftmost position */
X
X	/* bit mask not shifted out */
X
X	or	esi, esi	/* test sign of d */
X	jns	L12		/* jump if d >= 0 */
X
X	add	esi, incr1(ebp)	/* d := d + incr1 */
X	loop	L11
X
X	out	dx, ax		/* update Bit Mask register */
X	seg	es
X	orb	(edi), al	/* set remaining pixel(s) */
X	jmp	Lexit
X
XL12:	add	esi, incr2(ebp)	/* d := d + incr2 */
X	out	dx, ax		/* update Bit Mask register */
X
X	seg	es
X	orb	(edi), al	/* update bit planes */
X
X	add	edi, rowincr(ebp)	/* increment y */
X	loop	L10
X	jmp	Lexit
X
X	/* bit mask shifted out */
X
XL14:	out	dx, ax		/* update Bit Mask register */
X
X	seg	es
X	orb	(edi), al	/* update bit planes */
X	inc	edi		/* increment x */
X
X	or	esi, esi	/* test sign of d */
X	jns	L15		/* jump if non-negative */
X
X	add	esi, incr1(ebp)	/* d := d + incr1 */
X	loop	L10
X	jmp	Lexit
X
XL15:	add	esi, incr2(ebp)	/* d := d + incr2 */
X	add	edi, rowincr(ebp)	/* vertical increment */
X	loop	L10
X	jmp	Lexit
X
X
X/*
X * Routine for dy > dx (slope > 1)
X * ES:DI -> video buffer
X * AH = bit mask for first pixel
X * AL = Bit Mask register number
X * CX = number pixels to draw
X * DX = Graphics Controller port address
X * SI = decision variable
X */
XHighSlope:
X	mov	ebx, rowincr(ebp)	/* BX := y increment */
X
XL21:	out	dx, ax		/* update Bit Mask register */
XL21a:	seg	es
X	orb	(edi), al	/* update bit planes */
X
X	add	edi, ebx	/* increment y */
X
XL22:	or	esi, esi	/* test sign of d */
X	jns	L23		/* jump if d >= 0 */
X
X	add	esi, incr1(ebp)	/* d := d + incr1 */
X	loop	L21a
X	jmp	Lexit
X
XL23:	add	esi, incr2(ebp)	/* d := d + incr2 */
X	rorb	ah, #1		/* rotate bit mask */
X	adc	edi, #0		/* increment DI if when mask rotated to */
X				/* leftmost pixel position */
X	loop	L21
X/*	jmp	Lexit */
X
X
X	/* restore default Graphics Controller state and return to caller */
X
XLexit:	xor	ax, ax		/* AH := 0, AL := 0 */
X	out	dx, ax		/* restore Set/Reset register */
X
X	inc	ax		/* AH := 0, AL := 1 */
X	out	dx, ax		/* restore Enable Set/Reset register */
X
X	mov	ax, #INITBITMASK	/* AH := 0xff, AL := 0 */
X	out	dx, ax		/* restore Bit Mask register */
X
X	pop	es
X	pop	edi
X	pop	esi
X	mov	esp, ebp	/* restore registers and return */
X	pop	ebp
X	ret
X
X#undef	color
X
X
X/*
X * Routine to set an individual pixel value.
X * Called from C like:
X *	_ega_drawpoint(x, y, color);
X */
X
X/* argument offsets, starting with 8 bytes (eip + ebp) */
X#define	x	8		/* X coordinate */
X#define	y	12		/* Y coordinate */
X#define	color	16		/* pixel value */
X
X
X_ega_drawpoint:
X	push	ebp
X	mov	ebp, esp
X	push	ds		/* save registers and set up stack frame */
X
X	mov	ecx, x(ebp)	/* ECX := x */
X	cmp	ecx, #PIXCOLS	/* if ((x<0) || (x>=PIXCOLS)) return */
X	jae	done
X
X	mov	eax, y(ebp)	/* EAX := y */
X	cmp	eax, #PIXROWS	/* if ((y<0) || (y>=PIXROWS)) return */
X	jae	done
X
X	mov	edx, #PIXBYTES	/* AX := (y * PIXBYTES) */
X	mul	edx
X
X	mov	ebx, ecx	/* BX := (x / 8) */
X	shr	ebx, #3
X
X	add	ebx, eax	/* BX := (y * PIXBYTES) + (x / 8) */
X	add	ebx,#MEMADDR	/* add in memory physical address */
X
X	andb	cl, #0x07	/* CL := (x % 8) */
X	xorb	cl, #0x07	/* CL := 7 - (x % 8) */
X	movb	ch, #0x01	/* CH := 1 << (7 - (x % 8))	(mask) */
X	shlb	ch, cl
X
X	mov	ax, #FLAT_DS_SELECTOR	/* DS := EGA buffer segment address */
X	mov	ds, ax
X
X	mov	dx, #PORTADDR	/* graphics controller port address */
X	mov	ax, #WRITEMODE2	/* select write mode 2 */
X	out	dx, ax		/* (load value 2 into mode register 5) */
X	movb	al, #BITMASKREG	/* set the bit mask register */
X	movb	ah, ch		/* (load bit mask into register 8) */
X	out	dx, ax
X	movb	al, (ebx)	/* dummy read to latch bit planes */
X	mov	ax, color(ebp)	/* pixel value */
X	movb	(ebx), al	/* write pixel back to bit planes */
X
X	mov	ax, #INITWRITEMODE	/* restore default write mode 0 */
X	out	dx, ax		/* (load value 0 into mode register 5) */
X	mov	ax, #INITBITMASK	/* restore default bit mask */
X	out	dx, ax		/* (load value ff into register 8) */
X
Xdone:	pop	ds		/* restore registers and return */
X	pop	ebp
X	ret
X
X
X/*
X * Routine to draw a text string using the ROM character bitmap.
X * If the background color is (long) -1 then it is not drawn.
X * Called from C like:
X *	ega_drawtext(x, y, cp, len, fg, bg);
X */
X#undef	x
X#undef	y
X#define	x	8			/* X coordinate */
X#define	y	12			/* Y coordinate */
X#define	cp	16			/* character pointer */
X#define	len	20			/* length of string */
X#define	fg	24			/* foreground color */
X#define	bg	28			/* background color */
X
X_ega_drawtext:
X	push	ebp
X	mov	ebp, esp
X	push	ds		/* save registers we use */
X	push	es
X	push	edi
X	push	esi
X
X	mov	eax, y(ebp)	/* EAX := y */
X	cmp	eax, #PIXROWS	/* if ((y<0) || (y>=PIXROWS)) return */
X	jae	donetext
X	add	eax, #CHARROWS-1	/* convert y to top of chars */
X	jl	donetext	/* if not enough room, return */
X
X	mov	ebx, x(ebp)	/* EBX := x */
X	cmp	ebx, #PIXCOLS	/* if ((x<0) || (x>=PIXCOLS)) return */
X	jae	donetext
X
X	mov	ecx, len(ebp)	/* see if length is non-positive */
X	or	ecx, ecx
X	jle	donetext
X
X	cmp	ecx, #PIXCOLS	/* or very large */
X	jae	donetext
X
X	shl	ecx, #3		/* convert char length to pixel column count */
X	add	ecx, ebx	/* determine first column to not touch */
X	cmp	ecx, #PIXCOLS	/* see if will write off end */
X	jg	donetext
X
Xcharloop:
X	mov	ebx, cp(ebp)	/* get address of next character */
X	xor	eax, eax
X	movb	al, (ebx)	/* get next character */
X	inc	ebx		/* increment character pointer */
X	mov	cp(ebp), ebx	/* save away */
X	mov	edx,#CHARROWS	/* bytes between character bitmaps */
X	mul	edx		/* convert char code to offset in ROM table */
X	add	eax, _rom_char_addr	/* make physical address of char bits */
X	mov	esi, eax	/* save in source register */
X
X	mov	eax, x(ebp)
X	mov	edx, #PIXBYTES	/* AX := (y * PIXBYTES) */
X	mul	edx
X
X	movb	cl, bl		/* save low order column bits */
X	shr	ebx, #3		/* BX := (x / 8) */
X
X	add	ebx, eax	/* BX := (y * PIXBYTES) + (x / 8) */
X	add	ebx,#MEMADDR	/* add in memory physical address */
X
X	andb	cl, #0x07	/* CL := (x % 8) */
X	xorb	cl, #0x07	/* CL := 7 - (x % 8) */
X
X	mov	dx, #FLAT_DS_SELECTOR	/* ES := EGA buffer segment address */
X	mov	ds, dx
X
X	movb	ch, #0x01	/* CH := 1 << (7 - (col % 8))  (mask) */
X	shlb	ch, cl		/* CH := bit mask in proper position */
X
Xdonetext:
X	pop	esi
X	pop	edi
X	pop	es
X	pop	ds
X	ret
X
X
X/*
X * Routine to read the value of an individual pixel.
X * Called from C like:
X * 	color = readpoint(x, y);
X */
X
X#undef	x
X#undef	y
X#define	x	8			/* X coordinate */
X#define	y	12			/* Y coordinate */
X
X
X_ega_readpoint:
X	push	ebp
X	mov	ebp, esp
X
X	/*
X	 * Make sure that the line is totally within the screen area.
X	 * If not, then return a pixel value of 0.
X	 */
X	mov	eax, y(ebp)	/* EAX := y */
X	mov	ebx, x(ebp)	/* EBX := x */
X	cmp	eax, #PIXROWS	/* if ((y<0) || (y>=PIXROWS)) return */
X	jae	retzero
X	cmp	ebx, #PIXCOLS	/* if ((x<0) || (x>=PIXCOLS)) return */
X	jae	retzero
X
X	push	si
X	push	ds
X
X	mov	edx, #PIXBYTES	/* AX := (y * PIXBYTES) */
X	mul	edx
X
X	movb	cl, bl		/* save low order column bits */
X	shr	ebx, #3		/* BX := (x / 8) */
X
X	add	ebx, eax	/* BX := (y * PIXBYTES) + (x / 8) */
X	add	ebx,#MEMADDR	/* add in memory physical address */
X
X	andb	cl, #0x07	/* CL := (x % 8) */
X	xorb	cl, #0x07	/* CL := 7 - (x % 8) */
X
X	mov	dx, #FLAT_DS_SELECTOR	/* ES := EGA buffer segment address */
X	mov	ds, dx
X
X	movb	ch, #0x01	/* CH := 1 << (7 - (col % 8))  (mask) */
X	shlb	ch, cl		/* CH := bit mask in proper position */
X
X	mov	esi, ebx	/* ES:SI -> region buffer byte */
X	xorb	bl, bl		/* BL is used to accumulate the pixel value */
X
X	mov	dx, #PORTADDR	/* DX := Graphics Controller port */
X	mov	ax, #0x0304	/* AH := initial bit plane number */
X				/* AL := Read Map Select register number */
X
XL112:	out	dx, ax		/* select bit plane */
X	movb	bh, (esi)	/* BH := byte from current bit plane */
X	andb	bh, ch		/* mask one bit */
X	negb	bh		/* bit 7 of BH := 1 if masked bit = 1 */
X				/* bit 7 of BH := 0 if masked bit = 0 */
X	rol	bx, #1		/* bit 0 of BL := next bit from pixel value */
X	decb	ah		/* AH := next bit plane number */
X	jge	L112
X
X	xor	eax, eax	/* AL := pixel value */
X	movb	al, bl
X
X	pop	ds
X	pop	si
X	pop	ebp	
X	ret
X
Xretzero:
X	pop	ebp
X	xor	eax, eax
X	ret
X
X
X/*
X * Local routine to convert row and column numbers to pixel addresses and masks.
X * Input:	EAX = row
X *		EBX = column
X * Output:
X *		AH := bit mask
X *		ES:EBX -> video buffer
X *		CL := number bits to shift left
X */
XPixelAddr:
X	push	edx
X
X	mov	edx, #PIXBYTES	/* AX := (row * PIXBYTES) */
X	mul	edx
X
X	movb	cl, bl		/* save low order column bits */
X	shr	ebx, #3		/* BX := (col / 8) */
X
X	add	ebx, eax	/* BX := (row * PIXBYTES) + (col / 8) */
X	add	ebx,#MEMADDR	/* add in memory physical address */
X
X	andb	cl, #0x07	/* CL := (col % 8) */
X	xorb	cl, #0x07	/* CL := 7 - (col % 8) */
X	movb	ah, #0x01	/* AH := 1 << (7 - (col % 8))	(mask) */
X
X	mov	dx, #FLAT_DS_SELECTOR	/* ES := EGA buffer segment address */
X	mov	es, dx
X
X	pop	edx
X
X	ret
END_OF_FILE
if test 18881 -ne `wc -c <'mini-x/kernel/ega.x'`; then
    echo shar: \"'mini-x/kernel/ega.x'\" unpacked with wrong size!
fi
# end of 'mini-x/kernel/ega.x'
fi
if test -f 'mini-x/server/client.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'mini-x/server/client.c'\"
else
echo shar: Extracting \"'mini-x/server/client.c'\" \(16055 characters\)
sed "s/^X//" >'mini-x/server/client.c' <<'END_OF_FILE'
X/*
X * Copyright (c) 1991 David I. Bell
X * Permission is granted to use, distribute, or modify this source,
X * provided that this copyright notice remains intact.
X *
X * Client routines to do graphics with windows and graphics contexts.
X * NOTE: These are stub routines at the moment because the server
X * routines are loaded with the client into one process.  The problem
X * with this is that you can run only one client program on the screen.
X * Eventually, the server will run in its own process, and these routines
X * then must ship their arguments across some network interface to that
X * process.  At that point, the server can then serve multiple clients
X * simultaneously.
X */
X#include <stdio.h>
X#include "graph_serv.h"
X
X
X/*
X * The following is used to allocate ids which the server will
X * recognize as our windows and such.  Since we and the server
X * keep in step in the allocation, it is not necessary to wait
X * for the server to return resource ids.
X */
Xstatic	GR_ID	allocid;
X
X
X/*
X * The following is the user defined function for handling errors.
X * If this is not set, then the default action is to close the connection
X * to the server, describe the error, and then exit.  This error function
X * will only be called when the client asks for events.
X */
Xstatic GR_ERROR_FUNC	GrErrorFunc;
X
X
X
X/*
X * Open a connection to the graphics server.
X * Returns zero if successful, -1 on failure.
X */
Xint
XGrOpen()
X{
X	GrErrorFunc = 0;
X	allocid = GsOpen();
X	if (allocid == 0)
X		return -1;
X	return 0;
X}
X
X
X/*
X * Close the graphics device, first flushing any waiting messages.
X */
Xvoid
XGrClose()
X{
X	GsClose();
X}
X
X
X/*
X * Set an error handling routine, which will be called on any errors from
X * the server (when events are asked for by the client).  If zero is given,
X * then a default routine will be used.  Returns the previous error handler.
X */
XGR_ERROR_FUNC
XGrSetErrorHandler(func)
X	GR_ERROR_FUNC	func;		/* function to handle error */
X{
X	GR_ERROR_FUNC	oldfunc;	/* previous function */
X
X	oldfunc = GrErrorFunc;
X	GrErrorFunc = func;
X	return oldfunc;
X}
X
X
X/*
X * Return useful information about the screen.
X */
Xvoid
XGrGetScreenInfo(sip)
X	GR_SCREEN_INFO	*sip;		/* address of screen info */
X{
X	GsGetScreenInfo(sip);
X}
X
X
X/*
X * Return useful information about the specified font.
X */
Xvoid
XGrGetFontInfo(font, fip)
X	GR_FONT		font;		/* font number */
X	GR_FONT_INFO	*fip;		/* address of font info */
X{
X	GsGetFontInfo(font, fip);
X}
X
X
X/*
X * Return information about the specified graphics context.
X */
Xvoid
XGrGetGCInfo(gc, gcip)
X	GR_GC_ID	gc;		/* graphics context */
X	GR_GC_INFO	*gcip;		/* address of graphics context info */
X{
X	GsGetGCInfo(gc, gcip);
X}
X
X
X/*
X * Return the size of a text string for the font in a graphics context.
X * This is the width of the string, the height of the string,
X * and the height above the bottom of the font of the baseline for the font.
X */
Xvoid
XGrGetGCTextSize(gc, cp, len, retwidth, retheight, retbase)
X	GR_GC_ID	gc;		/* graphics context containing font */
X	GR_CHAR		*cp;		/* address of text string */
X	GR_SIZE		len;		/* length of text string */
X	GR_SIZE		*retwidth;	/* returned width of string */
X	GR_SIZE		*retheight;	/* returned height of string */
X	GR_SIZE		*retbase;	/* returned height of baseline */
X{
X	GsGetGCTextSize(gc, cp, len, retwidth, retheight, retbase);
X}
X
X
X/*
X * Return the next event from the event queue.
X * This waits for a new one if one is not ready.
X * If it is an error event, then a user-specified routine is
X * called if it was defined, otherwise we clean up and exit.
X */
Xvoid
XGrGetNextEvent(ep)
X	GR_EVENT	*ep;		/* address where event is returned */
X{
X	GsFlush();
X	while (1) {
X		GsGetNextEvent(ep);
X		if (ep->type != GR_EVENT_TYPE_ERROR)
X			return;
X
X		if (GrErrorFunc) {
X			(*GrErrorFunc)(ep->error.code, ep->error.name,
X				ep->error.id);
X			continue;
X		}
X
X		GsClose();
X		fprintf(stderr, "Graphics error %d, function %s, resource id %ld\n",
X			ep->error.code, ep->error.name, ep->error.id);
X		exit(1);
X	}
X}
X
X
X/*
X * Return the next event from the event queue if one is ready.
X * If one is not ready, then the type GR_EVENT_TYPE_NONE is returned.
X * If it is an error event, then a user-specified routine is called
X * if it was defined, otherwise we clean up and exit.
X */
Xvoid
XGrCheckNextEvent(ep)
X	GR_EVENT	*ep;		/* address where event is returned */
X{
X	GrPeekEvent(ep);
X	if (ep->type != GR_EVENT_TYPE_NONE)
X		GrGetNextEvent(ep);
X}
X
X
X/*
X * Return the next event from the event queue if available.
X * If there is no event, then a null event type is returned.
X */
Xvoid
XGrPeekEvent(ep)
X	GR_EVENT	*ep;		/* address where event is returned */
X{
X	GsFlush();
X	GsPeekEvent(ep);
X}
X
X
X/*
X * Select events for a window for this client.
X * The events are a bitmask for the events desired.
X */
Xvoid
XGrSelectEvents(wid, eventmask)
X	GR_WINDOW_ID	wid;		/* window id */
X	GR_EVENT_MASK	eventmask;	/* mask of events wanted */
X{
X	GsSelectEvents(wid, eventmask);
X}
X
X
X/*
X * Allocate a new window which is a child of the specified window.
X * The window inherits the cursor of the parent window.
X */
XGR_WINDOW_ID
XGrNewWindow(parent, x, y, width, height, bordersize, background, bordercolor)
X	GR_WINDOW_ID	parent;		/* parent id */
X	GR_COORD	x;		/* x position relative to parent */
X	GR_COORD	y;		/* y position relative to parent */
X	GR_SIZE		width;		/* width */
X	GR_SIZE		height;		/* height */
X	GR_SIZE		bordersize;	/* size of border */
X	GR_COLOR	background;	/* background color */
X	GR_COLOR	bordercolor;	/* border color */
X{
X	GsNewWindow(parent, x, y, width, height, bordersize,
X		background, bordercolor);
X
X	return ++allocid;
X}
X
X
X/*
X * Allocate a new input-only window which is a child of the specified window.
X * The window inherits the cursor of the parent window.
X */
XGR_WINDOW_ID
XGrNewInputWindow(parent, x, y, width, height)
X	GR_WINDOW_ID	parent;		/* parent id */
X	GR_COORD	x;		/* x position relative to parent */
X	GR_COORD	y;		/* y position relative to parent */
X	GR_SIZE		width;		/* width */
X	GR_SIZE		height;		/* height */
X{
X	GsNewInputWindow(parent, x, y, width, height);
X
X	return ++allocid;
X}
X
X
X/*
X * Destroy an existing window.
X */
Xvoid
XGrDestroyWindow(wid)
X	GR_WINDOW_ID	wid;		/* window to destroy */
X{
X	GsDestroyWindow(wid);
X}
X
X
X/*
X * Return information about a window id.
X */
Xvoid
XGrGetWindowInfo(wid, infoptr)
X	GR_WINDOW_ID		wid;		/* window to find out about */
X	GR_WINDOW_INFO		*infoptr;	/* pointer to returned data */
X{
X	GsGetWindowInfo(wid, infoptr);
X}
X
X
X/*
X * Allocate a new GC with default parameters.
X */
XGR_GC_ID
XGrNewGC()
X{
X	GsNewGC();
X
X	return ++allocid;
X}
X
X
X/*
X * Allocate a new GC which is a copy of another one.
X */
XGR_GC_ID
XGrCopyGC(gc)
X	GR_GC_ID	gc;		/* graphics context to copy */
X{
X	GsCopyGC(gc);
X
X	return ++allocid;
X}
X
X
X/*
X * Destroy an existing graphics context.
X */
Xvoid
XGrDestroyGC(gc)
X	GR_GC_ID	gc;		/* graphics context to destroy */
X{
X	GsDestroyGC(gc);
X}
X
X
X/*
X * Map the window to make it (and possibly its children) visible on the screen.
X * This paints the border and background of the window, and creates an
X * exposure event to tell the client to draw into it.
X */
Xvoid
XGrMapWindow(wid)
X	GR_WINDOW_ID	wid;		/* window to be mapped */
X{
X	GsMapWindow(wid);
X}
X
X
X/*
X * Unmap the window to make it and its children invisible on the screen.
X */
Xvoid
XGrUnmapWindow(wid)
X	GR_WINDOW_ID	wid;		/* window to be unmapped */
X{
X	GsUnmapWindow(wid);
X}
X
X
X/*
X * Raise the window to the highest level among its siblings.
X */
Xvoid
XGrRaiseWindow(wid)
X	GR_WINDOW_ID	wid;		/* window to be raised */
X{
X	GsRaiseWindow(wid);
X}
X
X
X/*
X * Lower the window to the lowest level among its siblings.
X */
Xvoid
XGrLowerWindow(wid)
X	GR_WINDOW_ID	wid;		/* window to be lowered */
X{
X	GsLowerWindow(wid);
X}
X
X
X/*
X * Move the window to the specified position relative to its parent.
X */
Xvoid
XGrMoveWindow(wid, x, y)
X	GR_WINDOW_ID	wid;		/* window to be lowered */
X	GR_COORD	x;		/* new relative x position */
X	GR_COORD	y;		/* new relative y position */
X{
X	GsMoveWindow(wid, x, y);
X}
X
X
X/*
X * Resize the window to be the specified size.
X */
Xvoid
XGrResizeWindow(wid, width, height)
X	GR_WINDOW_ID	wid;		/* window to be lowered */
X	GR_SIZE		width;		/* new width of window */
X	GR_SIZE		height;		/* new height of window */
X{
X	GsResizeWindow(wid, width, height);
X}
X
X
X/*
X * Clear the specified window by setting it to its background color.
X * If the exposeflag is nonzero, then this also creates an exposure
X * event for the window.
X */
Xvoid
XGrClearWindow(wid, exposeflag)
X	GR_WINDOW_ID	wid;		/* window id */
X	GR_BOOL		exposeflag;	/* nonzero to cause an exposure */
X{
X	GsClearWindow(wid, exposeflag);
X}
X
X
X/*
X * Set the focus to a particular window.
X * This makes keyboard events only visible to that window or children of it,
X * depending on the pointer location.
X */
Xvoid
XGrSetFocus(wid)
X	GR_WINDOW_ID	wid;		/* window id */
X{
X	GsSetFocus(wid);
X}
X
X
X/*
X * Set the border of a window to the specified color.
X */
Xvoid
XGrSetBorderColor(wid, color)
X	GR_WINDOW_ID	wid;		/* window id */
X	GR_COLOR	color;		/* color for border */
X{
X	GsSetBorderColor(wid, color);
X}
X
X
X/*
X * Specify a cursor for a window.
X * This cursor will only be used within that window, and by default
X * for its new children.  If the cursor is currently within this
X * window, it will be changed to the new one immediately.
X */
Xvoid
XGrSetCursor(wid, width, height, hotx, hoty, foreground, background,
X	fgbitmap, bgbitmap)
X
X	GR_WINDOW_ID	wid;		/* window id to set cursor for */
X	GR_SIZE		width;		/* width of cursor */
X	GR_SIZE		height;		/* height of cursor */
X	GR_COORD	hotx;		/* relative x position of hot spot */
X	GR_COORD	hoty;		/* relative y position of hot spot */
X	GR_COLOR	foreground;	/* foreground color of cursor */
X	GR_COLOR	background;	/* background color of cursor */
X	GR_BITMAP	*fgbitmap;	/* foreground bitmap */
X	GR_BITMAP	*bgbitmap;	/* background bitmap */
X{
X	GsSetCursor(wid, width, height, hotx, hoty, foreground, background,
X		fgbitmap, bgbitmap);
X}
X
X
X/*
X * Move the cursor to the specified absolute screen coordinates.
X * The coordinates are that of the defined hot spot of the cursor.
X * The cursor's appearance is changed to that defined for the window
X * in which the cursor is moved to.
X */
Xvoid
XGrMoveCursor(x, y)
X	GR_COORD	x;		/* new x position of cursor */
X	GR_COORD	y;		/* new y position of cursor */
X{
X	GsMoveCursor(x, y);
X}
X
X
X/*
X * Flush the message buffer of any messages it may contain.
X */
Xvoid
XGrFlush()
X{
X	GsFlush();
X}
X
X
X/*
X * Set the foreground color in a graphics context.
X */
Xvoid
XGrSetGCForeground(gc, foreground)
X	GR_GC_ID	gc;		/* graphics context id */
X	GR_COLOR	foreground;	/* foreground color */
X{
X	GsSetGCForeground(gc, foreground);
X}
X
X
X/*
X * Set the background color in a graphics context.
X */
Xvoid
XGrSetGCBackground(gc, background)
X	GR_GC_ID	gc;		/* graphics context id */
X	GR_COLOR	background;	/* background color */
X{
X	GsSetGCBackground(gc, background);
X}
X
X
X/*
X * Set the drawing mode in a graphics context.
X */
Xvoid
XGrSetGCMode(gc, mode)
X	GR_GC_ID	gc;		/* graphics context id */
X	GR_MODE		mode;		/* drawing mode */
X{
X	GsSetGCMode(gc, mode);
X}
X
X
X/*
X * Set whether or not the background color is drawn in bitmaps and text.
X */
Xvoid
XGrSetGCUseBackground(gc, flag)
X	GR_GC_ID	gc;		/* graphics context id */
X	GR_BOOL		flag;		/* TRUE if background is drawn */
X{
X	GsSetGCUseBackground(gc, flag);
X}
X
X
X/*
X * Set the font used for text drawing in a graphics context.
X * The font is a number identifying one of several fonts.
X * Font number 0 is always available, and is the default font.
X */
Xvoid
XGrSetGCFont(gc, font)
X	GR_GC_ID	gc;		/* graphics context id */
X	GR_FONT		font;		/* text font */
X{
X	GsSetGCFont(gc, font);
X}
X
X
X/*
X * Draw a line in the specified drawable using the specified graphics context.
X */
Xvoid
XGrLine(id, gc, x1, y1, x2, y2)
X	GR_DRAW_ID	id;
X	GR_GC_ID	gc;
X	GR_COORD	x1;
X	GR_COORD	y1;
X	GR_COORD	x2;
X	GR_COORD	y2;
X{
X	GsLine(id, gc, x1, y1, x2, y2);
X}
X
X
X/*
X * Draw the boundary of a rectangle in the specified drawable using the
X * specified graphics context.
X */
Xvoid
XGrRect(id, gc, x, y, width, height)
X	GR_DRAW_ID	id;
X	GR_GC_ID	gc;
X	GR_COORD	x;
X	GR_COORD	y;
X	GR_SIZE		width;
X	GR_SIZE		height;
X{
X	GsRect(id, gc, x, y, width, height);
X}
X
X
X/*
X * Fill a rectangle in the specified drawable using the specified
X * graphics context.
X */
Xvoid
XGrFillRect(id, gc, x, y, width, height)
X	GR_DRAW_ID	id;
X	GR_GC_ID	gc;
X	GR_COORD	x;
X	GR_COORD	y;
X	GR_SIZE		width;
X	GR_SIZE		height;
X{
X	GsFillRect(id, gc, x, y, width, height);
X}
X
X
X/*
X * Draw the boundary of an ellipse in the specified drawable with
X * the specified graphics context.
X */
Xvoid
XGrEllipse(id, gc, x, y, rx, ry)
X	GR_DRAW_ID	id;
X	GR_GC_ID	gc;
X	GR_COORD	x;
X	GR_COORD	y;
X	GR_SIZE		rx;
X	GR_SIZE		ry;
X{
X	GsEllipse(id, gc, x, y, rx, ry);
X}
X
X
X/*
X * Fill an ellipse in the specified drawable using the specified
X * graphics context.
X */
Xvoid
XGrFillEllipse(id, gc, x, y, rx, ry)
X	GR_DRAW_ID	id;
X	GR_GC_ID	gc;
X	GR_COORD	x;
X	GR_COORD	y;
X	GR_SIZE		rx;
X	GR_SIZE		ry;
X{
X	GsFillEllipse(id, gc, x, y, rx, ry);
X}
X
X
X/*
X * Draw a rectangular area in the specified drawable using the specified
X * graphics, as determined by the specified bit map.  This differs from
X * rectangle drawing in that the rectangle is drawn using the foreground
X * color and possibly the background color as determined by the bit map.
X * Each row of bits is aligned to the next bitmap word boundary (so there
X * is padding at the end of the row).  The background bit values are
X * only written if the usebackground flag is set in the GC.
X */
Xvoid
XGrBitmap(id, gc, x, y, width, height, bitmaptable)
X	GR_DRAW_ID	id;
X	GR_GC_ID	gc;
X	GR_COORD	x;
X	GR_COORD	y;
X	GR_SIZE		width;
X	GR_SIZE		height;
X	GR_BITMAP	*bitmaptable;
X{
X	GsBitmap(id, gc, x, y, width, height, bitmaptable);
X}
X
X
X/*
X * Draw a rectangular area in the specified drawable using the specified
X * graphics context.  This differs from rectangle drawing in that the
X * color values for each pixel in the rectangle are specified.  The color
X * values are restricted to 8 bit values.  The color table is indexed
X * row by row.  Values whose color matches the background color are only
X * written if the usebackground flag is set in the GC.
X */
Xvoid
XGrArea8(id, gc, x, y, width, height, colortable)
X	GR_DRAW_ID	id;
X	GR_GC_ID	gc;
X	GR_COORD	x;
X	GR_COORD	y;
X	GR_SIZE		width;
X	GR_SIZE		height;
X	GR_COLOR8	*colortable;
X{
X	GsArea8(id, gc, x, y, width, height, colortable);
X}
X
X
X/*
X * Read the color values from the specified rectangular area of the
X * specified drawable into a supplied buffer.  If the drawable is a
X * window which is obscured by other windows, then the returned values
X * will include the values from the covering windows.  Regions outside
X * of the screen boundaries, or unmapped windows will return black.
X */
Xvoid
XGrReadArea8(id, x, y, width, height, colortable)
X	GR_DRAW_ID	id;
X	GR_COORD	x;
X	GR_COORD	y;
X	GR_SIZE		width;
X	GR_SIZE		height;
X	GR_COLOR8	*colortable;
X{
X	GsReadArea8(id, x, y, width, height, colortable);
X}
X
X
X/*
X * Draw a point in the specified drawable using the specified
X * graphics context.
X */
Xvoid
XGrPoint(id, gc, x, y)
X	GR_DRAW_ID	id;
X	GR_GC_ID	gc;
X	GR_COORD	x;
X	GR_COORD	y;
X{
X	GsPoint(id, gc, x, y);
X}
X
X
X/*
X * Draw a polygon in the specified drawable using the specified
X * graphics context.  The polygon is only complete if the first
X * point is repeated at the end.
X */
Xvoid
XGrPoly(id, gc, count, pointtable)
X	GR_DRAW_ID	id;
X	GR_GC_ID	gc;
X	GR_COUNT	count;
X	GR_POINT	*pointtable;
X{
X	GsPoly(id, gc, count, pointtable);
X}
X
X
X/*
X * Draw a filled polygon in the specified drawable using the specified
X * graphics context.  The last point may be a duplicate of the first
X * point, but this is not required.
X */
Xvoid
XGrFillPoly(id, gc, count, pointtable)
X	GR_DRAW_ID	id;
X	GR_GC_ID	gc;
X	GR_COUNT	count;
X	GR_POINT	*pointtable;
X{
X	GsFillPoly(id, gc, count, pointtable);
X}
X
X
X/*
X * Draw a text string in the specified drawable using the specified
X * graphics context.  The background of the characters are only drawn
X * if the usebackground flag in the GC is set.
X */
Xvoid
XGrText(id, gc, x, y, str, count)
X	GR_DRAW_ID	id;
X	GR_GC_ID	gc;
X	GR_COORD	x;
X	GR_COORD	y;
X	GR_CHAR		*str;
X	GR_COUNT	count;
X{
X	GsText(id, gc, x, y, str, count);
X}
X
X/* END CODE */
END_OF_FILE
if test 16055 -ne `wc -c <'mini-x/server/client.c'`; then
    echo shar: \"'mini-x/server/client.c'\" unpacked with wrong size!
fi
# end of 'mini-x/server/client.c'
fi
if test -f 'mini-x/server/serv_event.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'mini-x/server/serv_event.c'\"
else
echo shar: Extracting \"'mini-x/server/serv_event.c'\" \(16971 characters\)
sed "s/^X//" >'mini-x/server/serv_event.c' <<'END_OF_FILE'
X/*
X * Copyright (c) 1991 David I. Bell
X * Permission is granted to use, distribute, or modify this source,
X * provided that this copyright notice remains intact.
X *
X * Graphics server event routines for windows.
X */
X#include <stdio.h>
X#include "graph_serv.h"
X
X
Xextern	char	*malloc();
X
X
X/*
X * Generate an error from a graphics function.
X * This creates a special event which describes the error.
X * Only one error event at a time can be saved for delivery to a client.
X * This is ok since there are usually lots of redundant errors generated
X * before the client can notice, errors occurs after the fact, and clients
X * can't do much about them except complain and die.  The error is saved
X * specially so that memory problems cannot occur.
X */
Xvoid
XGsError(code, id)
X	GR_ERROR	code;		/* error code */
X	GR_ID		id;		/* id value to describe */
X{
X	GR_EVENT_ERROR	*ep;		/* event to describe error */
X
X	/*
X	 * If there is already an outstanding error, then forget this one.
X	 */
X	if (curclient->errorevent.type == GR_EVENT_TYPE_ERROR)
X		return;
X
X	/*
X	 * Save the error in a special location.
X	 */
X	ep = &curclient->errorevent;
X	ep->type = GR_EVENT_TYPE_ERROR;
X	strncpy(ep->name, curfunc, sizeof(GR_FUNC_NAME));
X	ep->name[sizeof(GR_FUNC_NAME)-1] = '\0';
X	ep->code = code;
X	ep->id = id;
X}
X
X
X/*
X * Allocate an event to be passed back to the specified client.
X * The event is already chained onto the event queue, and only
X * needs filling out.  Returns NULL with an error generated if
X * the event cannot be allocated.
X */
XGR_EVENT *
XGsAllocEvent(client)
X	GR_CLIENT	*client;	/* client to send event to */
X{
X	GR_EVENT_LIST	*elp;		/* current element list */
X	GR_CLIENT	*oldcurclient;	/* old current client */
X
X	/*
X	 * Get a new event structure from the free list, or else
X	 * allocate it using malloc.
X	 */
X	elp = eventfree;
X	if (elp)
X		eventfree = elp->next;
X	else {
X		elp = (GR_EVENT_LIST *) malloc(sizeof(GR_EVENT_LIST));
X		if (elp == NULL) {
X			oldcurclient = curclient;
X			curclient = client;
X			GsError(GR_ERROR_MALLOC_FAILED, 0);
X			curclient = oldcurclient;
X			return NULL;
X		}
X	}
X
X	/*
X	 * Add the event to the end of the event list.
X	 */
X	if (client->eventhead)
X		client->eventtail->next = elp;
X	else
X		client->eventhead = elp;
X	client->eventtail = elp;
X	elp->next = NULL;
X	elp->event.type = GR_EVENT_TYPE_NONE;
X
X	return &elp->event;
X}
X
X
X/*
X * Check for a new event to arrive from the hardware devices.
X * The event is either a keystroke or a mouse event, and is placed at
X * the end of the client's event queue.  This collects all available
X * status before returning.  NOTICE: If waiting is required then this
X * routine is a busy loop since there is no poll MINIX call.
X */
Xvoid
XGsCheckEvent(waitflag)
X	GR_BOOL		waitflag;	/* TRUE if should wait for event */
X{
X	GR_COORD	rootx;		/* latest mouse x position */
X	GR_COORD	rooty;		/* latest mouse y position */
X	GR_BUTTON	newbuttons;	/* latest buttons */
X	GR_CHAR		ch;		/* latest character */
X	GR_MODIFIER	modifiers;	/* latest modifiers */
X	int		mousestatus;	/* latest mouse status */
X	int		keystatus;	/* latest keyboard status */
X
X	GsFlush();
X	if (GdCheckError(GR_FALSE)) {
X		GsError(GR_ERROR_SCREEN_ERROR, 0);
X		return;
X	}
X
X	do {
X		/*
X		 * First read the latest mouse and keyboard status.
X		 */
X		mousestatus = GsReadMouse(&rootx, &rooty, &newbuttons);
X		keystatus = GsReadKeyboard(&ch, &modifiers);
X		if (mousestatus < 0) {
X			GsError(GR_ERROR_MOUSE_ERROR, 0);
X			return;
X		}
X		if (keystatus < 0) {
X			GsError(GR_ERROR_KEYBOARD_ERROR, 0);
X			return;
X		}
X
X		/*
X		 * Then deliver mouse or keyboard events as appropriate.
X		 * We must handle mouse status first in order to get the
X		 * cursor location updated quickly.
X		 */	
X		if (mousestatus) {
X			waitflag = GR_FALSE;
X			GsHandleMouseStatus(rootx, rooty, newbuttons,
X				modifiers);
X		}
X
X		if (keystatus) {
X			waitflag = GR_FALSE;
X			GsDeliverKeyboardEvent(GR_EVENT_TYPE_KEY_DOWN, ch,
X				newbuttons, modifiers);
X		}
X
X	} while (waitflag || mousestatus || keystatus);
X}
X
X
X/*
X * Handle all mouse events.  These are mouse enter, mouse exit, mouse
X * motion, mouse position, button down, and button up.  This also moves
X * the cursor to the new mouse position and changes it shape if needed.
X */
Xvoid
XGsHandleMouseStatus(newx, newy, newbuttons, modifiers)
X	GR_COORD	newx;		/* new x position of mouse */
X	GR_COORD	newy;		/* new y position of mouse */
X	GR_BUTTON	newbuttons;	/* new button states */
X	GR_BUTTON	modifiers;	/* modifiers (SHIFT, CTRL, etc) */
X{
X	GR_BUTTON	changebuttons;	/* buttons that have changed */
X
X	/*
X	 * First, if the mouse has moved, then position the cursor to the
X	 * new location, which will send mouse enter, mouse exit, focus in,
X	 * and focus out events if needed.  Check here for mouse motion and
X	 * mouse position events.  Flush the device queue to make sure the
X	 * new cursor location is quickly seen by the user.
X	 */
X	if ((newx != cursorx) || (newy != cursory)) {
X		GsMoveCursor(newx, newy);
X		GsFlush();
X		GsDeliverMotionEvent(GR_EVENT_TYPE_MOUSE_MOTION,
X			newbuttons, modifiers);
X		GsDeliverMotionEvent(GR_EVENT_TYPE_MOUSE_POSITION,
X			newbuttons, modifiers);
X	}
X
X	/*
X	 * Next, generate a button up event if any buttons have been released.
X	 */
X	changebuttons = (curbuttons & ~newbuttons);
X	if (changebuttons) {
X		GsDeliverButtonEvent(GR_EVENT_TYPE_BUTTON_UP,
X			newbuttons, changebuttons, modifiers);
X	}
X
X	/*
X	 * Finally, generate a button down event if any buttons have been
X	 * pressed.
X	 */
X	changebuttons = (~curbuttons & newbuttons);
X	if (changebuttons) {
X		GsDeliverButtonEvent(GR_EVENT_TYPE_BUTTON_DOWN,
X			newbuttons, changebuttons, modifiers);
X	}
X
X	curbuttons = newbuttons;
X}
X
X
X/*
X * Deliver a mouse button event to the clients which have selected for it.
X * Each client can only be delivered one instance of the event.  The window
X * the event is delivered for is either the smallest one containing the
X * mouse coordinates, or else one of its direct ancestors.  The lowest
X * window in that tree which has enabled for the event gets it.  This scan
X * is done independently for each client.  If a window with the correct
X * noprop mask is reached, or if no window selects for the event, then the
X * event is discarded for that client.  Special case: for the first client
X * that is enabled for both button down and button up events in a window,
X * then the pointer is implicitly grabbed by that window when a button is
X * pressed down in that window.  The grabbing remains until all buttons are
X * released.  While the pointer is grabbed, no other clients or windows can
X * receive button down or up events.
X */
Xvoid
XGsDeliverButtonEvent(type, buttons, changebuttons, modifiers)
X	GR_EVENT_TYPE	type;		/* type of event */
X	GR_BUTTON	buttons;	/* current button information */
X	GR_BUTTON	changebuttons;	/* buttons which have changed */
X	GR_MODIFIER	modifiers;	/* modifiers (SHIFT, CTRL, etc) */
X{
X	GR_EVENT_BUTTON	*ep;		/* mouse button event */
X	GR_WINDOW	*wp;		/* current window */
X	GR_EVENT_CLIENT	*ecp;		/* current event client */
X	GR_CLIENT	*client;	/* current client */
X	GR_WINDOW_ID	subwid;		/* subwindow id event is for */
X	GR_EVENT_MASK	eventmask;	/* event mask */
X	GR_EVENT_MASK	tempmask;	/* to get around compiler bug */
X
X	eventmask = GR_EVENTMASK(type);
X	if (eventmask == 0)
X		return;
X
X	eventnumber++;
X
X	/*
X	 * If the pointer is implicitly grabbed, then the only window
X	 * which can receive button events is that window.  Otherwise
X	 * the window the pointer is in gets the events.  Determine the
X	 * subwindow by seeing if it is a child of the grabbed button.
X	 */
X	wp = mousewp;
X	subwid = wp->id;
X
X	if (grabbuttonwp) {
X		while ((wp != rootwp) && (wp != grabbuttonwp))
X			wp = wp->parent;
X		if (wp != grabbuttonwp)
X			subwid = grabbuttonwp->id;
X		wp = grabbuttonwp;
X	}
X
X	for (;;) {
X		for (ecp = wp->eventclients; ecp; ecp = ecp->next) {
X			if ((ecp->eventmask & eventmask) == 0)
X				continue;
X
X			client = ecp->client;
X			if (client->eventnumber == eventnumber)
X				continue;
X
X			client->eventnumber = eventnumber;
X
X			/*
X			 * If this is a button down, the buttons are not
X			 * yet grabbed, and this client is enabled for both
X			 * button down and button up events, then implicitly
X			 * grab the window for him.
X			 */
X			if ((type == GR_EVENT_TYPE_BUTTON_DOWN)
X				&& (grabbuttonwp == NULL))
X			{
X				tempmask = GR_EVENT_MASK_BUTTON_UP;
X				if (ecp->eventmask & tempmask)
X					grabbuttonwp = wp;
X			}
X
X			ep = (GR_EVENT_BUTTON *) GsAllocEvent(client);
X			if (ep == NULL)
X				continue;
X
X			ep->type = type;
X			ep->wid = wp->id;
X			ep->subwid = subwid;
X			ep->rootx = cursorx;
X			ep->rooty = cursory;
X			ep->x = cursorx - wp->x;
X			ep->y = cursory - wp->y;
X			ep->buttons = buttons;
X			ep->changebuttons = changebuttons;
X			ep->modifiers = modifiers;
X		}
X
X		/*
X		 * Events do not propagate if the window was grabbed.
X		 * Also release the grab if the buttons are now all released,
X		 * which can cause various events.
X		 */
X		if (grabbuttonwp) {
X			if (buttons == 0) {
X				grabbuttonwp = NULL;
X				GsMoveCursor(cursorx, cursory);
X				GsFlush();
X			}
X			return;
X		}
X
X		if ((wp == rootwp) || (wp->nopropmask & eventmask))
X			return;
X
X		wp = wp->parent;
X	}
X}
X
X
X/*
X * Deliver a mouse motion event to the clients which have selected for it.
X * Each client can only be delivered one instance of the event.  The window
X * the event is delivered for is either the smallest one containing the
X * mouse coordinates, or else one of its direct ancestors.  The lowest
X * window in that tree which has enabled for the event gets it.  This scan
X * is done independently for each client.  If a window with the correct
X * noprop mask is reached, or if no window selects for the event, then the
X * event is discarded for that client.  Special case: If the event type is
X * GR_EVENT_TYPE_MOUSE_POSITION, then only the last such event is queued for
X * any single client to reduce events.  If the mouse is implicitly grabbed,
X * then only the grabbing window receives the events, and continues to do
X * so even if the mouse is currently outside of the grabbing window.
X */
Xvoid
XGsDeliverMotionEvent(type, buttons, modifiers)
X	GR_EVENT_TYPE	type;		/* type of event */
X	GR_BUTTON	buttons;	/* current button information */
X	GR_MODIFIER	modifiers;	/* modifiers (SHIFT, CTRL, etc) */
X{
X	GR_EVENT_MOUSE	*ep;		/* mouse motion event */
X	GR_WINDOW	*wp;		/* current window */
X	GR_EVENT_CLIENT	*ecp;		/* current event client */
X	GR_CLIENT	*client;	/* current client */
X	GR_WINDOW_ID	subwid;		/* subwindow id event is for */
X	GR_EVENT_MASK	eventmask;	/* event mask */
X
X	eventmask = GR_EVENTMASK(type);
X	if (eventmask == 0)
X		return;
X
X	eventnumber++;
X
X	wp = mousewp;
X	subwid = wp->id;
X
X	if (grabbuttonwp) {
X		while ((wp != rootwp) && (wp != grabbuttonwp))
X			wp = wp->parent;
X		if (wp != grabbuttonwp)
X			subwid = grabbuttonwp->id;
X		wp = grabbuttonwp;
X	}
X
X	for (;;) {
X		for (ecp = wp->eventclients; ecp; ecp = ecp->next) {
X			if ((ecp->eventmask & eventmask) == 0)
X				continue;
X
X			client = ecp->client;
X			if (client->eventnumber == eventnumber)
X				continue;
X
X			client->eventnumber = eventnumber;
X
X			/*
X			 * If the event is for just the latest position,
X			 * then search the event queue for an existing
X			 * event of this type (if any), and free it.
X			 */
X			if (type == GR_EVENT_TYPE_MOUSE_POSITION) 
X				GsFreePositionEvent(client, wp->id, subwid);
X
X			ep = (GR_EVENT_MOUSE *) GsAllocEvent(client);
X			if (ep == NULL)
X				continue;
X
X			ep->type = type;
X			ep->wid = wp->id;
X			ep->subwid = subwid;
X			ep->rootx = cursorx;
X			ep->rooty = cursory;
X			ep->x = cursorx - wp->x;
X			ep->y = cursory - wp->y;
X			ep->buttons = buttons;
X			ep->modifiers = modifiers;
X		}
X
X		if ((wp == rootwp) || grabbuttonwp ||
X			(wp->nopropmask & eventmask))
X				return;
X
X		wp = wp->parent;
X	}
X}
X
X
X/*
X * Deliver a keyboard event to one of the clients which have selected for it.
X * Only the first client found gets the event (no duplicates are sent).  The
X * window the event is delivered to is either the smallest one containing
X * the mouse coordinates, or else one of its direct ancestors (if such a
X * window is a descendant of the focus window), or else just the focus window.
X * The lowest window in that tree which has enabled for the event gets it.
X * If a window with the correct noprop mask is reached, or if no window selects
X * for the event, then the event is discarded.
X */
Xvoid
XGsDeliverKeyboardEvent(type, ch, buttons, modifiers)
X	GR_EVENT_TYPE	type;		/* type of event */
X	GR_CHAR		ch;		/* character */
X	GR_BUTTON	buttons;	/* button information */
X	GR_MODIFIER	modifiers;	/* modifiers (SHIFT, CTRL, etc) */
X{
X	GR_EVENT_KEYSTROKE	*ep;		/* keystroke event */
X	GR_WINDOW		*wp;		/* current window */
X	GR_WINDOW		*tempwp;	/* temporary window pointer */
X	GR_EVENT_CLIENT		*ecp;		/* current event client */
X	GR_WINDOW_ID		subwid;		/* subwindow id event is for */
X	GR_EVENT_MASK		eventmask;	/* event mask */
X
X	eventmask = GR_EVENTMASK(type);
X	if (eventmask == 0)
X		return;
X
X	wp = mousewp;
X	subwid = wp->id;
X
X	/*
X	 * See if the actual window the pointer is in is a descendant of
X	 * the focus window.  If not, then ignore it, and force the input
X	 * into the focus window itself.
X	 */
X	tempwp = wp;
X	while ((tempwp != focuswp) && (tempwp != rootwp))
X		tempwp = tempwp->parent;
X
X	if (tempwp != focuswp) {
X		wp = focuswp;
X		subwid = wp->id;
X	}
X
X	/*
X	 * Now walk upwards looking for the first window which will accept
X	 * the keyboard event.  However, do not go beyond the focus window,
X	 * and only give the event to one client.
X	 */
X	for (;;) {
X		for (ecp = wp->eventclients; ecp; ecp = ecp->next) {
X			if ((ecp->eventmask & eventmask) == 0)
X				continue;
X
X			ep = (GR_EVENT_KEYSTROKE *) GsAllocEvent(ecp->client);
X			if (ep == NULL)
X				return;
X
X			ep->type = type;
X			ep->wid = wp->id;
X			ep->subwid = subwid;
X			ep->rootx = cursorx;
X			ep->rooty = cursory;
X			ep->x = cursorx - wp->x;
X			ep->y = cursory - wp->y;
X			ep->buttons = buttons;
X			ep->modifiers = modifiers;
X			ep->ch = ch;
X			return;			/* only one client gets it */
X		}
X
X		if ((wp == rootwp) || (wp == focuswp) ||
X			(wp->nopropmask & eventmask))
X				return;
X
X		wp = wp->parent;
X	}
X}
X
X
X/*
X * Try to deliver a exposure event to the clients which have selected for it.
X * This does not send exposure events for unmapped or input-only windows.
X * Exposure events do not propagate upwards.
X */
Xvoid
XGsDeliverExposureEvent(wp, x, y, width, height)
X	GR_WINDOW	*wp;		/* window being exposed */
X	GR_COORD	x;		/* x position of cursor */
X	GR_COORD	y;		/* y position of cursor */
X	GR_SIZE		width;		/* width of exposure */
X	GR_SIZE		height;		/* height of exposure */
X{
X	GR_EVENT_EXPOSURE	*ep;		/* exposure event */
X	GR_EVENT_CLIENT		*ecp;		/* current event client */
X
X	if (wp->unmapcount || !wp->output)
X		return;
X
X	for (ecp = wp->eventclients; ecp; ecp = ecp->next) {
X		if ((ecp->eventmask & GR_EVENT_MASK_EXPOSURE) == 0)
X			continue;
X
X		ep = (GR_EVENT_EXPOSURE *) GsAllocEvent(ecp->client);
X		if (ep == NULL)
X			continue;
X
X		ep->type = GR_EVENT_TYPE_EXPOSURE;
X		ep->wid = wp->id;
X		ep->x = x;
X		ep->y = y;
X		ep->width = width;
X		ep->height = height;
X	}
X}
X
X
X/*
X * Try to deliver a general event such as focus in, focus out, mouse enter,
X * or mouse exit to the clients which have selected for it.  These events
X * only have the window id as data, and do not propagate upwards.
X */
Xvoid
XGsDeliverGeneralEvent(wp, type)
X	GR_WINDOW	*wp;			/* window to give event to */
X	GR_EVENT_TYPE	type;			/* event type */
X{
X	GR_EVENT_GENERAL	*gp;		/* general event */
X	GR_EVENT_CLIENT		*ecp;		/* current event client */
X	GR_EVENT_MASK		eventmask;	/* event mask */
X
X	eventmask = GR_EVENTMASK(type);
X	if (eventmask == 0)
X		return;
X
X	for (ecp = wp->eventclients; ecp; ecp = ecp->next) {
X		if ((ecp->eventmask & eventmask) == 0)
X			continue;
X
X		gp = (GR_EVENT_GENERAL *) GsAllocEvent(ecp->client);
X		if (gp == NULL)
X			continue;
X
X		gp->type = type;
X		gp->wid = wp->id;
X	}
X}
X
X
X/*
X * Search for a matching mouse position event in the specified client's
X * event queue, and remove it.  This is used to prevent multiple position
X * events from being delivered, thus providing a more efficient rubber-
X * banding effect than if the mouse motion events were all sent.
X */
Xvoid
XGsFreePositionEvent(client, wid, subwid)
X	GR_CLIENT	*client;	/* client to search */
X	GR_WINDOW_ID	wid;		/* window id to search for */
X	GR_WINDOW_ID	subwid;		/* subwindow id to search for */
X{
X	GR_EVENT_LIST	*elp;		/* current element list */
X	GR_EVENT_LIST	*prevelp;	/* previous element list */
X
X	prevelp = NULL;
X	for (elp = client->eventhead; elp; prevelp = elp, elp = elp->next) {
X		if (elp->event.type != GR_EVENT_TYPE_MOUSE_POSITION)
X			continue;
X		if (elp->event.mouse.wid != wid)
X			continue;
X		if (elp->event.mouse.subwid != subwid)
X			continue;
X
X		/*
X		 * Found one, remove it and put it back on the free list.
X		 */
X		if (prevelp)
X			prevelp->next = elp->next;
X		else
X			client->eventhead = elp->next;
X		if (client->eventtail == elp)
X			client->eventtail = prevelp;
X
X		elp->next = eventfree;
X		eventfree = elp;
X		return;
X	}
X}
X
X/* END CODE */
END_OF_FILE
if test 16971 -ne `wc -c <'mini-x/server/serv_event.c'`; then
    echo shar: \"'mini-x/server/serv_event.c'\" unpacked with wrong size!
fi
# end of 'mini-x/server/serv_event.c'
fi
echo shar: End of archive 4 \(of 9\).
cp /dev/null ark4isdone
MISSING=""
for I in 1 2 3 4 5 6 7 8 9 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked all 9 archives.
    rm -f ark[1-9]isdone ark[1-9][0-9]isdone
else
    echo You still need to unpack the following archives:
    echo "        " ${MISSING}
fi
##  End of shell archive.
exit 0

dbell@pdact.pd.necisa.oz.au (David I. Bell) (04/22/91)

#! /bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of archive 5 (of 9)."
# Contents:  mini-x/kernel/graphics.c mini-x/server/serv_dev.c
# Wrapped by dbell@elm on Mon Apr 22 11:21:47 1991
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'mini-x/kernel/graphics.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'mini-x/kernel/graphics.c'\"
else
echo shar: Extracting \"'mini-x/kernel/graphics.c'\" \(19967 characters\)
sed "s/^X//" >'mini-x/kernel/graphics.c' <<'END_OF_FILE'
X/* Copyright (c) 1991 David I. Bell
X * Permission is granted to use, distribute, or modify this source,
X * provided that this copyright notice remains intact.
X *
X * This file contains the drivers for the following special file:
X *     /dev/graphics	- graphics screen
X *
X * The driver supports the following operations (using message format m2):
X *
X *    m_type      DEVICE    PROC_NR     COUNT    POSITION  ADRRESS
X * ----------------------------------------------------------------
X * |  DISK_READ | device  | proc nr |  bytes  |  offset | buf ptr |
X * |------------+---------+---------+---------+---------+---------|
X * | DISK_WRITE | device  | proc nr |  bytes  |  offset | buf ptr |
X * |------------+---------+---------+---------+---------+---------|
X *
X * The file contains one entry point:
X *
X *   graphics_task:	main entry when system is brought up
X *
X */
X
X#include "kernel.h"
X#include <minix/callnr.h>
X#include <minix/com.h>
X#include <minix/graph_msg.h>
X#include "graph_dev.h"
X
X
XPRIVATE GR_BOOL inited;		/* TRUE if graphics mode is inited */
XPRIVATE GR_FUNC readfunc;	/* function for reading */
XPRIVATE char buf[GR_MAX_SIZEOF_MSG];	/* drawing commands */
XPRIVATE phys_bytes buf_phys;	/* physical address of buffer */
XPRIVATE message mess;		/* message buffer */
X
X
X/* The following union holds all read request messages.
X * All of these messages must be of a fixed size.
X */
XPRIVATE union {
X  GR_MSG_HEADER head;		/* header */
X  GR_MSG_READAREA8 readarea8;	/* read area (8 bit colors) */
X  GR_MSG_GETSCREENINFO getscreeninfo;	/* get screen config info */
X  GR_MSG_GETFONTINFO getfontinfo;	/* get font info */
X} readdata;
X
X
X
XFORWARD void do_init();
XFORWARD void do_term();
XFORWARD void do_points();
XFORWARD void do_lines();
XFORWARD void do_rects();
XFORWARD void do_ellips();
XFORWARD void do_setforeground();
XFORWARD void do_setbackground();
XFORWARD void do_setusebackground();
XFORWARD void do_setmode();
XFORWARD void do_area8();
XFORWARD void do_bitmap();
XFORWARD void do_setcliprects();
XFORWARD void do_setcursor();
XFORWARD void do_movecursor();
XFORWARD void do_copyarea();
XFORWARD void do_text();
XFORWARD void do_poly();
X
XFORWARD int do_readarea8();
XFORWARD int do_getscreeninfo();
XFORWARD int do_getfontinfo();
X
XFORWARD int do_read();
XFORWARD int do_write();
X
X
X/*===========================================================================*
X *				graphics_task				     *
X *===========================================================================*/
XPUBLIC void graphics_task()
X{
X/* Main program of the memory task. */
X
X  int r, caller, proc_nr;
X
X  /* Initialize this task. */
X  buf_phys = umap(proc_ptr, D, buf, sizeof(buf));
X  inited = GR_FALSE;
X
X  /* Here is the main loop of the graphics task.  It waits for a
X   * message, carries it out, and sends a reply.
X   */
X  while (TRUE) {
X	/* First wait for a request to read or write. */
X	receive(ANY, &mess);
X
X	if (mess.m_source < 0)
X		panic("Graphics task got message from ", mess.m_source);
X	caller = mess.m_source;
X	proc_nr = mess.PROC_NR;
X
X	/* Now carry out the work.  It depends on the opcode. */
X	switch (mess.m_type) {
X	    case DISK_READ:	r = do_read(&mess);	break;
X	    case DISK_WRITE:	r = do_write(&mess);	break;
X	    default:	r = EINVAL;	break;
X	}
X
X	/* Finally, prepare and send the reply message. */
X	mess.m_type = TASK_REPLY;
X	mess.REP_PROC_NR = proc_nr;
X	mess.REP_STATUS = r;
X	send(caller, &mess);
X  }
X}
X
X
X/*===========================================================================*
X *				do_write				     *
X *===========================================================================*/
XPRIVATE int do_write(m_ptr)
Xregister message *m_ptr;	/* pointer to the newly arrived message */
X{
X  int cc;
X  int r;
X  PRIVATE phys_bytes user_phys;	/* physical address of user buf */
X
X  /* Make sure write count is between defined minimum and maximum sizes. */
X  cc = m_ptr->COUNT;
X  if ((cc < sizeof(GR_MSG_HEADER)) || (cc > GR_MAX_SIZEOF_MSG))
X	return EINVAL;
X
X  /* Validate and return physical address of user buffer */
X  user_phys = numap(m_ptr->PROC_NR, (vir_bytes) m_ptr->ADDRESS, (vir_bytes) cc);
X  if (user_phys == 0) return E_BAD_ADDR;
X
X  /* Read in the complete message */
X  phys_copy(user_phys, buf_phys, (phys_bytes) cc);
X
X  /* Execute the commands in it */
X  r = domessage(buf, cc);
X  if (r) return r;
X  return cc;
X}
X
X
X/*===========================================================================*
X *				do_read					     *
X *===========================================================================*/
XPRIVATE int do_read(m_ptr)
Xregister message *m_ptr;	/* pointer to the newly arrived message */
X{
X  int cc;
X  PRIVATE phys_bytes user_phys;	/* physical address of user buf */
X
X  if (!inited) return EIO;
X
X  /* Make sure write count is between defined minimum and maximum sizes. */
X  cc = m_ptr->COUNT;
X  if ((cc < 0) || (cc > GR_MAX_SIZEOF_MSG)) return EINVAL;
X
X  /* Validate and return physical address of user buffer */
X  user_phys = numap(m_ptr->PROC_NR, (vir_bytes) m_ptr->ADDRESS, (vir_bytes) cc);
X  if (user_phys == 0) return E_BAD_ADDR;
X
X  switch (readdata.head.func) {
X      case GR_FUNC_READAREA8:
X	cc = do_readarea8(&readdata.readarea8, buf, cc);
X	break;
X
X      case GR_FUNC_GETSCREENINFO:
X	cc = do_getscreeninfo(&readdata.getscreeninfo, buf, cc);
X	break;
X
X      case GR_FUNC_GETFONTINFO:
X	cc = do_getfontinfo(&readdata.getfontinfo, buf, cc);
X	break;
X
X      default:	cc = ENXIO;	break;
X  }
X
X  readdata.head.func = GR_FUNC_NOP;
X  if (cc <= 0) return cc;
X
X  /* Return the complete message to the user */
X  phys_copy(buf_phys, user_phys, (phys_bytes) cc);
X
X  return cc;
X}
X
X
X/*===========================================================================*
X *				do_readarea8				     *
X *===========================================================================*/
XPRIVATE int do_readarea8(mp, buf, cc)
XGR_MSG_READAREA8 *mp;		/* read request message */
Xchar *buf;			/* buffer address for result */
Xint cc;				/* buffer size for result */
X{
X/* Read a rectangular array of pixel values from the screen. */
X  GR_COLOR8 *color;
X  GR_COORD row;
X  GR_COORD col;
X
X  if ((mp->width <= 0) || (mp->width > cc) || (mp->height <= 0) ||
X      (mp->height > cc))
X	return EINVAL;
X
X  if (((long) mp->width * (long) mp->height * sizeof(GR_COLOR8)) > cc)
X	return EINVAL;
X
X  color = (GR_COLOR8 *) buf;
X  for (row = 0; row < mp->height; row++)
X	for (col = 0; col < mp->width; col++)
X		*color++ = (*gr_dev.readpoint) (mp->x + col, mp->y + row);
X
X  return mp->width * mp->height * sizeof(GR_COLOR8);
X}
X
X
X/*===========================================================================*
X *				do_getscreeninfo			     *
X *===========================================================================*/
XPRIVATE int do_getscreeninfo(mp, buf, cc)
XGR_MSG_GETSCREENINFO *mp;	/* read request message */
Xchar *buf;			/* buffer address for result */
Xint cc;				/* buffer size for result */
X{
X/* Get screen configuration information. */
X  if (cc < sizeof(GR_SCREEN_INFO)) return EINVAL;
X  (*gr_dev.getscreeninfo) ((GR_SCREEN_INFO *) buf);
X  return sizeof(GR_SCREEN_INFO);
X}
X
X
X/*===========================================================================*
X *				do_getfontinfo				     *
X *===========================================================================*/
XPRIVATE int do_getfontinfo(mp, buf, cc)
XGR_MSG_GETFONTINFO *mp;		/* read request message */
Xchar *buf;			/* buffer address for result */
Xint cc;				/* buffer size for result */
X{
X/* Get font information. */
X  if (cc < sizeof(GR_FONT_INFO)) return EINVAL;
X  (*gr_dev.getfontinfo) (mp->font, (GR_FONT_INFO *) buf);
X  return sizeof(GR_FONT_INFO);
X}
X
X
X/*===========================================================================*
X *				domessage				     *
X *===========================================================================*/
XPRIVATE int domessage(msg, cc)
Xchar *msg;			/* message bufer */
Xint cc;				/* number of characters available */
X{
X/* Execute all graphics messages encoded in a bufferful of data.
X * Returns error if an unknown or invalid message was encountered.
X * In this case, remaining messages in the buffer were ignored.
X */
X  GR_COUNT count;
X  long size;
X  GR_MSG_HEADER *mp;
X
X  while (cc > 0) {
X	if (cc < sizeof(GR_MSG_HEADER)) return EIO;
X	mp = (GR_MSG_HEADER *) msg;
X	count = mp->count;
X	if ((count < 0) || (count > GR_MAX_COUNT)) return EIO;
X	if (!inited && (mp->func != GR_FUNC_INIT)) return EIO;
X
X	/* Verify the current function, and calculate the size of the
X	 * message structure for that function.
X	 */
X	switch (mp->func) {
X	    case GR_FUNC_INIT:
X		size = sizeof(GR_MSG_INIT);
X		break;
X	    case GR_FUNC_TERM:
X		size = sizeof(GR_MSG_TERM);
X		break;
X	    case GR_FUNC_NOP:
X		size = sizeof(GR_MSG_HEADER);
X		break;
X	    case GR_FUNC_DRAWPOINTS:
X		size = GR_SIZEOF_MSG_POINTS(count);
X		break;
X	    case GR_FUNC_DRAWLINES:
X		size = GR_SIZEOF_MSG_LINES(count);
X		break;
X	    case GR_FUNC_DRAWRECTS:
X		size = GR_SIZEOF_MSG_RECTS(count);
X		break;
X	    case GR_FUNC_DRAWELLIPS:
X		size = GR_SIZEOF_MSG_ELLIPS(count);
X		break;
X	    case GR_FUNC_SETMODE:
X		size = sizeof(GR_MSG_SETMODE);
X		break;
X	    case GR_FUNC_SETFOREGROUND:
X		size = sizeof(GR_MSG_SETFOREGROUND);
X		break;
X	    case GR_FUNC_SETBACKGROUND:
X		size = sizeof(GR_MSG_SETBACKGROUND);
X		break;
X	    case GR_FUNC_SETUSEBACKGROUND:
X		size = sizeof(GR_MSG_SETUSEBACKGROUND);
X		break;
X	    case GR_FUNC_DRAWAREA8:
X		size = GR_SIZEOF_MSG_AREA8(count);
X		break;
X	    case GR_FUNC_DRAWBITMAP:
X		size = GR_SIZEOF_MSG_BITMAP(count);
X		break;
X	    case GR_FUNC_SETCLIPRECTS:
X		size = GR_SIZEOF_MSG_SETCLIPRECTS(count);
X		break;
X	    case GR_FUNC_DRAWPOLY:
X		size = GR_SIZEOF_MSG_POLY(count);
X		break;
X	    case GR_FUNC_DRAWTEXT:
X		size = GR_SIZEOF_MSG_TEXT(count);
X		break;
X	    case GR_FUNC_SETCURSOR:
X		size = GR_SIZEOF_MSG_SETCURSOR(count);
X		break;
X	    case GR_FUNC_MOVECURSOR:
X		size = sizeof(GR_MSG_MOVECURSOR);
X		break;
X	    case GR_FUNC_COPYAREA:
X		size = sizeof(GR_MSG_COPYAREA);
X		break;
X	    case GR_FUNC_READAREA8:
X		size = sizeof(GR_MSG_READAREA8);
X		break;
X	    case GR_FUNC_GETSCREENINFO:
X		size = sizeof(GR_MSG_GETSCREENINFO);
X		break;
X	    case GR_FUNC_GETFONTINFO:
X		size = sizeof(GR_MSG_GETFONTINFO);
X		break;
X	    default:	return ENXIO;
X	}
X
X	/* Make sure that the complete message structure for the
X	 * current function fits in the remainder of the buffer.
X	 */
X	if ((size < sizeof(GR_MSG_HEADER)) || (size > cc)) return EIO;
X
X	/* OK, now call the routine to handle the function. */
X	switch (mp->func) {
X	    case GR_FUNC_INIT:
X		do_init((GR_MSG_INIT *) mp);
X		if (!inited) return EIO;
X		break;
X	    case GR_FUNC_TERM:
X		do_term((GR_MSG_TERM *) mp);
X		break;
X	    case GR_FUNC_DRAWPOINTS:
X		do_points((GR_MSG_POINTS *) mp);
X		break;
X	    case GR_FUNC_DRAWLINES:
X		do_lines((GR_MSG_LINES *) mp);
X		break;
X	    case GR_FUNC_DRAWRECTS:
X		do_rects((GR_MSG_RECTS *) mp);
X		break;
X	    case GR_FUNC_DRAWELLIPS:
X		do_ellips((GR_MSG_ELLIPS *) mp);
X		break;
X	    case GR_FUNC_SETMODE:
X		do_setmode((GR_MSG_SETMODE *) mp);
X		break;
X	    case GR_FUNC_SETFOREGROUND:
X		do_setforeground((GR_MSG_SETFOREGROUND *) mp);
X		break;
X	    case GR_FUNC_SETBACKGROUND:
X		do_setbackground((GR_MSG_SETBACKGROUND *) mp);
X		break;
X	    case GR_FUNC_SETUSEBACKGROUND:
X		do_setusebackground((GR_MSG_SETUSEBACKGROUND *) mp);
X		break;
X	    case GR_FUNC_DRAWAREA8:
X		do_area8((GR_MSG_AREA8 *) mp);
X		break;
X	    case GR_FUNC_DRAWBITMAP:
X		do_bitmap((GR_MSG_BITMAP *) mp);
X		break;
X	    case GR_FUNC_SETCLIPRECTS:
X		do_setcliprects((GR_MSG_SETCLIPRECTS *) mp);
X		break;
X	    case GR_FUNC_DRAWPOLY:
X		do_poly((GR_MSG_POLY *) mp);
X		break;
X	    case GR_FUNC_DRAWTEXT:
X		do_text((GR_MSG_TEXT *) mp);
X		break;
X	    case GR_FUNC_SETCURSOR:
X		do_setcursor((GR_MSG_SETCURSOR *) mp);
X		break;
X	    case GR_FUNC_MOVECURSOR:
X		do_movecursor((GR_MSG_MOVECURSOR *) mp);
X		break;
X	    case GR_FUNC_COPYAREA:
X		do_copyarea((GR_MSG_COPYAREA *) mp);
X		break;
X	    case GR_FUNC_READAREA8:
X		if (cc != size) return EIO;
X		readdata.readarea8 = *((GR_MSG_READAREA8 *) mp);
X		break;
X	    case GR_FUNC_GETSCREENINFO:
X		if (cc != size) return EIO;
X		readdata.getscreeninfo =
X			*((GR_MSG_GETSCREENINFO *) mp);
X		break;
X	    case GR_FUNC_GETFONTINFO:
X		if (cc != size) return EIO;
X		readdata.getfontinfo =
X			*((GR_MSG_GETFONTINFO *) mp);
X		break;
X	}
X
X	/* Restore the cursor if it was removed because of the
X	 * graphics operation.
X	 */
X	(*gr_dev.fixcursor) ();
X
X	/* Advance to the next free location in the buffer. */
X	msg += size;
X	cc -= size;
X  }
X  return 0;
X}
X
X
X/*===========================================================================*
X *				do_init					     *
X *===========================================================================*/
XPRIVATE void do_init(ip)
XGR_MSG_INIT *ip;
X{
X/* Initialize the graphics device */
X  if (ip->head.flags || ip->head.count || (ip->magic != GR_INIT_MAGIC))
X	return;
X  if ((*gr_dev.init) (ip->rows, ip->cols, ip->colors)) return;
X  clipinit(0, 0);
X  gen_initcursor();
X  gr_foreground = gr_dev.white;
X  gr_background = gr_dev.black;
X  gr_usebg = GR_TRUE;
X  readdata.head.func = GR_FUNC_NOP;
X  inited = GR_TRUE;
X}
X
X
X/*===========================================================================*
X *				do_term					     *
X *===========================================================================*/
XPRIVATE void do_term(tp)
XGR_MSG_TERM *tp;
X{
X/* Terminate graphics mode. */
X  (*gr_dev.term) ();
X  inited = GR_FALSE;
X}
X
X
X/*===========================================================================*
X *				do_points				     *
X *===========================================================================*/
XPRIVATE void do_points(mp)
XGR_MSG_POINTS *mp;
X{
X/* Process a list of points to be drawn. */
X  GR_COUNT count;
X  GR_POINT *pp;
X
X  pp = mp->points;
X  count = mp->head.count;
X  while (count-- > 0) {
X	drawpoint(pp->x, pp->y);
X	pp++;
X  }
X}
X
X
X/*===========================================================================*
X *				do_lines				     *
X *===========================================================================*/
XPRIVATE void do_lines(mp)
XGR_MSG_LINES *mp;
X{
X/* Process a list of lines to be drawn. */
X  GR_COUNT count;
X  GR_LINE *lp;
X
X  lp = mp->lines;
X  count = mp->head.count;
X  while (count-- > 0) {
X	drawline(lp->x1, lp->y1, lp->x2, lp->y2);
X	(*gr_dev.fixcursor) ();
X	lp++;
X  }
X}
X
X
X/*===========================================================================*
X *				do_rects				     *
X *===========================================================================*/
XPRIVATE void do_rects(mp)
XGR_MSG_RECTS *mp;
X{
X/* Process a list of rectangles to be drawn.
X * The rectangles can be filled or not depending on the flags.
X */
X  GR_COUNT count;
X  GR_RECT *rp;
X
X  count = mp->head.count;
X  for (rp = mp->rects; count-- > 0; rp++) {
X	if ((rp->width <= 0) || (rp->height <= 0)) continue;
X	if ((mp->head.flags & GR_FLAG_FILLAREA) == 0)
X		drawrect(rp->x, rp->y, rp->width, rp->height);
X	else
X		fillrect(rp->x, rp->y, rp->x + rp->width - 1,
X			 rp->y + rp->height - 1);
X	(*gr_dev.fixcursor) ();
X  }
X}
X
X
X/*===========================================================================*
X *				do_ellips				     *
X *===========================================================================*/
XPRIVATE void do_ellips(mp)
XGR_MSG_ELLIPS *mp;
X{
X/* Process a list of ellipses (or circles) to be drawn.
X * The ellipses can be filled or not depending on the flags.
X */
X  GR_COUNT count;
X  GR_ELLIPSE *ep;
X
X  ep = mp->ellips;
X  count = mp->head.count;
X  while (count-- > 0) {
X	if (mp->head.flags & GR_FLAG_FILLAREA)
X		fillellipse(ep->x, ep->y, ep->rx, ep->ry);
X	else
X		drawellipse(ep->x, ep->y, ep->rx, ep->ry);
X	(*gr_dev.fixcursor) ();
X	ep++;
X  }
X}
X
X
X/*===========================================================================*
X *				do_setmode				     *
X *===========================================================================*/
XPRIVATE void do_setmode(mp)
XGR_MSG_SETMODE *mp;
X{
X/* Process a set drawing mode message.
X * This is one of SET, OR, AND, or XOR.
X */
X  if (mp->mode > GR_MAX_MODE) {
X	gr_error = GR_TRUE;
X	return;
X  }
X  if (gr_mode != mp->mode) {
X	(*gr_dev.setmode) (mp->mode);
X	gr_mode = mp->mode;
X  }
X}
X
X
X/*===========================================================================*
X *				do_setforeground			     *
X *===========================================================================*/
XPRIVATE void do_setforeground(mp)
XGR_MSG_SETFOREGROUND *mp;
X{
X/* Process a set foreground message. */
X  gr_foreground = mp->foreground;
X}
X
X
X/*===========================================================================*
X *				do_setbackground			     *
X *===========================================================================*/
XPRIVATE void do_setbackground(mp)
XGR_MSG_SETBACKGROUND *mp;
X{
X/* Process a set background message. */
X  gr_background = mp->background;
X}
X
X
X/*===========================================================================*
X *				do_setusebackground			     *
X *===========================================================================*/
XPRIVATE void do_setusebackground(mp)
XGR_MSG_SETUSEBACKGROUND *mp;
X{
X/* Process a set use background message. */
X  gr_usebg = mp->flag;
X}
X
X
X/*===========================================================================*
X *				do_area8				     *
X *===========================================================================*/
XPRIVATE void do_area8(mp)
XGR_MSG_AREA8 *mp;
X{
X/* Process a draw 8 bit color values message. */
X  drawarea8(mp->x, mp->y, mp->width, mp->height, mp->colors);
X}
X
X
X/*===========================================================================*
X *				do_bitmap				     *
X *===========================================================================*/
XPRIVATE void do_bitmap(mp)
XGR_MSG_BITMAP *mp;
X{
X/* Process a draw bitmap message. */
X  drawbitmap(mp->x, mp->y, mp->width, mp->height, mp->bitmaps);
X}
X
X
X/*===========================================================================*
X *				do_setcliprects				     *
X *===========================================================================*/
XPRIVATE void do_setcliprects(mp)
XGR_MSG_SETCLIPRECTS *mp;
X{
X/* Process a set clip rectangles message. */
X  if ((mp->head.count < 0) || (mp->head.count > GR_MAX_CLIPRECTS)) {
X	gr_error = GR_TRUE;
X	return;
X  }
X  clipinit(mp->head.count, mp->cliprects);
X}
X
X
X/*===========================================================================*
X *				do_poly					     *
X *===========================================================================*/
XPRIVATE void do_poly(pp)
XGR_MSG_POLY *pp;
X{
X/* Process a draw polygon message. */
X  if (pp->head.flags & GR_FLAG_FILLAREA)
X	fillpoly(pp->points, pp->head.count);
X  else
X	drawpoly(pp->points, pp->head.count);
X}
X
X
X/*===========================================================================*
X *				do_text					     *
X *===========================================================================*/
XPRIVATE void do_text(cp)
XGR_MSG_TEXT *cp;
X{
X/* Process a draw text string message. */
X  drawtext(cp->x, cp->y, cp->chars, cp->head.count);
X}
X
X
X/*===========================================================================*
X *				do_setcursor				     *
X *===========================================================================*/
XPRIVATE void do_setcursor(cp)
XGR_MSG_SETCURSOR *cp;
X{
X/* Process a set cursor message. */
X  (*gr_dev.setcursor) (cp->width, cp->height, cp->foreground,
X		     cp->background, cp->bitmaps,
X		     &cp->bitmaps[cp->head.count / 2]);
X}
X
X
X/*===========================================================================*
X *				do_movecursor				     *
X *===========================================================================*/
XPRIVATE void do_movecursor(mp)
XGR_MSG_MOVECURSOR *mp;
X{
X/* Process a move cursor message. */
X  (*gr_dev.movecursor) (mp->x, mp->y);
X}
X
X
X/*===========================================================================*
X *				do_copyarea				     *
X *===========================================================================*/
XPRIVATE void do_copyarea(mp)
XGR_MSG_COPYAREA *mp;
X{
X/* Process a copy area message. */
X  copyarea(mp->sx, mp->sy, mp->width, mp->height, mp->dx, mp->dy);
X}
X
X/* END CODE */
END_OF_FILE
if test 19967 -ne `wc -c <'mini-x/kernel/graphics.c'`; then
    echo shar: \"'mini-x/kernel/graphics.c'\" unpacked with wrong size!
fi
# end of 'mini-x/kernel/graphics.c'
fi
if test -f 'mini-x/server/serv_dev.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'mini-x/server/serv_dev.c'\"
else
echo shar: Extracting \"'mini-x/server/serv_dev.c'\" \(21102 characters\)
sed "s/^X//" >'mini-x/server/serv_dev.c' <<'END_OF_FILE'
X/*
X * Copyright (c) 1991 David I. Bell
X * Permission is granted to use, distribute, or modify this source,
X * provided that this copyright notice remains intact.
X *
X * Routines to package up drawing messages to be sent to the device driver.
X * These routines are the low level graphics driver routines, and should
X * not be called by clients.  Clients must call the GrXXXX routines instead
X * of these GdXXXX routines (or the GsXXXX routines too).
X */
X#include "graph_serv.h"
X#include <minix/graph_msg.h>
X#include <fcntl.h>
X
X
X/*
X * The device name for the graphics device.
X */
X#define	DEVICENAME	"/dev/graphics"
X
X
X/*
X * The following definition is useful for debugging.
X * Making it nonzero disables actual writing to the graphics device,
X * thus preserving the screen and allowing you to see printfs that
X * your program is doing.
X */
X#define	DEBUG	0
X
X#define	NULL	0
X
X
Xstatic char 	*lastmsg;		/* most recent message */
Xstatic char	*newmsg;		/* place to put new message */
Xstatic int	msgavail;		/* space left in current message */
Xstatic GR_BOOL	error;			/* error occurred from functions */
Xstatic int	fd;			/* file descriptor for device */
Xstatic char	msgbuf[GR_MAX_SIZEOF_MSG];	/* message buffer being filled */
X
X
X/*
X * Prepare the graphics device for use, and initialize the message buffer.
X * The parameters are the requested number of rows, columns, and colors
X * to be used.  If they are nonzero, then an error occurs if the requested
X * configuration cannot be met by the hardware.  If any parameter value is
X * zero, then it is a "free" parameter.   The device driver can then select
X * the best value for the parameter consistent with the other parameters.
X * This best value is usually the one giving the highest possible resolution.
X * Returns zero if successful, -1 on failure.
X */
Xint
XGdOpenScreen(rows, cols, colors)
X	GR_SIZE	rows;			/* desired number of rows */
X	GR_SIZE	cols;			/* desired number of columns */
X	long	colors;			/* desired number of colors */
X{
X	GR_MSG_INIT	init;		/* initialization message */
X
X#if !DEBUG
X	fd = open(DEVICENAME, O_RDWR);
X	if (fd < 0)
X		return -1;
X#endif
X
X	lastmsg = msgbuf;
X	newmsg = msgbuf;
X	msgavail = sizeof(msgbuf);
X	((GR_MSG_HEADER *) lastmsg)->func = GR_FUNC_NOP;
X
X	/*
X	 * Send the initial configuration message requesting the
X	 * desired parameters of the display.
X	 */
X	init.head.func = GR_FUNC_INIT;
X	init.head.flags = 0;
X	init.head.count = 0;
X	init.magic = GR_INIT_MAGIC;
X	init.rows = rows;
X	init.cols = cols;
X	init.colors = colors;
X#if !DEBUG
X	if (write(fd, &init, sizeof(init)) != sizeof(init)) {
X		close(fd);
X		fd = -1;
X		return -1;
X	}
X#endif
X	error = GR_FALSE;
X	return 0;
X}
X
X
X/*
X * Close the graphics device, first flushing any waiting messages.
X */
Xvoid
XGdCloseScreen()
X{
X	if (fd <= 0)
X		return;
X	GdTextMode();
X	GdFlush();
X	if (close(fd) < 0)
X		error = GR_TRUE;
X	fd = -1;
X}
X
X
X/*
X * Check to see if there was a device error.
X * Clears the error if indicated.
X */
XGR_BOOL
XGdCheckError(clearflag)
X	GR_BOOL		clearflag;	/* TRUE to clear error */
X{
X	if (!error)
X		return GR_FALSE;
X	if (clearflag)
X		error = GR_FALSE;
X	return GR_TRUE;
X}
X
X
X/*
X * Flush the message buffer of any messages it may contain.
X */
Xvoid
XGdFlush()
X{
X	int	cc;
X
X	if (error)
X		return;
X
X	cc = sizeof(msgbuf) - msgavail;
X	if (cc <= 0)
X		return;
X#if !DEBUG
X	if (write(fd, msgbuf, cc) != cc)
X		error = GR_TRUE;
X#endif
X	lastmsg = msgbuf;
X	newmsg = msgbuf;
X	msgavail = sizeof(msgbuf);
X	((GR_MSG_HEADER *) lastmsg)->func = GR_FUNC_NOP;
X}
X
X
X/*
X * Allocate space for a new message of the specified size,
X * flushing the buffer if necessary to make room.  Returns
X * a pointer to the header of the new message.
X */
Xstatic GR_MSG_HEADER *
XGdNewMessage(size)
X	GR_SIZE		size;		/* required size of message */
X{
X	GR_MSG_HEADER *	mp;		/* message header */
X
X	if (msgavail < size)
X		GdFlush();
X
X	mp = (GR_MSG_HEADER *) newmsg;
X	mp->func = GR_FUNC_NOP;
X	mp->flags = 0;
X	mp->count = 1;
X	lastmsg = newmsg;
X	newmsg += size;
X	msgavail -= size;
X	return mp;
X}
X
X
X/*
X * Attempt to grow an existing message by the specified size.
X * In order to grow, the last message must be the indicated function,
X * its flags must match the indicated flags, and the available size
X * must me at least as large as the indicated size.  If the message
X * cannot be grown, then a new message is allocated with the specified
X * minimum size.  The function code, flags, and count fields of the
X * message are initialized here.
X */
Xstatic GR_MSG_HEADER *
XGdGrowMessage(func, flags, origsize, growsize)
X	GR_FUNC		func;		/* required function */
X	GR_FLAGS	flags;		/* required flags */
X	GR_SIZE		origsize;	/* space for original message */
X	GR_SIZE		growsize;	/* required new space */
X{
X	GR_MSG_HEADER *	mp;		/* message header */
X
X	mp = (GR_MSG_HEADER *) lastmsg;
X	if (growsize && (mp->func == func) && (mp->flags == flags) &&
X		(growsize <= msgavail) && (mp->count < GR_MAX_COUNT))
X	{
X		newmsg += growsize;
X		msgavail -= growsize;
X		mp->count++;
X		return mp;
X	}
X
X	mp = GdNewMessage(origsize);
X	mp->func = func;
X	mp->flags = flags;
X	return mp;
X}
X
X
X/*
X * Terminate graphics mode, but keep the graphics device open.
X */
Xvoid
XGdTextMode()
X{
X	GR_MSG_TERM	*mp;
X
X	mp = (GR_MSG_TERM *) GdNewMessage(sizeof(GR_MSG_TERM));
X	mp->head.func = GR_FUNC_TERM;
X}
X
X
X/*
X * Return information about the screen for clients to use.
X * This does a write to the device, then a read to get the results.
X */
Xvoid
XGdGetScreenInfo(sip)
X	GR_SCREEN_INFO	*sip;		/* pointer to screen info */
X{
X	GR_MSG_GETSCREENINFO	*mp;	/* message to send */
X	int			cc;	/* number of bytes read */
X
X	mp = (GR_MSG_GETSCREENINFO *)
X		GdNewMessage(sizeof(GR_MSG_GETSCREENINFO));
X	mp->head.func = GR_FUNC_GETSCREENINFO;
X	GsFlush();
X	cc = read(fd, (char *) sip, sizeof(GR_SCREEN_INFO));
X	if (cc == sizeof(GR_SCREEN_INFO))
X		return;
X
X	/*
X	 * Read failed, give an error and some dummy results.
X	 */
X	error = GR_TRUE;
X	sip->rows = 1;
X	sip->cols = 1;
X	sip->xdpcm = 1;
X	sip->ydpcm = 1;
X	sip->maxcolor = 1;
X	sip->black = 0;
X	sip->white = 1;
X	sip->buttons = 0;
X	sip->modifiers = 0;
X	sip->fonts = 1;
X}
X
X
X/*
X * Read information about a specified font.
X */
Xvoid
XGdGetFontInfo(font, fip)
X	GR_FONT		font;		/* font number to get info about */
X	GR_FONT_INFO	*fip;		/* location to read info into */
X{
X	GR_MSG_GETFONTINFO	*mp;	/* message to send */
X	int			cc;	/* number of bytes read */
X
X	mp = (GR_MSG_GETFONTINFO *)
X		GdNewMessage(sizeof(GR_MSG_GETFONTINFO));
X	mp->head.func = GR_FUNC_GETFONTINFO;
X	mp->font = font;
X
X	GsFlush();
X
X	cc = read(fd, (char *) fip, sizeof(GR_FONT_INFO));
X	if (cc == sizeof(GR_FONT_INFO))
X		return;
X	fip->height = 1;
X	fip->maxwidth = 1;
X	fip->baseline = 0;
X	fip->fixed = GR_TRUE;
X}
X
X
X/*
X * Set an array of clip rectangles for future drawing actions.
X * Each pixel will be drawn only if lies in one or more of the specified
X * clip rectangles.  As a special case, specifying no rectangles implies
X * clipping is for the complete screen.
X */
Xvoid
XGdSetClipRects(count, cliprects)
X	GR_COUNT	count;		/* number of rectangles */
X	GR_RECT		*cliprects;	/* table of rectangles */
X{
X	GR_MSG_SETCLIPRECTS	*mp;
X	long			size;
X
X	/*
X	 * Make sure there is room in the buffer for the new message.
X	 */
X	size = GR_SIZEOF_MSG_SETCLIPRECTS(count);
X	if ((count < 0) || (count > GR_MAX_COUNT) || (count > GR_MAX_CLIPRECTS)
X		|| (size > GR_MAX_SIZEOF_MSG))
X	{
X		error = GR_TRUE;
X		return;
X	}
X
X	mp = (GR_MSG_SETCLIPRECTS *) GdNewMessage((GR_SIZE) size);
X	mp->head.func = GR_FUNC_SETCLIPRECTS;
X	mp->head.count = count;
X	if (count > 0) {
X		memcpy((char *) mp->cliprects, (char *) cliprects,
X			(int) (count * sizeof(GR_RECT)));
X	}
X}
X
X
X/*
X * Set the cursor size and bitmaps.
X */
Xvoid
XGdSetCursor(width, height, foreground, background, fgbitmap, bgbitmap)
X	GR_SIZE		width;		/* width of cursor */
X	GR_SIZE		height;		/* height of cursor */
X	GR_COLOR	foreground;	/* foreground color of cursor */
X	GR_COLOR	background;	/* background color of cursor */
X	GR_BITMAP	*fgbitmap;	/* foreground bitmap */
X	GR_BITMAP	*bgbitmap;	/* background bitmap */
X{
X	GR_MSG_SETCURSOR	*mp;
X	long			count;
X	long			size;
X	int			bytes;
X
X	/*
X	 * Make sure there is room in the buffer for the new message,
X	 * and that the size of the cursor is not too large.
X	 */
X	count = BITMAP_WORDS((long) width) * ((long) height) * 2;
X	size = GR_SIZEOF_MSG_SETCURSOR(count);
X	if ((width <= 0) || (height <= 0) || (width > GR_MAX_CURSOR_SIZE) ||
X		(height > GR_MAX_CURSOR_SIZE) || (count > GR_MAX_COUNT) ||
X		(size > GR_MAX_SIZEOF_MSG))
X	{
X		error = GR_TRUE;
X		return;
X	}
X
X	mp = (GR_MSG_SETCURSOR *) GdNewMessage((GR_SIZE) size);
X	mp->head.func = GR_FUNC_SETCURSOR;
X	mp->head.count = count;
X	mp->width = width;
X	mp->height = height;
X	mp->foreground = foreground;
X	mp->background = background;
X	bytes = count * sizeof(GR_BITMAP) / 2;
X	if (bytes > 0) {
X		memcpy((char *) mp->bitmaps, (char *) fgbitmap, bytes);
X		memcpy((char *) &mp->bitmaps[count / 2], (char *) bgbitmap,
X			bytes);
X	}
X}
X
X
X/*
X * Set the cursor position.
X */
Xvoid
XGdMoveCursor(x, y)
X	GR_COORD	x;		/* new x position of cursor */
X	GR_COORD	y;		/* new y position of cursor */
X{
X	GR_MSG_MOVECURSOR	*mp;
X
X	mp = (GR_MSG_MOVECURSOR *) GdNewMessage(sizeof(GR_MSG_MOVECURSOR));
X	mp->head.func = GR_FUNC_MOVECURSOR;
X	mp->x = x;
X	mp->y = y;
X}
X
X
X/*
X * Set whether or not the background is used for drawing pixmaps and text.
X */
Xvoid
XGdSetUseBackground(flag)
X	GR_BOOL		flag;		/* TRUE if background is drawn */
X{
X	GR_MSG_SETUSEBACKGROUND	*mp;
X
X	/*
X	 * See if the previous message was a set usebackground function,
X	 * and if so, overwrite that message.
X	 */
X	mp = (GR_MSG_SETUSEBACKGROUND *) lastmsg;
X	if (mp->head.func == GR_FUNC_SETUSEBACKGROUND) {
X		mp->flag = flag;
X		return;
X	}
X
X	mp = (GR_MSG_SETUSEBACKGROUND *)
X		GdNewMessage(sizeof(GR_MSG_SETUSEBACKGROUND));
X	mp->head.func = GR_FUNC_SETUSEBACKGROUND;
X	mp->flag = flag;
X}
X
X
X/*
X * Set the drawing mode for future calls.
X */
Xvoid
XGdSetMode(mode)
X	GR_MODE		mode;		/* drawing mode */
X{
X	GR_MSG_SETMODE	*mp;
X
X	/*
X	 * See if the previous message was a set mode function, and
X	 * if so, overwrite that message.
X	 */
X	mp = (GR_MSG_SETMODE *) lastmsg;
X	if (mp->head.func == GR_FUNC_SETMODE) {
X		mp->mode = mode;
X		return;
X	}
X
X	mp = (GR_MSG_SETMODE *) GdNewMessage(sizeof(GR_MSG_SETMODE));
X	mp->head.func = GR_FUNC_SETMODE;
X	mp->mode = mode;
X}
X
X
X/*
X * Set the foreground color for future calls.
X */
Xvoid
XGdSetForeground(fg)
X	GR_COLOR	fg;		/* foreground color */
X{
X	GR_MSG_SETFOREGROUND	*mp;
X
X	/*
X	 * See if the previous message was a set foreground function, and
X	 * if so, overwrite that message.
X	 */
X	mp = (GR_MSG_SETFOREGROUND *) lastmsg;
X	if (mp->head.func == GR_FUNC_SETFOREGROUND) {
X		mp->foreground = fg;
X		return;
X	}
X
X	mp = (GR_MSG_SETFOREGROUND *)
X		GdNewMessage(sizeof(GR_MSG_SETFOREGROUND));
X	mp->head.func = GR_FUNC_SETFOREGROUND;
X	mp->foreground = fg;
X}
X
X
X/*
X * Set the background color for future calls.
X */
Xvoid
XGdSetBackground(bg)
X	GR_COLOR	bg;		/* background color */
X{
X	GR_MSG_SETBACKGROUND	*mp;
X
X	/*
X	 * See if the previous message was a set background function, and
X	 * if so, overwrite that message.
X	 */
X	mp = (GR_MSG_SETBACKGROUND *) lastmsg;
X	if (mp->head.func == GR_FUNC_SETBACKGROUND) {
X		mp->background = bg;
X		return;
X	}
X
X	mp = (GR_MSG_SETBACKGROUND *)
X		GdNewMessage(sizeof(GR_MSG_SETBACKGROUND));
X	mp->head.func = GR_FUNC_SETBACKGROUND;
X	mp->background = bg;
X}
X
X
X/*
X * Draw a line using the current clipping region and foreground color.
X */
Xvoid
XGdLine(x1, y1, x2, y2)
X	GR_COORD	x1;
X	GR_COORD	y1;
X	GR_COORD	x2;
X	GR_COORD	y2;
X{
X	GR_MSG_LINES	*mp;
X	GR_LINE		*lp;
X
X	mp = (GR_MSG_LINES *) GdGrowMessage(GR_FUNC_DRAWLINES, 0,
X		sizeof(GR_MSG_LINES), sizeof(GR_LINE));
X
X	lp = &mp->lines[mp->head.count - 1];
X	lp->x1 = x1;
X	lp->y1 = y1;
X	lp->x2 = x2;
X	lp->y2 = y2;
X}
X
X
X/*
X * Draw a rectangle using the current clipping region and foreground color.
X * This just draws in the outline of the rectangle.
X */
Xvoid
XGdRect(x, y, width, height)
X	GR_COORD	x;
X	GR_COORD	y;
X	GR_SIZE		width;
X	GR_SIZE		height;
X{
X	GR_MSG_RECTS	*mp;
X	GR_RECT		*rp;
X
X	mp = (GR_MSG_RECTS *) GdGrowMessage(GR_FUNC_DRAWRECTS, 0,
X		sizeof(GR_MSG_RECTS), sizeof(GR_RECT));
X
X	rp = &mp->rects[mp->head.count - 1];
X	rp->x = x;
X	rp->y = y;
X	rp->width = width;
X	rp->height = height;
X}
X
X
X/*
X * Fill a rectangle using the current clipping region and foreground color.
X * This draws the boarder plus all of its interior.
X */
Xvoid
XGdFillRect(x, y, width, height)
X	GR_COORD	x;
X	GR_COORD	y;
X	GR_SIZE		width;
X	GR_SIZE		height;
X{
X	GR_MSG_RECTS	*mp;
X	GR_RECT		*rp;
X
X	mp = (GR_MSG_RECTS *) GdGrowMessage(GR_FUNC_DRAWRECTS,
X		GR_FLAG_FILLAREA, sizeof(GR_MSG_RECTS), sizeof(GR_RECT));
X
X	rp = &mp->rects[mp->head.count - 1];
X	rp->x = x;
X	rp->y = y;
X	rp->width = width;
X	rp->height = height;
X}
X
X
X/*
X * Draw an ellipse using the current clipping region and foreground color.
X * This just draws in the outline of the ellipse.
X */
Xvoid
XGdEllipse(x, y, rx, ry)
X	GR_COORD	x;
X	GR_COORD	y;
X	GR_SIZE		rx;
X	GR_SIZE		ry;
X{
X	GR_MSG_ELLIPS	*mp;
X	GR_ELLIPSE	*ep;
X
X	mp = (GR_MSG_ELLIPS *) GdGrowMessage(GR_FUNC_DRAWELLIPS, 0,
X		sizeof(GR_MSG_ELLIPS), sizeof(GR_ELLIPSE));
X
X	ep = &mp->ellips[mp->head.count - 1];
X	ep->x = x;
X	ep->y = y;
X	ep->rx = rx;
X	ep->ry = ry;
X}
X
X
X/*
X * Fill an ellipse using the current clipping region and foreground color.
X */
Xvoid
XGdFillEllipse(x, y, rx, ry)
X	GR_COORD	x;
X	GR_COORD	y;
X	GR_SIZE		rx;
X	GR_SIZE		ry;
X{
X	GR_MSG_ELLIPS	*mp;
X	GR_ELLIPSE	*ep;
X
X	mp = (GR_MSG_ELLIPS *) GdGrowMessage(GR_FUNC_DRAWELLIPS,
X		GR_FLAG_FILLAREA, sizeof(GR_MSG_ELLIPS), sizeof(GR_ELLIPSE));
X
X	ep = &mp->ellips[mp->head.count - 1];
X	ep->x = x;
X	ep->y = y;
X	ep->rx = rx;
X	ep->ry = ry;
X}
X
X
X/*
X * Copy a rectangular area from one location on the screen to another.
X * This bypasses clipping.
X */
Xvoid
XGdCopyArea(srcx, srcy, width, height, destx, desty)
X	GR_COORD	srcx;
X	GR_COORD	srcy;
X	GR_SIZE		width;
X	GR_SIZE		height;
X	GR_COORD	destx;
X	GR_COORD	desty;
X{
X	GR_MSG_COPYAREA	*mp;
X
X	mp = (GR_MSG_COPYAREA *) GdNewMessage(sizeof(GR_MSG_COPYAREA));
X	mp->head.func = GR_FUNC_COPYAREA;
X	mp->sx = srcx;
X	mp->sy = srcy;
X	mp->width = width;
X	mp->height = height;
X	mp->dx = destx;
X	mp->dy = desty;
X}
X
X
X/*
X * Draw a rectangular area using the current clipping region and the
X * specified bit map.  This differs from rectangle drawing in that the
X * rectangle is drawn using the foreground color and possibly the background
X * color as determined by the bit map.  Each row of bits is aligned to the
X * next bitmap word boundary (so there is padding at the end of the row).
X * The background bit values are only written if the usebackground flag
X * is set in the GC.
X */
Xvoid
XGdBitmap(x, y, width, height, bitmaptable)
X	GR_COORD	x;
X	GR_COORD	y;
X	GR_SIZE		width;
X	GR_SIZE		height;
X	GR_BITMAP	*bitmaptable;
X{
X	GR_MSG_BITMAP	*mp;
X	long		count;
X	long		size;
X
X	/*
X	 * Make sure there is room in the buffer for the new message,
X	 * and that the size of the rectangle is not too large.
X	 */
X	count = BITMAP_WORDS((long) width) * ((long) height);
X	size = GR_SIZEOF_MSG_BITMAP(count);
X	if ((width <= 0) || (height <= 0) || (width > GR_MAX_COUNT) ||
X		(height > GR_MAX_COUNT) || (count > GR_MAX_COUNT) ||
X		(size > GR_MAX_SIZEOF_MSG))
X	{
X		error = GR_TRUE;
X		return;
X	}
X
X	mp = (GR_MSG_BITMAP *) GdNewMessage((GR_SIZE) size);
X	mp->head.func = GR_FUNC_DRAWBITMAP;
X	mp->head.count = count;
X	mp->x = x;
X	mp->y = y;
X	mp->width = width;
X	mp->height = height;
X	if (count > 0) {
X		memcpy((char *) mp->bitmaps, (char *) bitmaptable,
X			(int) (count * sizeof(GR_BITMAP)));
X	}
X}
X
X
X/*
X * Draw a rectangular area using the current clipping region.
X * This differs from rectangle drawing in that the color values for
X * each pixel in the rectangle is specified.  The color values are
X * restricted to 8 bit values.  The color table is indexed row by row.
X */
Xvoid
XGdArea8(x, y, width, height, colortable)
X	GR_COORD	x;
X	GR_COORD	y;
X	GR_SIZE		width;
X	GR_SIZE		height;
X	GR_COLOR8	*colortable;
X{
X	GR_MSG_AREA8	*mp;
X	GR_COUNT	rows;		/* current number of rows sending */
X	GR_COUNT	maxrows;	/* maximum rows that can be sent */
X	GR_COUNT	count;		/* current count of cells sent */
X	GR_SIZE		rowsize;	/* size needed for each row */
X	GR_SIZE		fullsize;	/* total size required for message */
X	long		minsize;	/* minimum size of message */
X
X	/*
X	 * Make sure that at least one row at a time will fit in the buffer.
X	 */
X	minsize = GR_SIZEOF_MSG_AREA8(width);
X	if ((width <= 0) || (height <= 0) || (width > GR_MAX_COUNT) ||
X		(height > GR_MAX_COUNT) || (minsize > GR_MAX_SIZEOF_MSG))
X	{
X		error = GR_TRUE;
X		return;
X	}
X
X	/*
X	 * Now iterate as necessary fitting as many rows as will fit at
X	 * one time into the buffer.  The number of rows is limited both
X	 * by the maximum message size, and by the maximum cell count.
X	 */
X	rowsize = width * sizeof(GR_COLOR8);
X	maxrows = GR_MAX_COUNT / width;
X
X	while (height > 0) {
X		mp = (GR_MSG_AREA8 *) GdNewMessage((GR_SIZE) minsize);
X		rows = (msgavail / rowsize) + 1;
X		if (rows > height)
X			rows = height;
X		if (rows > maxrows)
X			rows = maxrows;
X		count = rows * width;
X		fullsize = GR_SIZEOF_MSG_AREA8(count);
X		msgavail -= (fullsize - minsize);
X		newmsg += (fullsize - minsize);
X		mp->head.func = GR_FUNC_DRAWAREA8;
X		mp->head.count = count;
X		mp->x = x;
X		mp->y = y;
X		mp->width = width;
X		mp->height = rows;
X		memcpy((char *) mp->colors, (char *) colortable,
X			rows * rowsize);
X		colortable += count;
X		y += rows;
X		height -= rows;
X	}
X}
X
X
X/*
X * Read a rectangular area of the screen.  The color values are restricted
X * to 8 bit values.  The color table is indexed row by row.
X */
Xvoid
XGdReadArea8(x, y, width, height, colortable)
X	GR_COORD	x;
X	GR_COORD	y;
X	GR_SIZE		width;
X	GR_SIZE		height;
X	GR_COLOR8	*colortable;
X{
X	GR_MSG_READAREA8	*mp;
X	GR_COUNT		rows;	/* current number of rows reading */
X	GR_COUNT		maxrows; /* maximum rows to read at once */
X	GR_SIZE			size;	/* size needed for read rows */
X	int			cc;
X
X	/*
X	 * Make sure that at least one row at a time will fit in the buffer.
X	 */
X	if ((width <= 0) || (height <= 0) || (width > GR_MAX_COUNT) ||
X		(height > GR_MAX_COUNT) ||
X		((width * sizeof(GR_COLOR8)) > GR_MAX_SIZEOF_MSG))
X	{
X		error = GR_TRUE;
X		return;
X	}
X
X	/*
X	 * Now iterate as necessary fitting as many rows as will fit at
X	 * one time into the buffer.  The number of rows is limited by the
X	 * maximum message size.
X	 */
X	maxrows = (GR_MAX_SIZEOF_MSG / (width * sizeof(GR_COLOR8)));
X
X	while (height > 0) {
X		mp = (GR_MSG_READAREA8 *) GdNewMessage(sizeof(GR_MSG_READAREA8));
X		rows = height;
X		if (rows > maxrows)
X			rows = maxrows;
X		size = rows * width * sizeof(GR_COLOR8);
X		mp->head.func = GR_FUNC_READAREA8;
X		mp->x = x;
X		mp->y = y;
X		mp->width = width;
X		mp->height = rows;
X
X		GsFlush();
X
X		cc = read(fd, (char *) colortable, (int) size);
X		if (cc != size) {
X			error = GR_TRUE;
X			return;
X		}
X
X		colortable += rows * width;
X		y += rows;
X		height -= rows;
X	}
X}
X
X
X/*
X * Draw a point using the current clipping region and foreground color.
X */
Xvoid
XGdPoint(x, y)
X	GR_COORD	x;
X	GR_COORD	y;
X{
X	GR_MSG_POINTS	*mp;
X	GR_POINT	*pp;
X
X	mp = (GR_MSG_POINTS *) GdGrowMessage(GR_FUNC_DRAWPOINTS, 0,
X		sizeof(GR_MSG_POINTS), sizeof(GR_POINT));
X
X	pp = &mp->points[mp->head.count - 1];
X	pp->x = x;
X	pp->y = y;
X}
X
X
X/*
X * Draw a polygon from the specified list of points.  The polygon is
X * only complete if the first point is repeated at the end.
X */
Xvoid
XGdPoly(count, pointtable)
X	GR_COUNT	count;
X	GR_POINT	*pointtable;
X{
X	GR_MSG_POLY	*mp;
X	long		size;
X
X	/*
X	 * Make sure there is room in the buffer for the new message.
X	 */
X	size = GR_SIZEOF_MSG_POLY(count);
X	if ((count < 0) || (count > GR_MAX_COUNT) ||
X		(size > GR_MAX_SIZEOF_MSG))
X	{
X		error = GR_TRUE;
X		return;
X	}
X
X	mp = (GR_MSG_POLY *) GdNewMessage((GR_SIZE) size);
X	mp->head.func = GR_FUNC_DRAWPOLY;
X	mp->head.count = count;
X	if (count > 0) {
X		memcpy((char *) mp->points, (char *) pointtable,
X			(int) (count * sizeof(GR_POINT)));
X	}
X}
X
X
X/*
X * Draw a filled polygon from the specified list of points.  The last
X * point may be a duplicate of the first point, but this is not required.
X */
Xvoid
XGdFillPoly(count, pointtable)
X	GR_COUNT	count;
X	GR_POINT	*pointtable;
X{
X	GR_MSG_POLY	*mp;
X	long		size;
X
X	/*
X	 * Make sure there is room in the buffer for the new message.
X	 */
X	size = GR_SIZEOF_MSG_POLY(count);
X	if ((count < 0) || (count > GR_MAX_COUNT) ||
X		(size > GR_MAX_SIZEOF_MSG))
X	{
X		error = GR_TRUE;
X		return;
X	}
X
X	mp = (GR_MSG_POLY *) GdNewMessage((GR_SIZE) size);
X	mp->head.func = GR_FUNC_DRAWPOLY;
X	mp->head.flags = GR_FLAG_FILLAREA;
X	mp->head.count = count;
X	if (count > 0) {
X		memcpy((char *) mp->points, (char *) pointtable,
X			(int) (count * sizeof(GR_POINT)));
X	}
X}
X
X
X/*
X * Draw a text string starting at the specified coordinates.
X */
Xvoid
XGdText(x, y, str, count)
X	GR_COORD	x;
X	GR_COORD	y;
X	GR_CHAR		*str;
X	GR_COUNT	count;
X{
X	GR_MSG_TEXT	*mp;
X	long		size;
X
X	/*
X	 * Make sure there is room in the buffer for the new message.
X	 */
X	size = GR_SIZEOF_MSG_TEXT(count);
X	if ((count < 0) || (count > GR_MAX_COUNT) ||
X		(size > GR_MAX_SIZEOF_MSG))
X	{
X		error = GR_TRUE;
X		return;
X	}
X
X	mp = (GR_MSG_TEXT *) GdNewMessage((GR_SIZE) size);
X	mp->head.func = GR_FUNC_DRAWTEXT;
X	mp->head.count = count;
X	mp->x = x;
X	mp->y = y;
X	memcpy((char *) mp->chars, (char *) str, (int) count * sizeof(GR_CHAR));
X}
X
X/* END CODE */
END_OF_FILE
if test 21102 -ne `wc -c <'mini-x/server/serv_dev.c'`; then
    echo shar: \"'mini-x/server/serv_dev.c'\" unpacked with wrong size!
fi
# end of 'mini-x/server/serv_dev.c'
fi
echo shar: End of archive 5 \(of 9\).
cp /dev/null ark5isdone
MISSING=""
for I in 1 2 3 4 5 6 7 8 9 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked all 9 archives.
    rm -f ark[1-9]isdone ark[1-9][0-9]isdone
else
    echo You still need to unpack the following archives:
    echo "        " ${MISSING}
fi
##  End of shell archive.
exit 0

dbell@pdact.pd.necisa.oz.au (David I. Bell) (04/22/91)

#! /bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of archive 6 (of 9)."
# Contents:  mini-x/README mini-x/kernel/graph_main.c
# Wrapped by dbell@elm on Mon Apr 22 11:21:48 1991
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'mini-x/README' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'mini-x/README'\"
else
echo shar: Extracting \"'mini-x/README'\" \(22803 characters\)
sed "s/^X//" >'mini-x/README' <<'END_OF_FILE'
X			MINI-X GRAPHICS NOTES
X			David I. Bell
X			22 Apr 91
X
XThis is my mini-X graphics package for MINIX 1.5.  It has been designed to
Xwork for various types of machines, but the only low level support routines
Xprovided are for the IBM PC running a 386 in 32-bit protected mode.  If
Xsomeone writes the device routines for other machines such as Amiga or Mac,
Xthen this code could work on them too.  This code is also only written for
Xa serial mouse accessed using a normal tty line.  If you have a bus mouse,
Xor have a mouse device driver, then you will have to modify the mouse code
Xappropriately.
X
XThis code is not TOO large, and doesn't require TOO much table space.  Even
Xso, it will probably not run on machines with 64K limits.  So before trying
Xthis package, you MUST first install Bruce Evan's 32-bit patches since some
Xof the code assumes this.  (If someone wants to try, I am sure that it would
Xfit in 64K if the graphics code ran in its own address space, like mm and fs.
XHowever, this requires much more kernel hacking than I wanted to do.)
X
XI have also installed the virtual console code in my kernel, but I do not
Xthink that this is required.  I have done nothing to make the virtual
Xconsole code and the graphics code aware of each other (but this would
Xbe nice someday).  What interactions there are between the two will be
Xdiscussed under the bugs section.  The virtual console code will only
Xaffect the device number used for /dev/graphics, and the name of the tty
Xport used for the serial mouse.
X
XI am also running shoelace, but this should not affect things either except
Xfor the manner in which you back up old kernels when building new ones.
X
XYou must also have a version of CPP which works.  The one I got from the
XMINIX archives works, but required several patches to make it useable for
Xbuilding the MINIX kernel.  This CPP is from "cpp.tar.Z", written by Martin
XMinow.  It needed patches to disable errors for unquoted strings, and errors
Xwhen #if SYMBOL was used where SYMBOL was not defined.  If you have already
Xrebuilt your own kernels in 32-bit mode, you must have already gotten around
Xthese problems.  If not, then I have included patches to this version of CPP
Xfor the above problems if you need them.
X
XThe graphics code consists of two parts.  The first part is kernel code,
Xwhich implements a new device type of /dev/graphics.  There are small
Xpatches to several files in order to make the device accessible to the
Xrest of the system.  There are one or two small assembly routines needed
Xto support the main graphics code.  Everything else is in new files in the
Xkernel directory.  I have deliberately avoided changing existing code as
Xmuch as possible for this first release.  Therefore, I expect that you
Xshould not have much trouble installing this code into the operating system,
Xexcept for the known problems with using CPP.
X
XThe second part is the graphics server code.  Eventually, the graphics
Xserver will be a process by itself, and will just be a program that you
Xstart up, and then run clients which open connections to it.  But in this
Xrelease, the server code must be loaded with each client.  Therefore,
Xthe graphics server is built into a library that you just search when
Xloading your client program.  The server code is self-contained, and is
Xin its own directory called "/usr/src/graphics/server".
X
XFor clients, the built server library "libgraph.a" must be moved into the
Xlibrary directory (/usr/local/lib/i386) and the include file "graphics.h"
Xmust be put into /usr/include for clients to use.  I expect that client
Xprograms (whenever they are written) would be placed into the directory
X"/usr/src/graphics/clients".  The only clients I have provided are a demo
Xprogram and a program to reset the terminal back into text mode.
X
XThe demo program is simple and doesn't do much, but it shows how to open the
Xgraphics device, determine the size of the screen and what black and white
Xcolor values are, create windows and graphics contexts, draw lines, circles,
Xand text, change graphics contexts in order to change colors, read keyboard
Xand mouse events, handle several other types of events, and catch fatal
Xerrors.  It also demonstrates how to set input focus, how to draw rubber-
Xbanded lines, how to track the mouse constantly, and how to perform
Xbackground calculations while waiting for events.  This should be enough
Xexamples to get you started writing your own stuff.
X
XI have also written a simple tutorial on the use of the graphics functions,
Xand some concepts that you need to know if you don't know X-style graphics.
XThis is called TUTORIAL.
X
X
XINSTALLATION INSTRUCTIONS
X
XDetailed instructions on installing and testing the graphics routines follow.
XIn all the following, you are logged in as root.
X
XYou should first copy the mini-X package into a temporary directory where
Xyou can examine and play with the files without harming anything.
XNOTE: The following instructions assume that you are using the directory
X"/mini-x" for your temporary directory.
X
X
XUnpacking the mini-X package creates the following directories:
X	include		include files for /usr/include and /usr/include/minix
X	kernel		changes to /usr/src/kernel
X	fs		changes to /usr/src/fs
X	server		server library to be put into /usr/src/graphics/server
X	clients		client programs to be put in /usr/src/graphics/clients
X	cpp		patches for Martin Minow's CPP program
X
X
XPART A, BUILDING THE KERNEL:
X
X1.	If you have a working version of CPP that doesn't complain about
X	misquoted strings or undefined symbols, then skip this step.
X	Otherwise, you can get the CPP from the MINIX archives, and apply
X	the patches from the cpp directory to it.  These are for the
X	files "cpp5.c" and "cpp6.c".  Install the new CPP for use.
X
X2.	Copy the two include files from the include directory to the
X	system include directories.  One belongs in /usr/include, and the
X	other belongs in /usr/include/minix.
X		cd /mini-x/include
X		cp graphics.h /usr/include
X		cp graph_msg.h /usr/include/minix
X		chmod 644 /usr/include/graphics.h
X		chmod 644 /usr/include/minix/graph_msg.h
X
X3.	Copy or backup the following files in your kernel and fs directory
X	so that you can undo the changes to them if required.  Even better,
X	if you have disk space, then copy ALL of the current kernel and fs
X	directories to make sure they are safe.
X		fs/table.c
X		kernel/cstart.c
X		kernel/glo.h
X		kernel/klib386.x
X		kernel/makefile.cpp
X		kernel/makefile
X		kernel/proto.h
X		kernel/start.x
X		kernel/table.c
X		kernel/tty.c
X
X4.	Copy the existing minix image onto a bootable diskette so in case
X	the new one doesn't work, you can still bring the old MINIX back up.
X	If you are running shoelace like I am, then you can just copy the
X	kernel and fs into backup files in /etc/system.  For example:
X		cd /etc/system
X		cp kernel old_kernel
X		cp fs old_fs	
X
X5.	Copy the cdiff file from fs/table.c into /usr/src/fs, and
X	apply it.  Then build a new fs.
X		cd /usr/src/fs
X		cp /mini-x/fs/table.c.cdif .
X		patch table.c table.c.cdif
X		make
X
X6.	Copy the files from the kernel directory into /usr/src/kernel.
X	Some of these files are cdiff files and some are new files.
X		cd /usr/src/kernel
X		cp /mini-x/kernel/* .
X
X7.	Patch some of the files in the kernel directory.
X		cd /usr/src/kernel
X		patch cstart.c cstart.c.cdif
X		patch glo.h glo.h.cdif
X		patch klib386.x klib386.x.cdif
X		patch proto.h proto.h.cdif
X		patch start.x start.x.cdif
X		patch table.c table.c.cdif
X		patch tty.c tty.c.cdif
X
X8.	You must now manually edit start.x, and insert the routine which
X	is in start.x.insert into it.  The reason for this is that cdiff
X	(and diff) gave the wrong results when I attempted to build patch
X	files, and so this part must be done manually.  In start.x, after
X	the routine get_ega, and before the routine get_ext_memsize, read in
X	the file start.x.insert (containing the routine get_rom_char_addr).
X	Leave two blank lines before and after the new routine.
X
X9.	You must now create a correct makefile.  I have given you cdiffs
X	for the original makefile source, "makefile.cpp.cdif", and for the
X	resulting file "makefile.cdif".  You can try using these to patch
X	makefile.cpp and makefile.  Alternatively, I have also given you
X	complete new copies of makefile.cpp and makefile with the patches
X	already applied, as "makefile.new" and "makefile.cpp.n".  Make use
X	of these however you can.  The reason I	have given you all these
X	versions is because of the CPP problems.  Assuming that the new
X	makefile I supply is correct as is, then simply do the following:
X		cp makefile.cpp.n makefile.cpp
X		cp makefile.new makefile
X
X	If you must rebuild a new makefile from makefile.cpp, then as
X	described in the original porting notes for the 32-bit kernel,
X	you must do the following.  Edit out extraneous # lines from the
X	makefile.cpp file, then	run a version of CPP on the makefile.cpp
X	to produce makefile.  Then you must edit that makefile and again
X	remove the # lines, and convert the string "/usr/include/1" back
X	to "/usr/include/minix", and restore the leading tabs on the build
X	lines.  If you have already tried playing with rebuilding your
X	kernel in 32-bit mode, then you know these problems already.
X
X10.	Run Bruce Evan's config script in /usr/src/kernel to produce a new
X	klib.x from the modified klib386.x.  Alternatively, just copy it.
X	As I mentioned above, I have patches only for the 32-bit kernel.
X		cd /usr/src/kernel
X		cp klib386.x klib.x
X
X11.	Build the kernel.  There should be no more warning messages during
X	the load than there used to be.
X		cd /usr/src/kernel
X		make
X
X12.	Make the new /dev/graphics file which is a character device.  If
X	you have added extra devices to your system, then you must use the
X	correct major device number (instead of 7) in the mknod command.
X	Examine dmap in /usr/src/fs/table.c to make sure of the number.
X		mknod /dev/graphics c 7 0
X		chmod 666 /dev/graphics
X
X13.	Sync and Reboot the system and verify that the system works correctly.
X	Then you can try copying a file to /dev/graphics if you want, and
X	nothing	should happen except that you should get an I/O error.  This
X	is normal, since the format of the data sent to the graphics device
X	includes a magic number which is validated.  For example:
X		cp /etc/passwd /dev/graphics
X		cp: I/O error
X
X
X
XPART B, BUILDING THE GRAPHICS SERVER:
X
X1.	Create the directories /usr/src/graphics and /usr/src/graphics/server.
X		cd /usr/src
X		mkdir graphics
X		chmod 755 graphics
X		cd graphics
X		mkdir server
X		chmod 755 server
X
X2.	Copy the files from the server directory to /usr/src/graphics/server.
X		cd /usr/src/graphics/server
X		cp /mini-x/server/* .
X
X3.	Examine the configuration of your machine, and define the mouse
X	type and mouse port names appropriately.  This is in the file
X	"mousedev.c", and the defines are MOUSE_TYPE and MOUSE_PORT.
X	MOUSE_TYPE specifies the type of mouse, where "ms" is a Microsoft
X	mouse (two buttons), and "pc" is a PC mouse (three buttons).
X	The default is "ms".  MOUSE_PORT specifies the tty device name
X	which the mouse is plugged into.  Since I am running the virtual
X	console code, the default value is "/dev/tty64".  If your mouse is
X	plugged into a different tty, then change MOUSE_PORT to use it.
X
X4.	Examine the makefile to determine where the graphics library
X	should go.  The default library directory is /usr/local/lib/i386,
X	and is the directory that Bruce Evan's 32-bit patches uses.  If
X	you have changed this, then edit LIBDIR in the makefile to point
X	at the correct library directory.
X
X5.	Build the graphics server library by typing make.  The library
X	name is called "libgraph.a".
X		cd /usr/src/graphics/server
X		make
X
X6.	Copy the built library into the library directory.
X		make install
X
X
X
XPART C, BUILDING THE DEMO PROGRAM AND THE TERMINAL RESET MODE PROGRAM:
X
X1.	Create the /usr/src/graphics/clients directory, and copy the
X	files from the clients directory into it.
X		cd /usr/src/graphics
X		mkdir clients
X		chmod 755 clients
X		cd clients
X		cp /mini-x/clients/* .
X
X2.	Build the clients demo and tm.  Demo is the demonstration graphics
X	program, and tm is the "text mode" program, which is used to reset
X	the console back into text mode if a graphics program bombs out.
X		make
X
X3.	Try demo.  It should bring up several colored windows, with circles
X	being constantly drawn in the upper left one.  Move the mouse, and
X	a cursor should track its motion.  Moving the mouse into the small
X	grey window at the top middle should leave a trail of colored dots.
X	Using the button in the window at the upper right should let you
X	draw lines.  Moving the mouse into or out of the left window should
X	cause it to raise or lower itself, and change its border color.
X	Moving the mouse into or out of the large window should cause the
X	window to change it border color.  Clicking the mouse in the large
X	window should raise it to the top.  Typing characters while the mouse
X	is in the window should display them in the window.  The large window
X	should contain a filled	rectangle and a filled triangle.  Clicking
X	the button in the small	top window should take a snapshot of the
X	circles being drawn and	display that in the upper left of the large
X	window, blown up by a factor of 2.  The cursor should change its
X	shape when it enters or exits the circles window, or the large window.
X	Releasing a button while the mouse in in the circles window exits
X	from the demo.	Alternatively, pressing more than one button when
X	the mouse is in	the root window should cause a purposely generated
X	fatal error.
X
X4.	Install the demo program and tm program into /bin.  If you wish a
X	different destination directory then /bin, then edit makefile and
X	change BINDIR as appropriate.  Also change LIBRARIES in the makefile
X	if your library	directory is not /usr/local/lib/i386.
X		make install
X
X
XThat's it!
X
X
XPORTING NOTES FOR OTHER MACHINES
X
XI do not understand how MINIX runs on Macs or Amigas, so I cannot say much
Xhere, except to point out which files probably need changing, and what
Xthose changes are likely to be.
X
XThe files graph_ega.c and ega.x are the only files which reference the
Xgraphics hardware.  The first file is the high level code which interfaces
Xto the rest of the device driver, and the second is the low level graphics
Xroutines in assembly.  All calls to the graphics device are made through
Xprocedure variables in the gr_dev structure, which is typedef'd in the
Xfile graph_dev.h, and defined in graph_ega.c.  A typical call looks like
X(*gr_dev.drawpoint)(x, y, color).
X
XThe procedure variables can call either the device specific routines,
Xor the general routines.  The general routines are all in graph_gen.c.
XThe general routines call other lower-level routines, also through the
Xgr_dev structure.  Eventually, the lowest level routine is reached which
Xis the drawing of a single pixel.  This routine cannot be a general
Xroutine, it must be a device specific routine.
X
XIn order to implement a new graphics device, copy graph_ega.c into a new
Xfile (say, graph_foo.c), and modify it as required.  For those functions
Xwhich can be done by the general routines (such as drawing lines), make
Xthe entries in the gr_dev structure point at the general routines.  For those
Xfunctions which you can do in your hardware specific code, make the entries
Xpoint to your own function.  You MUST have certain functions implemented as
Xyour own routines.  These are the init, term, setmode, drawpoint, drawtext,
Xsizetext, readpoint, getcharbits, getscreeninfo, and getfontinto functions.
XThe other functions can use the generic routines in graph_gen, if desired.
XLater, you can replace the generic routines with device specific routines
Xfor performance gains (especially drawing of lines and filling of areas).
X
XThe gr_dev structure also contains parameters which give the configuration
Xof the graphics screen, such as the number of rows, columns, and colors.
XIf these are constant, you can just define them as initialized data in the
Xstructure definition.  However, if they vary (you may have more than one
Xgraphics mode available), then you can set them dynamically when the init
Xroutine is called.  The init routine is called with the requested number of
Xrows, columns, and colors.  If any value is 0, then you can choose it.
XOtherwise, you should honor the request, returning an error from the init
Xroutine if this is impossible.  (The current ega_init routine is such an
Xexample, but it only accepts the 640x350 16 color mode.  It could be
Xenhanced to support other modes too.)
X
XNote that the device level routines do not need to know about clipping.
XHowever, it is probably a good idea to put in checks to make sure that
Xthe arguments are within the screen area, just to be safe.  You can
Xignore drawing requests which attempt to go off of the screen, since
Xthey should not happen.
X
XOnce you have made your new module, just change the makefile to build
Xyour graph_foo module, and any other new modules you made, and remove
Xthe use of graph_ega.c and ega.x.  Your gr_dev structure will then be
Xused instead of the EGA one, and the higher level graphics functions
Xwill call your code.
X
XI cannot say much about interfacing the mouse, or returning modifiers from
Xthe keyboard.  One of you will have to investigate this.
X
X
XBUGS
X
XThe following is a list of things which do not work as I desire.  Maybe
Xsomeone can send me (or post) fixes or code for some of these things.
X
X1.	One line is missing at the bottom of the screen.  I don't know why,
X	but the screen resolution is actually 640 by 349 on my EGA.
X
X2.	If the client or any other process outputs normally to the screen,
X	this will mess up the screen with rubbish.  This is because the
X	console code and the graphics code know nothing about each other.
X	Someday the console should be told to leave the screen alone, or
X	else it can send messages to the graphics server to draw characters
X	for it.  (This is an argument to keep the graphics code in the
X	kernel, instead of moving it out to user space.)
X
X3.	When the graphics program closes the screen, it is blanked, but
X	previous text and the cursor do not reappear.  When running the
X	virtual console code, typing a few returns to cause the screen
X	to scroll will fix things.  Once again, this is because the
X	console and graphics know nothing about each other.  Someday the
X	graphics code should send a message to the console driver to fix
X	the screen.
X
X4.	The graphics device needs to know about the last close for it, so
X	that it can automatically reset the console back into text mode.
X	Then the tm program would be unnecessary.
X
X5.	The graphics device really should be a once-open device, to prevent
X	attempts by multiple clients to open it.  If multiple  clients do
X	open it, they will interfere with each other.
X
X6.	There is no way to obtain the state of the the modifiers from the
X	keyboard.  These are SHIFT, CTRL, and ALT.  So currently there are
X	no modifiers available for clients to use.  The keyboard driver
X	knows these things, what is required is a way of obtaining them.
X	A simple way is to just make an IOCTL which returns the state.
X	Races can occur with this, so to do it right requires much more
X	extensive hacking in the keyboard driver to make sure the modifiers
X	are correct for each character read.
X
X7.	All the graphics programs busy loop.  So while events are being
X	waited for, the program constantly tries to read the newest status
X	from the mouse and keyboard.  Fixing this requires some form of
X	poll or select.
X
X
XFUTURES
X
XI have not thought much about window managers.  There is no code to support
Xthem at present.  For mini-X, I do not really see the need for an external
Xwindow manager, with all of its complications.  It seems better to have a
Xbuilt-in window manager in the server.  However, it must interact with the
Xrest of the server code in a small number of well-defined ways.  The reason
Xfor this is to allow multiple versions of the window mananger to be built,
Xso that everyone can run the one they want.  If the interface was correct,
Xthen you could replace the window manager code with your own window manager
Xwith no problems.  As I said, I think this is adequate for mini-X.
X
XChanging the server code to run with multiple clients is needed.  This
Xrequires some form of cross-process communication, and POLL to be able to
Xselect on the clients.  The amoeba routines are not adequate, because
Xthey assume an RPC-type network call.  The server must be able to read and
Xwrite from multiple clients, in any order, so that there can be many
Xoutstanding replies.  Named pipes could be used, but they are rather ugly.
X
XPoll is needed even without multiple clients, in order to stop the busy
Xloop that the server does.  For a single user machine, a busy loop is not
Xtoo bad, but it still slows down compiles and such.  It is better to fix it.
X
XPixmaps would be useful.  Without them, doing redraws when exposures occur
Xbecomes very hard.  The code currently has stubs for the pixmap routines,
Xso adding them would not be very difficult.
X
XLoadable fonts would be nice.  Currently the only fonts are the ones known
Xby the device driver (and there is only 1 of those!).  The server would
Xread a font from a file into memory, and then use the bitmap drawing
Xprimitives to draw the characters.  The bitmap drawing routines would
Xthen need some performance enhancements, such as adding a low level device
Xfunction to do it.
X
XPtys would be needed for building xterms.
X
XHigher resolution modes for the VGA would be nice to have.
X
XRoutines are needed to convert color names into color values.  I have
Xstarted this, but don't have it ready for this posting.  Hardwiring
Xconstants into client programs for colors is not good.
X
XLots of client programs to do nifty graphics would be nice.  Some games
Xusing them would be fun.  I plan to post some later.
X
XSpeedups for various operations would be nice.  Some operations are much
Xslower and uglier than they need to be.
X
XFinally, I do **NOT** want to implement everything that the real X has.
XIf you want all that, then buy some more memory, run UNIX, and run the
Xreal thing.  What I do want are the smallest changes that do the most
Xgood.  In other words, weigh the cost of a feature with the usefulness
Xof the feature.  The best features are the ones which win real big with
Xonly a little bit of effort.  I am sure that you all will argue for hours
Xabout which features are the really necessary ones...
X
X
XI hope this stuff will be as fun and useful to you as it is for me.  I
Xwill answer questions and coordinate changes and bug fixes to the code as
Xpeople request it (as long as I am not TOO swamped with them).  However,
Xif someone else wants to volunteer to do this, then that is OK by me too.
X(Especially for non-IBM machines, which I know nothing about.)
X
X
XDavid I. Bell			NEC Information Systems Australia
Xdbell@pdact.pd.necisa.oz.au	SDC Canberra
END_OF_FILE
if test 22803 -ne `wc -c <'mini-x/README'`; then
    echo shar: \"'mini-x/README'\" unpacked with wrong size!
fi
# end of 'mini-x/README'
fi
if test -f 'mini-x/kernel/graph_main.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'mini-x/kernel/graph_main.c'\"
else
echo shar: Extracting \"'mini-x/kernel/graph_main.c'\" \(21918 characters\)
sed "s/^X//" >'mini-x/kernel/graph_main.c' <<'END_OF_FILE'
X/* Copyright (c) 1991 David I. Bell
X * Permission is granted to use, distribute, or modify this source,
X * provided that this copyright notice remains intact.
X *
X * Top level drawing primitives.
X * These routines do the necessary range checking, clipping, and cursor
X * overwriting checks, and then call the lower level device dependent
X * routines to actually do the drawing.  The lower level routines are
X * only called when it is known that all the pixels to be drawn are
X * within the device area and are visible.
X */
X
X#include "kernel.h"
X#include "graph_dev.h"
X
X
X/* Global symbols used throughout the graphics code. */
XGR_COLOR gr_foreground;		/* current foreground color */
XGR_COLOR gr_background;		/* current background color */
XGR_BOOL gr_usebg;		/* TRUE if background drawn in pixmaps */
XGR_BOOL gr_error;		/* true if error occurred */
XGR_MODE gr_mode;		/* drawing mode */
X
X
X#define	min(a,b) ((a) < (b) ? (a) : (b))
X
XFORWARD void drawrow();
XFORWARD void drawcol();
XFORWARD void draw4points();
XFORWARD void extendrow();
X
X
X/*===========================================================================*
X *				fillellipse				     *
X *===========================================================================*/
XPUBLIC void fillellipse(x, y, rx, ry)
XGR_COORD x, y;			/* coordinates of center of ellipse */
XGR_SIZE rx;			/* radius along x axis */
XGR_SIZE ry;			/* radius along y axis */
X{
X/* Fill an ellipse in the foreground color, applying clipping if necessary. */
X  int xp, yp;			/* current point (based on center) */
X  long Asquared;		/* square of x semi axis */
X  long TwoAsquared;
X  long Bsquared;		/* square of y semi axis */
X  long TwoBsquared;
X  long d;
X  long dx, dy;
X
X  if ((rx < 0) || (ry < 0)) return;
X
X  /* See if the ellipse is either totally visible or totally invisible.
X   * If so, then the ellipse drawing is easy.
X   */
X  switch (cliparea(x - rx, y - ry, x + rx, y + ry)) {
X      case GR_CLIP_VISIBLE:
X	(*gr_dev.fillellipse) (x, y, rx, ry, gr_foreground);
X	/* Fall into return */
X      case GR_CLIP_INVISIBLE:	return;
X}
X
X  xp = 0;
X  yp = ry;
X  Asquared = rx * rx;
X  TwoAsquared = 2 * Asquared;
X  Bsquared = ry * ry;
X  TwoBsquared = 2 * Bsquared;
X  d = Bsquared - Asquared * ry + (Asquared >> 2);
X  dx = 0;
X  dy = TwoAsquared * ry;
X
X  while (dx < dy) {
X	drawrow(x - xp, x + xp, y - yp);
X	drawrow(x - xp, x + xp, y + yp);
X	if (d > 0) {
X		yp--;
X		dy -= TwoAsquared;
X		d -= dy;
X	}
X	xp++;
X	dx += TwoBsquared;
X	d += (Bsquared + dx);
X  }
X  d += ((3L * (Asquared - Bsquared) / 2L - (dx + dy)) >> 1);
X  while (yp >= 0) {
X	drawrow(x - xp, x + xp, y - yp);
X	drawrow(x - xp, x + xp, y + yp);
X	if (d < 0) {
X		xp++;
X		dx += TwoBsquared;
X		d += dx;
X	}
X	yp--;
X	dy -= TwoAsquared;
X	d += (Asquared - dy);
X  }
X}
X
X
X/*===========================================================================*
X *				drawpoint				     *
X *===========================================================================*/
XPUBLIC void drawpoint(x, y)
XGR_COORD x;
XGR_COORD y;
X{
X/* Draw an individual point in the foreground color, applying
X * clipping if necessary.
X */
X  if (clippoint(x, y)) (*gr_dev.drawpoint) (x, y, gr_foreground);
X}
X
X
X/*===========================================================================*
X *				drawline				     *
X *===========================================================================*/
XPUBLIC void drawline(x1, y1, x2, y2)
XGR_COORD x1;
XGR_COORD y1;
XGR_COORD x2;
XGR_COORD y2;
X{
X/* Draw an arbitrary line in the foreground color, applying
X * clipping if necessary.
X */
X  int xdelta;			/* width of rectangle around line */
X  int ydelta;			/* height of rectangle around line */
X  int xinc;			/* increment for moving x coordinate */
X  int yinc;			/* increment for moving y coordinate */
X  int rem;			/* current remainder */
X
X  /* See if the line is horizontal or vertical. If so, then call
X   * special routines.
X   */
X  if (y1 == y2) {
X	drawrow(x1, x2, y1);
X	return;
X  }
X  if (x1 == x2) {
X	drawcol(x1, y1, y2);
X	return;
X  }
X
X  /* See if the line is either totally visible or totally invisible. If
X   * so, then the line drawing is easy.
X   */
X  switch (cliparea(x1, y1, x2, y2)) {
X      case GR_CLIP_VISIBLE:
X	(*gr_dev.drawline) (x1, y1, x2, y2, gr_foreground);
X	/* Fall into return */
X      case GR_CLIP_INVISIBLE:	return;
X}
X
X  /* The line may be partially obscured. Do the draw line algorithm
X   * checking each point against the clipping regions.
X   */
X  xdelta = x2 - x1;
X  ydelta = y2 - y1;
X  if (xdelta < 0) xdelta = -xdelta;
X  if (ydelta < 0) ydelta = -ydelta;
X  xinc = (x2 > x1) ? 1 : -1;
X  yinc = (y2 > y1) ? 1 : -1;
X  if (clippoint(x1, y1)) (*gr_dev.drawpoint) (x1, y1, gr_foreground);
X  if (xdelta >= ydelta) {
X	rem = xdelta / 2;
X	do {
X		x1 += xinc;
X		rem += ydelta;
X		if (rem >= xdelta) {
X			rem -= xdelta;
X			y1 += yinc;
X		}
X		if (clippoint(x1, y1))
X			(*gr_dev.drawpoint) (x1, y1, gr_foreground);
X	} while (x1 != x2);
X  } else {
X	rem = ydelta / 2;
X	do {
X		y1 += yinc;
X		rem += xdelta;
X		if (rem >= ydelta) {
X			rem -= ydelta;
X			x1 += xinc;
X		}
X		if (clippoint(x1, y1))
X			(*gr_dev.drawpoint) (x1, y1, gr_foreground);
X	} while (y1 != y2);
X  }
X}
X
X
X/*===========================================================================*
X *				drawrow					     *
X *===========================================================================*/
XPRIVATE void drawrow(x1, x2, y)
XGR_COORD x1;
XGR_COORD x2;
XGR_COORD y;
X{
X/* Draw a horizontal line in the foreground color, applying
X * clipping if necessary.
X */
X  GR_COORD temp;
X
X  if (x1 > x2) {
X	temp = x1;
X	x1 = x2;
X	x2 = temp;
X  }
X  if (x1 < 0) x1 = 0;
X  if (x2 >= gr_dev.cols) x2 = gr_dev.cols - 1;
X
X  (*gr_dev.checkcursor) (x1, y, x2, y);
X
X  while (x1 <= x2) {
X	if (clippoint(x1, y)) {
X		temp = min(clipmaxx, x2);
X		(*gr_dev.drawrow) (x1, temp, y, gr_foreground);
X	} else
X		temp = min(clipmaxx, x2);
X	x1 = temp + 1;
X  }
X}
X
X
X/*===========================================================================*
X *				drawcol					     *
X *===========================================================================*/
XPRIVATE void drawcol(x, y1, y2)
XGR_COORD x;
XGR_COORD y1;
XGR_COORD y2;
X{
X/* Draw a vertical line in the foreground color, applying
X * clipping if necessary.
X */
X  GR_COORD temp;
X
X  if (y1 > y2) {
X	temp = y1;
X	y1 = y2;
X	y2 = temp;
X  }
X  if (y1 < 0) y1 = 0;
X  if (y2 >= gr_dev.rows) y2 = gr_dev.rows - 1;
X
X  (*gr_dev.checkcursor) (x, y1, x, y2);
X
X  while (y1 <= y2) {
X	if (clippoint(x, y1)) {
X		temp = min(clipmaxy, y2);
X		(*gr_dev.drawcol) (x, y1, temp, gr_foreground);
X	} else
X		temp = min(clipmaxy, y2);
X	y1 = temp + 1;
X  }
X}
X
X
X/*===========================================================================*
X *				drawrect				     *
X *===========================================================================*/
XPUBLIC void drawrect(x, y, width, height)
XGR_COORD x;
XGR_COORD y;
XGR_COORD width;
XGR_COORD height;
X{
X/* Draw a rectangle in the foreground color, applying clipping if necessary.
X * This is careful to not draw points multiple times in case the rectangle
X * is being drawn using XOR.
X */
X  GR_COORD maxx;
X  GR_COORD maxy;
X
X  if ((width <= 0) || (height <= 0)) return;
X  maxx = x + width - 1;
X  maxy = y + height - 1;
X  drawline(x, y, maxx, y);
X  if (height > 1) drawline(x, maxy, maxx, maxy);
X  if (height < 3) return;
X  y++;
X  maxy--;
X  drawline(x, y, x, maxy);
X  if (width > 1) drawline(maxx, y, maxx, maxy);
X}
X
X
X/*===========================================================================*
X *				fillrect				     *
X *===========================================================================*/
XPUBLIC void fillrect(x1, y1, x2, y2)
XGR_COORD x1;
XGR_COORD y1;
XGR_COORD x2;
XGR_COORD y2;
X{
X/* Draw a filled in rectangle in the foreground color, applying
X * clipping if necessary.
X */
X  GR_COORD temp;
X
X  if (y1 == y2) {
X	drawrow(x1, x2, y1);
X	return;
X  }
X  if (x1 == x2) {
X	drawcol(x1, y1, y2);
X	return;
X  }
X  if (x1 > x2) {
X	temp = x1;
X	x1 = x2;
X	x2 = temp;
X  }
X  if (y1 > y2) {
X	temp = y1;
X	y1 = y2;
X	y2 = temp;
X  }
X
X  /* See if the rectangle is either totally visible or totally
X   * invisible. If so, then the rectangle drawing is easy.
X   */
X  switch (cliparea(x1, y1, x2, y2)) {
X      case GR_CLIP_VISIBLE:
X	(*gr_dev.fillrect) (x1, y1, x2, y2, gr_foreground);
X	/* Fall into return */
X      case GR_CLIP_INVISIBLE:	return;
X}
X
X  /* The rectangle may be partially obstructed. So do it line by line. */
X  while (y1 <= y2) drawrow(x1, x2, y1++);
X}
X
X
X/*===========================================================================*
X *				drawpoly				     *
X *===========================================================================*/
XPUBLIC void drawpoly(points, count)
XGR_POINT *points;
XGR_COUNT count;
X{
X/* Draw a polygon in the foreground color, applying clipping if necessary.
X * The polygon is only closed if the first point is repeated at the end.
X * Some care is taken to plot the endpoints correctly if the current
X * drawing mode is XOR.  However, internal crossings are not handled
X * correctly.
X */
X  GR_COORD firstx;
X  GR_COORD firsty;
X  GR_BOOL didline;
X
X  if (count < 2) return;
X  firstx = points->x;
X  firsty = points->y;
X  didline = GR_FALSE;
X
X  while (count-- > 1) {
X	if (didline && (gr_mode == GR_MODE_XOR))
X		drawpoint(points->x, points->y);
X	drawline(points[0].x, points[0].y, points[1].x, points[1].y);
X	points++;
X	didline = GR_TRUE;
X  }
X  if (gr_mode != GR_MODE_XOR) return;
X  points--;
X  if ((points->x == firstx) && (points->y == firsty))
X	drawpoint(points->x, points->y);
X}
X
X
X/*===========================================================================*
X *				fillpoly				     *
X *===========================================================================*/
XPUBLIC void fillpoly(points, count)
XGR_POINT *points;
XGR_COUNT count;
X{
X/* Fill a polygon in the foreground color, applying clipping if necessary.
X * Note: this routine currently only correctly fills convex polygons.
X */
X  GR_POINT *pp;			/* current point */
X  GR_COORD miny;		/* minimum row */
X  GR_COORD maxy;		/* maximum row */
X  GR_COORD minx;		/* minimum column */
X  GR_COORD maxx;		/* maximum column */
X  GR_COUNT i;			/* counter */
X
X  if (count <= 0) return;
X
X  /* First determine the minimum and maximum rows for the polygon. */
X  pp = points;
X  miny = pp->y;
X  maxy = pp->y;
X  for (i = count; i-- > 0; pp++) {
X	if (miny > pp->y) miny = pp->y;
X	if (maxy < pp->y) maxy = pp->y;
X  }
X  if (miny < 0) miny = 0;
X  if (maxy >= gr_dev.rows) maxy = gr_dev.rows - 1;
X  if (miny > maxy) return;
X
X  /* Now for each row, scan the list of points and determine the
X   * minimum and maximum x coordinate for each line, and plot the row.
X   * The last point connects with the first point automatically.
X   */
X  for (; miny <= maxy; miny++) {
X	minx = GR_COORD_MAX;
X	maxx = GR_COORD_MIN;
X	pp = points;
X	for (i = count; --i > 0; pp++) {
X		extendrow(miny, pp[0].x, pp[0].y, pp[1].x,
X			  pp[1].y, &minx, &maxx);
X	}
X	extendrow(miny, pp[0].x, pp[0].y, points[0].x,
X		  points[0].y, &minx, &maxx);
X
X	if (minx <= maxx) drawrow(minx, maxx, miny);
X  }
X}
X
X
X/*===========================================================================*
X *				extendrow				     *
X *===========================================================================*/
XPRIVATE void extendrow(y, x1, y1, x2, y2, minxptr, maxxptr)
XGR_COORD y;			/* row to check for intersection */
XGR_COORD x1;			/* x coordinate of first endpoint */
XGR_COORD y1;			/* y coordinate of first endpoint */
XGR_COORD x2;			/* x coordinate of second endpoint */
XGR_COORD y2;			/* y coordinate of second endpoint */
XGR_COORD *minxptr;		/* address of current minimum x */
XGR_COORD *maxxptr;		/* address of current maximum x */
X{
X/* Utility routine for filling polygons.  Find the intersection point (if
X * any) of a horizontal line with an arbitrary line, and extend the current
X * minimum and maximum x values as needed to include the intersection point.
X */
X  GR_COORD x;			/* x coordinate of intersection */
X  long num;			/* numerator of fraction */
X
X  /* First make sure the specified line segment includes the specified
X   * row number.  If not, then there is no intersection.
X   */
X  if (((y < y1) || (y > y2)) && ((y < y2) || (y > y1))) return;
X
X  /* If a horizontal line, then check the two endpoints. */
X  if (y1 == y2) {
X	if (*minxptr > x1) *minxptr = x1;
X	if (*minxptr > x2) *minxptr = x2;
X	if (*maxxptr < x1) *maxxptr = x1;
X	if (*maxxptr < x2) *maxxptr = x2;
X	return;
X  }
X
X  /* If a vertical line, then check the x coordinate. */
X  if (x1 == x2) {
X	if (*minxptr > x1) *minxptr = x1;
X	if (*maxxptr < x1) *maxxptr = x1;
X	return;
X  }
X
X  /* An arbitrary line.  Calculate the intersection point using the
X   * formula x = x1 + (y - y1) * (x2 - x1) / (y2 - y1).
X   */
X  num = ((long) (y - y1)) * ((long) (x2 - x1));
X  x = x1 + num / (y2 - y1);
X  if (*minxptr > x) *minxptr = x;
X  if (*maxxptr < x) *maxxptr = x;
X}
X
X
X/*===========================================================================*
X *				drawellipse				     *
X *===========================================================================*/
XPUBLIC void drawellipse(x, y, rx, ry)
XGR_COORD x, y;			/* coordinates of center of ellipse */
XGR_SIZE rx;			/* radius along x axis */
XGR_SIZE ry;			/* radius along y axis */
X{
X/* Draw the boundary of an ellipse in the foreground color, applying
X * clipping if necessary.
X */
X  int xp, yp;			/* current point (based on center) */
X  long Asquared;		/* square of x semi axis */
X  long TwoAsquared;
X  long Bsquared;		/* square of y semi axis */
X  long TwoBsquared;
X  long d;
X  long dx, dy;
X
X  if ((rx < 0) || (ry < 0)) return;
X  /* See if the ellipse is either totally visible or totally invisible.
X   * If so, then the ellipse drawing is easy.
X   */
X  switch (cliparea(x - rx, y - ry, x + rx, y + ry)) {
X      case GR_CLIP_VISIBLE:
X	(*gr_dev.drawellipse) (x, y, rx, ry, gr_foreground);
X	/* Fall into return */
X      case GR_CLIP_INVISIBLE:	return;
X}
X
X  xp = 0;
X  yp = ry;
X  Asquared = rx * rx;
X  TwoAsquared = 2 * Asquared;
X  Bsquared = ry * ry;
X  TwoBsquared = 2 * Bsquared;
X  d = Bsquared - Asquared * ry + (Asquared >> 2);
X  dx = 0;
X  dy = TwoAsquared * ry;
X
X  while (dx < dy) {
X	draw4points(x, y, xp, yp);
X	if (d > 0) {
X		yp--;
X		dy -= TwoAsquared;
X		d -= dy;
X	}
X	xp++;
X	dx += TwoBsquared;
X	d += (Bsquared + dx);
X  }
X  d += ((3L * (Asquared - Bsquared) / 2L - (dx + dy)) >> 1);
X  while (yp >= 0) {
X	draw4points(x, y, xp, yp);
X	if (d < 0) {
X		xp++;
X		dx += TwoBsquared;
X		d += dx;
X	}
X	yp--;
X	dy -= TwoAsquared;
X	d += (Asquared - dy);
X  }
X}
X
X
X/*===========================================================================*
X *				draw4points				     *
X *===========================================================================*/
XPRIVATE void draw4points(x, y, px, py)
XGR_COORD x, y;			/* center of the points */
XGR_SIZE px, py;			/* point to plot (based on center) */
X{
X/* Set four points symmetrically situated around a point. */
X  drawpoint(x + px, y + py);
X  drawpoint(x - px, y + py);
X  drawpoint(x + px, y - py);
X  drawpoint(x - px, y - py);
X}
X
X
X/*===========================================================================*
X *				copyarea				     *
X *===========================================================================*/
XPUBLIC void copyarea(srcx, srcy, width, height, destx, desty)
X{
X/* Copy a rectangular area from one screen area to another.
X * This bypasses clipping.
X */
X  GR_COORD srcx;		/* leftmost column of area to copy */
X  GR_COORD srcy;		/* topmost row of area to copy */
X  GR_SIZE width;		/* width of area to copy */
X  GR_SIZE height;		/* height of area to copy */
X  GR_COORD destx;		/* leftmost column of destination */
X  GR_COORD desty;		/* topmost row of destination */
X
X  if ((width <= 0) || (height <= 0)) return;
X  if ((srcx == destx) && (srcy == desty)) return;
X  (*gr_dev.checkcursor) (srcx, srcy, srcx + width - 1, srcy + height - 1);
X  (*gr_dev.checkcursor) (destx, desty, destx + width - 1, desty + height - 1);
X  (*gr_dev.copyarea) (srcx, srcy, width, height, destx, desty);
X}
X
X
X/*===========================================================================*
X *				drawarea8				     *
X *===========================================================================*/
XPUBLIC void drawarea8(x, y, width, height, table)
XGR_COORD x;			/* leftmost column of area */
XGR_COORD y;			/* topmost row of area */
XGR_SIZE width;			/* width of area */
XGR_SIZE height;			/* height of area */
XGR_COLOR8 *table;		/* table of 8 bit color values */
X{
X/* Draw a rectangle of color values, clipping if necessary.
X * The rectangle is composed of 8 bit color values so that each color
X * only uses one character.  If a color matches the background color,
X * that that pixel is only drawn if the gr_usebg flag is set.
X */
X  long cellstodo;		/* remaining number of cells */
X  long count;			/* number of cells of same color */
X  long cc;			/* current cell count */
X  long rows;			/* number of complete rows */
X  GR_COORD minx;		/* minimum x value */
X  GR_COORD maxx;		/* maximum x value */
X  GR_COLOR savecolor;		/* saved foreground color */
X  GR_BOOL dodraw;		/* TRUE if draw these points */
X
X  minx = x;
X  maxx = x + width - 1;
X
X  /* See if the area is either totally visible or totally invisible. If
X   * so, then the area drawing is easy.
X   */
X  switch (cliparea(minx, y, maxx, y + height - 1)) {
X      case GR_CLIP_VISIBLE:
X	(*gr_dev.drawarea8) (x, y, width, height, table);
X	/* Fall into return */
X      case GR_CLIP_INVISIBLE:	return;
X}
X
X  savecolor = gr_foreground;
X  cellstodo = width * height;
X  while (cellstodo > 0) {
X	/* See how many of the adjacent remaining points have the
X	 * same color as the next point.
X	 */
X	gr_foreground = *table++;
X	dodraw = (gr_usebg || (gr_foreground != gr_background));
X	count = 1;
X	cellstodo--;
X	while ((cellstodo > 0) && (gr_foreground == *table)) {
X		table++;
X		count++;
X		cellstodo--;
X	}
X
X	/* If there is only one point with this color, then draw it
X	 * by itself.
X	 */
X	if (count == 1) {
X		if (dodraw) drawpoint(x, y);
X		if (++x > maxx) {
X			x = minx;
X			y++;
X		}
X		continue;
X	}
X
X	/* There are multiple points with the same color. If we are
X	 * not at the start of a row of the rectangle, then draw this
X	 * first row specially.
X	 */
X	if (x != minx) {
X		cc = count;
X		if (x + cc - 1 > maxx) cc = maxx - x + 1;
X		if (dodraw) drawrow(x, x + cc - 1, y);
X		count -= cc;
X		x += cc;
X		if (x > maxx) {
X			x = minx;
X			y++;
X		}
X	}
X
X	/* Now the x value is at the beginning of a row if there are
X	 * any points left to be drawn.  Draw all the complete rows
X	 * with one call.
X	 */
X	rows = count / width;
X	if (rows > 0) {
X		if (dodraw) fillrect(x, y, maxx, y + rows - 1);
X		count %= width;
X		y += rows;
X	}
X
X	/* If there is a final partial row of pixels left to be
X	 * drawn, then do that.
X	 */
X	if (count > 0) {
X		if (dodraw) drawrow(x, x + count - 1, y);
X		x += count;
X	}
X  }
X  gr_foreground = savecolor;
X}
X
X
X/*===========================================================================*
X *				drawbitmap				     *
X *===========================================================================*/
XPUBLIC void drawbitmap(x, y, width, height, table)
XGR_COORD x;			/* leftmost column of area */
XGR_COORD y;			/* topmost row of area */
XGR_SIZE width;			/* width of area */
XGR_SIZE height;			/* height of area */
XGR_BITMAP *table;		/* table of bitmaps */
X{
X/* Draw a rectangle of foreground (and possibly background) colors as
X * determined by the specified bitmap, clipping if necessary.  The
X * background is only drawn if the gr_usebg flag is set.
X */
X  GR_COORD minx;
X  GR_COORD maxx;
X  GR_COLOR savecolor;		/* saved foreground color */
X  GR_BITMAP bitvalue;		/* bitmap word value */
X  int bitcount;			/* number of bits left in bitmap word */
X
X  switch (cliparea(x, y, x + width - 1, y + height - 1)) {
X      case GR_CLIP_VISIBLE:
X	if (gr_usebg) {
X		(*gr_dev.fillrect) (x, y, x + width - 1,
X				    y + height - 1, gr_background);
X	}
X	(*gr_dev.drawbitmap) (x, y, width, height, table, gr_foreground);
X	/* Fall into return */
X
X      case GR_CLIP_INVISIBLE:	return;
X}
X
X  /* The rectangle is partially visible, so must do clipping. First
X   * fill a rectangle in the background color if necessary.
X   */
X  if (gr_usebg) {
X	savecolor = gr_foreground;
X	gr_foreground = gr_background;
X	fillrect(x, y, x + width - 1, y + height - 1);
X	gr_foreground = savecolor;
X  }
X  minx = x;
X  maxx = x + width - 1;
X  bitcount = 0;
X  while (height > 0) {
X	if (bitcount <= 0) {
X		bitcount = GR_BITMAPBITS;
X		bitvalue = *table++;
X	}
X	if (GR_TESTBIT(bitvalue) && clippoint(x, y))
X		(*gr_dev.drawpoint) (x, y, gr_foreground);
X	bitvalue = GR_SHIFTBIT(bitvalue);
X	bitcount--;
X	if (x++ == maxx) {
X		x = minx;
X		y++;
X		height--;
X		bitcount = 0;
X	}
X  }
X}
X
X
X/*===========================================================================*
X *				drawtext				     *
X *===========================================================================*/
XPUBLIC void drawtext(x, y, str, cc)
XGR_COORD x, y;			/* location to draw string at */
XGR_CHAR *str;			/* string to draw */
XGR_SIZE cc;			/* number of characters */
X{
X/* Draw a text string at a specifed coordinates in the foreground color
X * (and possibly the background color), applying clipping if necessary.
X * The background color is only drawn if the gr_usebg flag is set.
X */
X  GR_SIZE width;		/* width of text area */
X  GR_SIZE height;		/* height of text area */
X  GR_BITMAP bitmap[14];		/* bitmaps for characters */
X
X  if ((cc <= 0) || (y < 0) || (x >= gr_dev.cols)) return;
X
X  (*gr_dev.sizetext) (str, cc, &width, &height);
X
X  switch (cliparea(x, y - height + 1, x + width - 1, y)) {
X      case GR_CLIP_VISIBLE:
X	if (gr_usebg) {
X		(*gr_dev.fillrect) (x, y - height + 1,
X				    x + width - 1, y, gr_background);
X	}
X	(*gr_dev.drawtext) (x, y, str, cc, gr_foreground);
X	/* Fall into return */
X
X      case GR_CLIP_INVISIBLE:	return;
X}
X
X  /* Get the bitmap for each character individually, and then display
X   * them using clipping for each one.
X   */
X  y -= (height - 1);
X  while ((cc-- > 0) && (x < gr_dev.cols)) {
X	(*gr_dev.getcharbits) (*str++, bitmap, &width, &height);
X	drawbitmap(x, y, width, height, bitmap);
X	x += width;
X  }
X}
X
X/* END CODE */
END_OF_FILE
if test 21918 -ne `wc -c <'mini-x/kernel/graph_main.c'`; then
    echo shar: \"'mini-x/kernel/graph_main.c'\" unpacked with wrong size!
fi
# end of 'mini-x/kernel/graph_main.c'
fi
echo shar: End of archive 6 \(of 9\).
cp /dev/null ark6isdone
MISSING=""
for I in 1 2 3 4 5 6 7 8 9 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked all 9 archives.
    rm -f ark[1-9]isdone ark[1-9][0-9]isdone
else
    echo You still need to unpack the following archives:
    echo "        " ${MISSING}
fi
##  End of shell archive.
exit 0

dbell@pdact.pd.necisa.oz.au (David I. Bell) (04/22/91)

#! /bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of archive 7 (of 9)."
# Contents:  mini-x/server/serv_util.c
# Wrapped by dbell@elm on Mon Apr 22 11:21:50 1991
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'mini-x/server/serv_util.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'mini-x/server/serv_util.c'\"
else
echo shar: Extracting \"'mini-x/server/serv_util.c'\" \(26728 characters\)
sed "s/^X//" >'mini-x/server/serv_util.c' <<'END_OF_FILE'
X/*
X * Copyright (c) 1991 David I. Bell
X * Permission is granted to use, distribute, or modify this source,
X * provided that this copyright notice remains intact.
X *
X * Graphics server utility routines for windows.
X */
X#include <stdio.h>
X#include "graph_serv.h"
X
X
X/*
X * Help prevent future bugs by defining this variable to an illegal value.
X * These routines should not be referencing this, but should be using
X * unmapcount instead.
X */
X#define	mapped	cannotusemapped
X
X
X/*
X * Macro to distinguish cases of clipping.
X */
X#define	GAPVAL(leftgap, rightgap, topgap, bottomgap) \
X	(((leftgap) << 3) + ((rightgap) << 2) + ((topgap) << 1) + (bottomgap))
X
X
X/*
X * Unmap the window to make it and its children invisible on the screen.
X * This is a recursive routine which increments the unmapcount values for
X * this window and all of its children, and causes exposure events for
X * windows which are newly uncovered.
X */
Xvoid
XGsWpUnmapWindow(wp)
X	GR_WINDOW	*wp;		/* window to be unmapped */
X{
X	GR_WINDOW	*pwp;		/* parent window */
X	GR_WINDOW	*sibwp;		/* sibling window */
X	GR_SIZE		bs;		/* border size of this window */
X
X	if (wp == rootwp) {
X		GsError(GR_ERROR_ILLEGAL_ON_ROOT_WINDOW, wp->id);
X		return;
X	}
X
X	if (wp == clipwp)
X		clipwp = NULL;
X
X	wp->unmapcount++;
X
X	for (wp = wp->children; wp; wp = wp->siblings)
X		GsWpUnmapWindow(wp);
X
X	if (wp == mousewp) {
X		GsCheckMouseWindow();
X		GsCheckCursor();
X	}
X
X	if (wp == focuswp) {
X		focusfixed = GR_FALSE;
X		GsCheckFocusWindow();
X	}
X
X	/*
X	 * If this is an input-only window or the parent window is
X	 * still unmapped, then we are all done.
X	 */
X	if (!wp->output || wp->parent->unmapcount)
X		return;
X
X	/*
X	 * Clear the area in the parent for this window, causing an
X	 * exposure event for it.  Take into account the border size.
X	 */
X	bs = wp->bordersize;
X	pwp = wp->parent;
X	GsWpClearWindow(pwp, wp->x - pwp->x - bs, wp->y - pwp->y - bs,
X		wp->width + bs * 2, wp->height + bs * 2, GR_TRUE);
X
X	/*
X	 * Finally clear and redraw all parts of our lower sibling
X	 * windows that were covered by this window.
X	 */
X	sibwp = wp;
X	while (sibwp->siblings) {
X		sibwp = sibwp->siblings;
X		GsExposeArea(sibwp, wp->x - bs, wp->y - bs,
X			wp->width + bs * 2, wp->height + bs * 2);
X	}
X}
X
X
X/*
X * Map the window to possibly make it and its children visible on the screen.
X * This is a recursive routine which decrements the unmapcount values for
X * this window and all of its children, and causes exposure events for
X * those windows which become visible.
X */
Xvoid
XGsWpMapWindow(wp)
X	GR_WINDOW	*wp;		/* window to be unmapped */
X{
X	if (wp == rootwp) {
X		GsError(GR_ERROR_ILLEGAL_ON_ROOT_WINDOW, wp->id);
X		return;
X	}
X
X	if (wp->unmapcount)
X		wp->unmapcount--;
X
X	if (wp->unmapcount == 0) {
X		GsCheckMouseWindow();
X		GsCheckFocusWindow();
X		GsCheckCursor();
X	}
X
X	/*
X	 * If the window is an output window and just became visible,
X	 * then draw its border, clear it to the background color, and
X	 * generate an exposure event.
X	 */
X	if (wp->output && (wp->unmapcount == 0)) {
X		GsDrawBorder(wp);
X		GsWpClearWindow(wp, 0, 0, wp->width, wp->height, GR_TRUE);
X	}
X
X	/*
X	 * Do the same thing for the children.
X	 */
X	for (wp = wp->children; wp; wp = wp->siblings)
X		GsWpMapWindow(wp);
X}
X
X
X/*
X * Destroy the specified window, and all of its children.
X * This is a recursive routine.
X */
Xvoid
XGsWpDestroyWindow(wp)
X	GR_WINDOW	*wp;		/* window to be destroyed */
X{
X	GR_WINDOW	*prevwp;	/* previous window pointer */
X	GR_EVENT_CLIENT	*ecp;		/* selections for window */
X
X	if (wp == rootwp) {
X		GsError(GR_ERROR_ILLEGAL_ON_ROOT_WINDOW, wp->id);
X		return;
X	}
X
X	/*
X	 * Unmap the window first.
X	 */
X	if (wp->unmapcount == 0)
X		GsWpUnmapWindow(wp);
X
X	/*
X	 * Destroy all children.
X	 */
X	while (wp->children)
X		GsWpDestroyWindow(wp->children);
X
X	/*
X	 * Free all client selection structures.
X	 */
X	while (wp->eventclients) {
X		ecp = wp->eventclients;
X		wp->eventclients = ecp->next;
X		free(ecp);
X	}
X
X	/*
X	 * Free any cursor associated with the window.
X	 */
X	if (wp->cursor->usecount-- == 1) {
X		free(wp->cursor);
X		wp->cursor = NULL;
X	}
X
X	/*
X	 * Remove this window from the child list of its parent.
X	 */
X	prevwp = wp->parent->children;
X	if (prevwp == wp)
X		wp->parent->children = wp->siblings;
X	else {
X		while (prevwp->siblings != wp)
X			prevwp = prevwp->siblings;
X		prevwp->siblings = wp->siblings;
X	}
X	wp->siblings = NULL;
X
X	/*
X	 * Remove this window from the complete list of windows.
X	 */
X	prevwp = listwp;
X	if (prevwp == wp)
X		listwp = wp->next;
X	else {
X		while (prevwp->next != wp)
X			prevwp = prevwp->next;
X		prevwp->next = wp->next;
X	}
X	wp->next = NULL;
X
X	/*
X	 * Forget various information if they related to this window.
X	 * Then finally free the structure.
X	 */
X	if (wp == clipwp)
X		clipwp = NULL;
X	if (wp == grabbuttonwp)
X		grabbuttonwp = NULL;
X	if (wp == cachewp) {
X		cachewindowid = 0;
X		cachewp = NULL;
X	}
X	if (wp == focuswp) {
X		focusfixed = GR_FALSE;
X		focuswp = rootwp;
X	}
X
X	free(wp);
X}
X
X
X/*
X * Clear the specified area of a window and possibly make an exposure event.
X * This sets the area window to its background color.  If the exposeflag is
X * nonzero, then this also creates an exposure event for the window.
X */
Xvoid
XGsWpClearWindow(wp, x, y, width, height, exposeflag)
X	GR_WINDOW	*wp;		/* window structure */
X	GR_BOOL		exposeflag;	/* nonzero to cause an exposure */
X{
X	if (wp->unmapcount || !wp->output)
X		return;
X
X	/*
X	 * Reduce the arguments so that they actually lie within the window.
X	 */
X	if (x < 0) {
X		width += x;
X		x = 0;
X	}
X	if (y < 0) {
X		height += y;
X		y = 0;
X	}
X	if (x + width > wp->width)
X		width = wp->width - x;
X	if (y + height > wp->height)
X		height = wp->height - y;
X
X	/*
X	 * Now see if the region is really in the window.  If not, then
X	 * do nothing.
X	 */
X	if ((x >= wp->width) || (y >= wp->height) || (width <= 0) ||
X		(height <= 0))
X			return;
X
X	/*
X	 * Draw the background of the window.
X	 * Invalidate the current graphics context since
X	 * we are changing the foreground color and mode.
X	 */
X	GsSetClipWindow(wp);
X	curgcp = NULL;
X	GdSetMode(GR_MODE_SET);
X	GdSetForeground(wp->background);
X	GdFillRect(wp->x + x, wp->y + y, width, height);
X
X	/*
X	 * Now do the exposure if required.
X	 */
X	if (exposeflag)
X		GsDeliverExposureEvent(wp, x, y, width, height);
X}
X
X
X/*
X * Handle the exposing of the specified absolute region of the screen,
X * starting with the specified window.  That window and all of its
X * children will be redrawn and/or exposure events generated if they
X * overlap the specified area.  This is a recursive routine.
X */
Xvoid
XGsExposeArea(wp, rootx, rooty, width, height)
X	GR_WINDOW	*wp;		/* window which was exposed */
X	GR_COORD	rootx;		/* absolute x coordinate */
X	GR_COORD	rooty;		/* absolute y coordinate */
X	GR_SIZE		width;		/* width of area */
X	GR_SIZE		height;		/* height of area */
X{
X	if (!wp->output || wp->unmapcount)
X		return;
X
X	/*
X	 * First see if the area overlaps the window including the border.
X	 * If not, then there is nothing more to do.
X	 */
X	if ((rootx >= wp->x + wp->width + wp->bordersize) ||
X		(rooty >= wp->y + wp->height + wp->bordersize) ||
X		(rootx + width <= wp->x - wp->bordersize) ||
X		(rooty + height <= wp->y - wp->bordersize))
X			return;
X
X	/*
X	 * The area does overlap the window.  See if the area overlaps
X	 * the border, and if so, then redraw it.
X	 */
X	if ((rootx < wp->x) || (rooty < wp->y) ||
X		(rootx + width > wp->x + wp->width) ||
X		(rooty + height > wp->y + wp->height))
X			GsDrawBorder(wp);
X
X	/*
X	 * Now clear the window itself in the specified area,
X	 * which might cause an exposure event.
X	 */
X	GsWpClearWindow(wp, rootx - wp->x, rooty - wp->y,
X		width, height, GR_TRUE);
X
X	/*
X	 * Now do the same for all the children.
X	 */
X	for (wp = wp->children; wp; wp = wp->siblings)
X		GsExposeArea(wp, rootx, rooty, width, height);
X}
X
X
X/*
X * Draw the border of a window if there is one.
X * Note: To allow the border to be drawn with the correct clipping,
X * we temporarily grow the size of the window to include the border.
X */
Xvoid
XGsDrawBorder(wp)
X	GR_WINDOW	*wp;		/* window needing border drawn */
X{
X	GR_COORD	lminx;		/* left edge minimum x */
X	GR_COORD	rminx;		/* right edge minimum x */
X	GR_COORD	tminy;		/* top edge minimum y */
X	GR_COORD	bminy;		/* bottom edge minimum y */
X	GR_COORD	topy;		/* top y value of window */
X	GR_COORD	boty;		/* bottom y value of window */
X	GR_SIZE		width;		/* original width of window */
X	GR_SIZE		height;		/* original height of window */
X	GR_SIZE		bs;		/* border size */
X
X	bs = wp->bordersize;
X	if (bs <= 0)
X		return;
X
X	width = wp->width;
X	height = wp->height;
X	lminx = wp->x - bs;
X	rminx = wp->x + width;
X	tminy = wp->y - bs;
X	bminy = wp->y + height;
X	topy = wp->y;
X	boty = bminy - 1;
X 
X	wp->x -= bs;
X	wp->y -= bs;
X	wp->width += (bs * 2);
X	wp->height += (bs * 2);
X	wp->bordersize = 0;
X
X	clipwp = NULL;
X	GsSetClipWindow(wp);
X	curgcp = NULL;
X	GdSetMode(GR_MODE_SET);
X	GdSetForeground(wp->bordercolor);
X
X	if (bs == 1) {
X		GdLine(lminx, tminy, rminx, tminy);
X		GdLine(lminx, bminy, rminx, bminy);
X		GdLine(lminx, topy, lminx, boty);
X		GdLine(rminx, topy, rminx, boty);
X	} else {
X		GdFillRect(lminx, tminy, width + bs * 2, bs);
X		GdFillRect(lminx, bminy, width + bs * 2, bs);
X		GdFillRect(lminx, topy, bs, height);
X		GdFillRect(rminx, topy, bs, height);
X	}
X
X	/*
X	 * Restore the true window size.
X	 * Forget the currently clipped window since we messed it up.
X	 */
X	wp->x += bs;
X	wp->y += bs;
X	wp->width -= (bs * 2);
X	wp->height -= (bs * 2);
X	wp->bordersize = bs;
X	clipwp = NULL;
X}
X
X
X/*
X * Check to see if the first window overlaps the second window.
X */
XGR_BOOL
XGsCheckOverlap(topwp, botwp)
X	GR_WINDOW	*topwp;		/* window on top */
X	GR_WINDOW	*botwp;		/* window on bottom */
X{
X	GR_COORD	minx1;
X	GR_COORD	miny1;
X	GR_COORD	maxx1;
X	GR_COORD	maxy1;
X	GR_COORD	minx2;
X	GR_COORD	miny2;
X	GR_COORD	maxx2;
X	GR_COORD	maxy2;
X	GR_SIZE		bs;
X
X	if (!topwp->output || topwp->unmapcount || botwp->unmapcount)
X		return GR_FALSE;
X
X	bs = topwp->bordersize;
X	minx1 = topwp->x - bs;
X	miny1 = topwp->y - bs;
X	maxx1 = topwp->x + topwp->width + bs - 1;
X	maxy1 = topwp->y + topwp->height + bs - 1;
X
X	bs = botwp->bordersize;
X	minx2 = botwp->x - bs;
X	miny2 = botwp->y - bs;
X	maxx2 = botwp->x + botwp->width + bs - 1;
X	maxy2 = botwp->y + botwp->height + bs - 1;
X
X	if ((minx1 > maxx2) || (minx2 > maxx1) || (miny1 > maxy2)
X		|| (miny2 > maxy1))
X			return GR_FALSE;
X
X	return GR_TRUE;
X}
X
X
X/*
X * Return a pointer to the window structure with the specified window id.
X * Returns NULL if the window does not exist, with an error set.
X */
XGR_WINDOW *
XGsFindWindow(id)
X	GR_WINDOW_ID	id;		/* id of window to find */
X{
X	GR_WINDOW	*wp;		/* current window pointer */
X
X	/*
X	 * See if this is the root window or the same window as last time.
X	 */
X	if (id == GR_ROOT_WINDOW_ID)
X		return rootwp;
X
X	if ((id == cachewindowid) && id)
X		return cachewp;
X
X	/*
X	 * No, search for it and cache it for future calls.
X	 */
X	for (wp = listwp; wp; wp = wp->next) {
X		if (wp->id == id) {
X			cachewindowid = id;
X			cachewp = wp;
X			return wp;
X		}
X	}
X
X	GsError(GR_ERROR_BAD_WINDOW_ID, id);
X
X	return NULL;
X}
X
X
X/*
X * Return a pointer to the graphics context with the specified id.
X * Returns NULL if the graphics context does not exist, with an
X * error saved.
X */
XGR_GC *
XGsFindGC(gcid)
X	GR_GC_ID	gcid;		/* id of graphics context to find */
X{
X	GR_GC		*gcp;		/* current graphics context pointer */
X
X	/*
X	 * See if this is the same graphics context as last time.
X	 */
X	if ((gcid == cachegcid) && gcid)
X		return cachegcp;
X
X	/*
X	 * No, search for it and cache it for future calls.
X	 */
X	for (gcp = listgcp; gcp; gcp = gcp->next) {
X		if (gcp->id == gcid) {
X			cachegcid = gcid;
X			cachegcp = gcp;
X			return gcp;
X		}
X	}
X
X	GsError(GR_ERROR_BAD_GC_ID, gcid);
X
X	return NULL;
X}
X
X
X/*
X * Prepare to do drawing in a window or pixmap using the specified
X * graphics context.  Returns the window or pixmap pointer if successful,
X * and the type of drawing id that was supplied.  Returns the special value
X * GR_DRAW_TYPE_NONE if an error is generated, or if drawing is useless.
X */
XGR_DRAW_TYPE
XGsPrepareDrawing(id, gcid, retwp, retpixptr)
X	GR_DRAW_ID	id;		/* drawing id to be used */
X	GR_GC_ID	gcid;		/* graphics id to be used */
X	GR_WINDOW	**retwp;	/* returned window pointer (or NULL) */
X	GR_PIXMAP	**retpixptr;	/* returned pixmap pointer (or NULL) */
X{
X	GR_WINDOW	*wp;		/* found window */
X	GR_GC		*gcp;		/* found graphics context */
X
X	*retwp = NULL;
X	*retpixptr = NULL;
X
X	gcp = GsFindGC(gcid);
X	if (gcp == NULL)
X		return GR_DRAW_TYPE_NONE;
X
X	/*
X	 * Future: look for pixmap id too.
X	 * For now, can only have window ids.
X	 */
X	wp = GsFindWindow(id);
X	if (wp == NULL)
X		return GR_DRAW_TYPE_NONE;
X
X	if (!wp->output) {
X		GsError(GR_ERROR_INPUT_ONLY_WINDOW, id);
X		return GR_DRAW_TYPE_NONE;
X	}
X
X	if (wp->unmapcount)
X		return GR_DRAW_TYPE_NONE;
X
X	/*
X	 * If the window is not the currently clipped one, then make it the
X	 * current one and define its clip rectangles.
X	 */
X	if (wp != clipwp)
X		GsSetClipWindow(wp);
X
X	/*
X	 * If the graphics context is not the current one, then
X	 * make it the current one and remember to update it.
X	 */
X	if (gcp != curgcp) {
X		curgcp = gcp;
X		gcp->changed = GR_TRUE;
X	}
X
X	/*
X	 * If the graphics context has been changed, then tell the
X	 * device driver about it.
X	 */
X	if (gcp->changed) {
X		GdSetForeground(gcp->foreground);
X		GdSetBackground(gcp->background);
X		GdSetMode(gcp->mode);
X		GdSetUseBackground(gcp->usebackground);
X		gcp->changed = GR_FALSE;
X	}
X
X	*retwp = wp;
X	return GR_DRAW_TYPE_WINDOW;
X}
X
X
X/*
X * Prepare the specified window for drawing into it.
X * This sets up the clipping regions to just allow drawing into it.
X * Returns NULL if the drawing is illegal (with an error generated),
X * or if the window is not mapped.
X */
XGR_WINDOW *
XGsPrepareWindow(wid)
X	GR_WINDOW_ID	wid;		/* window id to be used */
X{
X	GR_WINDOW	*wp;		/* found window */
X
X	wp = GsFindWindow(wid);
X	if (wp == NULL)
X		return NULL;
X	
X	if (!wp->output) {
X		GsError(GR_ERROR_INPUT_ONLY_WINDOW, wid);
X		return NULL;
X	}
X
X	if (wp->unmapcount)
X		return NULL;
X
X	if (wp != clipwp)
X		GsSetClipWindow(wp);
X
X	return wp;
X}
X
X
X/*
X * Set the clip rectangles for a window taking into account other
X * windows that may be obscuring it.  The windows that may be obscuring
X * this one are the siblings of each direct ancestor which are higher
X * in priority than those ancestors.  Also, each parent limits the visible
X * area of the window.  The clipping is not done if it is already up to
X * date of if the window is not outputtable.
X */
Xvoid
XGsSetClipWindow(wp)
X	GR_WINDOW	*wp;		/* window to set clipping for */
X{
X	GR_WINDOW	*pwp;		/* parent window */
X	GR_WINDOW	*sibwp;		/* sibling windows */
X	GR_RECT		*clip;		/* first clip rectangle */
X	GR_COUNT	count;		/* number of clip rectangles */
X	GR_COUNT	newcount;	/* number of new rectangles */
X	GR_COUNT	i;		/* current index */
X	GR_COORD	minx;		/* minimum clip x coordinate */
X	GR_COORD	miny;		/* minimum clip y coordinate */
X	GR_COORD	maxx;		/* maximum clip x coordinate */
X	GR_COORD	maxy;		/* maximum clip y coordinate */
X	GR_COORD	diff;		/* difference in coordinates */
X	GR_SIZE		bs;		/* border size */
X	GR_BOOL		toomany;	/* TRUE if too many clip rects */
X	GR_RECT		cliprects[GR_MAX_CLIPRECTS];	/* clip rectangles */
X
X	if (wp->unmapcount || !wp->output || (wp == clipwp))
X		return;
X
X	clipwp = wp;
X
X	/*
X	 * Start with the rectangle for the complete window.
X	 * We will then cut pieces out of it as needed.
X	 */
X	count = 1;
X	clip = cliprects;
X	clip->x = wp->x;
X	clip->y = wp->y;
X	clip->width = wp->width;
X	clip->height = wp->height;
X
X	/*
X	 * First walk upwards through all parent windows,
X	 * and restrict the visible part of this window to the part
X	 * that shows through all of those parent windows.
X	 */
X	pwp = wp;
X	while (pwp != rootwp) {
X		pwp = pwp->parent;
X
X		diff = pwp->x - clip->x;
X		if (diff > 0) {
X			clip->width -= diff;
X			clip->x = pwp->x;
X		}
X
X		diff = (pwp->x + pwp->width) - (clip->x + clip->width);
X		if (diff < 0)
X			clip->width += diff;
X
X		diff = pwp->y - clip->y;
X		if (diff > 0) {
X			clip->height -= diff;
X			clip->y = pwp->y;
X		}
X
X		diff = (pwp->y + pwp->height) - (clip->y + clip->height);
X		if (diff < 0)
X			clip->height += diff;
X	}
X
X	/*
X	 * If the window is completely clipped out of view, then
X	 * set the clipping region to indicate that.
X	 */
X	if ((clip->width <= 0) || (clip->height <= 0)) {
X		GdSetClipRects(1, cliprects);
X		return;
X	}
X
X	/*
X	 * Now examine all windows that obscure this window, and
X	 * for each obscuration, break up the clip rectangles into
X	 * the smaller pieces that are still visible.  The windows
X	 * that can obscure us are the earlier siblings of all of
X	 * our parents.
X 	 */
X	toomany = GR_FALSE;
X	pwp = wp;
X	while (pwp != rootwp) {
X		wp = pwp;
X		pwp = wp->parent;
X		sibwp = pwp->children;
X		for (; sibwp != wp; sibwp = sibwp->siblings) {
X			if (sibwp->unmapcount || !sibwp->output)
X				continue;
X
X			bs = sibwp->bordersize;
X			minx = sibwp->x - bs;
X			miny = sibwp->y - bs;
X			maxx = sibwp->x + sibwp->width + bs - 1;
X			maxy = sibwp->y + sibwp->height + bs - 1;
X
X			newcount = count;
X			for (i = 0; i < count; i++) {
X				if (newcount > GR_MAX_CLIPRECTS - 3) {
X					toomany = GR_TRUE;
X					break;
X				}
X				newcount += GsSplitClipRect(&cliprects[i],
X					&cliprects[newcount],
X					minx, miny, maxx, maxy);
X			}
X			count = newcount;
X		}
X	}
X
X	if (toomany) {
X		GsError(GR_ERROR_TOO_MUCH_CLIPPING, wp->id);
X		clip->x = 0;
X		clip->y = 0;
X		clip->width = -1;
X		clip->height = -1;
X		count = 1;
X	}
X
X	/*
X	 * Set the clip rectangles.
X	 */
X	GdSetClipRects(count, cliprects);
X}
X
X
X/*
X * Check the specified clip rectangle against the specified rectangular
X * region, and reduce it or split it up into multiple clip rectangles
X * such that the specified region is not contained in any of the clip
X * rectangles.  The source clip rectangle can be modified in place, and
X * in addition more clip rectangles can be generated, which are placed in
X * the indicated destination location.  The maximum number of new clip
X * rectangles needed is 3.  Returns the number of clip rectangles added.
X * If the source clip rectangle is totally obliterated, it is set to an
X * impossible region and 0 is returned.  When splits are done, we prefer
X * to create wide regions instead of high regions.
X */
XGR_COUNT
XGsSplitClipRect(srcrect, destrect, minx, miny, maxx, maxy)
X	GR_RECT		*srcrect;	/* source clip rectangle */
X	GR_RECT		*destrect;	/* source dest rectangle */
X	GR_COORD	minx;		/* minimum x coordinate of region */
X	GR_COORD	miny;		/* minimum y coordinate of region */
X	GR_COORD	maxx;		/* maximum x coordinate of region */
X	GR_COORD	maxy;		/* maximum y coordinate of region */
X{
X	GR_COORD	x;
X	GR_COORD	y;
X	GR_SIZE		width;
X	GR_SIZE		height;
X	GR_COORD	dx;
X	GR_COORD	dy;
X	int		gaps;
X
X	/*
X	 * First see if there is any overlap at all.
X	 * If not, then nothing to do.
X	 */
X	x = srcrect->x;
X	y = srcrect->y;
X	width = srcrect->width;
X	height = srcrect->height;
X
X	if ((minx > maxx) || (miny > maxy) || (maxx < x) || (maxy < y) ||
X		(x + width <= minx) || (y + height <= miny))
X			return 0;
X
X	/*
X	 * There is an overlap.  Calculate a value to differentiate
X	 * various cases, and then handle each case separately.  The
X	 * cases are classified on whether there are gaps on the left,
X	 * right, top, and bottom sides of the clip rectangle.
X	 */
X	gaps = 0;
X	if (x < minx)
X		gaps |= GAPVAL(1, 0, 0, 0);
X	if (x + width - 1 > maxx)
X		gaps |= GAPVAL(0, 1, 0, 0);
X	if (y < miny)
X		gaps |= GAPVAL(0, 0, 1, 0);
X	if (y + height - 1 > maxy)
X		gaps |= GAPVAL(0, 0, 0, 1);
X
X	switch (gaps) {
X		case GAPVAL(0, 0, 0, 0):	/* no gaps at all */
X			srcrect->x = 0;
X			srcrect->y = 0;
X			srcrect->width = 0;
X			srcrect->height = 0;
X			return 0;
X
X		case GAPVAL(0, 0, 0, 1):	/* gap on bottom */
X			dy = maxy - y + 1;
X			srcrect->y += dy;
X			srcrect->height -= dy;
X			return 0;
X
X		case GAPVAL(0, 0, 1, 0):	/* gap on top */
X			srcrect->height = miny - y;
X			return 0;
X
X		case GAPVAL(0, 0, 1, 1):	/* gap on top, bottom */
X			srcrect->height = miny - y;
X			destrect->x = x;
X			destrect->width = width;
X			destrect->y = maxy + 1;
X			destrect->height = y + height - maxy - 1;
X			return 1;
X
X		case GAPVAL(0, 1, 0, 0):	/* gap on right */
X			dx = maxx - x + 1;
X			srcrect->x += dx;
X			srcrect->width -= dx;
X			return 0;
X
X		case GAPVAL(0, 1, 0, 1):	/* gap on right, bottom */
X			dx = maxx - x + 1;
X			srcrect->x += dx;
X			srcrect->width -= dx;
X			srcrect->height = maxy - y + 1;
X			destrect->x = x;
X			destrect->width = width;
X			destrect->y = maxy + 1;
X			destrect->height = y + height - maxy - 1;
X			return 1;
X
X		case GAPVAL(0, 1, 1, 0):	/* gap on right, top */
X			dx = maxx - x + 1;
X			srcrect->height = miny - y;
X			destrect->x = x + dx;
X			destrect->width = width - dx;
X			destrect->y = miny;
X			destrect->height = y + height - miny;
X			return 1;
X
X		case GAPVAL(0, 1, 1, 1):	/* gap on right, top, bottom */
X			dx = maxx - x + 1;
X			srcrect->height = miny - y;
X			destrect->x = x;
X			destrect->width = width;
X			destrect->y = maxy + 1;
X			destrect->height = y + height - maxy - 1;
X			destrect++;
X			destrect->x = x + dx;
X			destrect->width = width - dx;
X			destrect->y = miny;
X			destrect->height = maxy - miny + 1;
X			return 2;
X
X		case GAPVAL(1, 0, 0, 0):	/* gap on left */
X			srcrect->width = minx - x;
X			return 0;
X
X		case GAPVAL(1, 0, 0, 1):	/* gap on left, bottom */
X			srcrect->width = minx - x;
X			srcrect->height = maxy - y + 1;
X			destrect->x = x;
X			destrect->width = width;
X			destrect->y = maxy + 1;
X			destrect->height = y + height - maxy - 1;
X			return 1;
X
X		case GAPVAL(1, 0, 1, 0):	/* gap on left, top */
X			srcrect->height = miny - y;
X			destrect->x = x;
X			destrect->width = minx - x;
X			destrect->y = miny;
X			destrect->height = y + height - miny;
X			return 1;
X
X		case GAPVAL(1, 0, 1, 1):	/* gap on left, top, bottom */
X			srcrect->height = miny - y;
X			destrect->x = x;
X			destrect->width = minx - x;
X			destrect->y = miny;
X			destrect->height = maxy - miny + 1;
X			destrect++;
X			destrect->x = x;
X			destrect->width = width;
X			destrect->y = maxy + 1;
X			destrect->height = y + height - maxy - 1;
X			return 2;
X
X		case GAPVAL(1, 1, 0, 0):	/* gap on left, right */
X			destrect->x = maxx + 1;
X			destrect->width = x + width - maxx - 1;
X			destrect->y = y;
X			destrect->height = height;
X			srcrect->width = minx - x;
X			return 1;
X
X		case GAPVAL(1, 1, 0, 1):	/* gap on left, right, bottom */
X			dy = maxy - y + 1;
X			srcrect->y += dy;
X			srcrect->height -= dy;
X			destrect->x = x;
X			destrect->width = minx - x;
X			destrect->y = y;
X			destrect->height = dy;
X			destrect++;
X			destrect->x = maxx + 1;
X			destrect->width = x + width - maxx - 1;
X			destrect->y = y;
X			destrect->height = dy;
X			return 2;
X
X		case GAPVAL(1, 1, 1, 0):	/* gap on left, right, top */
X			srcrect->height = miny - y;
X			destrect->x = x;
X			destrect->width = minx - x;
X			destrect->y = miny;
X			destrect->height = y + height - miny;
X			destrect++;
X			destrect->x = maxx + 1;
X			destrect->width = x + width - maxx - 1;
X			destrect->y = miny;
X			destrect->height = y + height - miny;
X			return 2;
X
X		case GAPVAL(1, 1, 1, 1):	/* gap on all sides */
X			srcrect->height = miny - y;
X			destrect->x = x;
X			destrect->width = minx - x;
X			destrect->y = miny;
X			destrect->height = maxy - miny + 1;
X			destrect++;
X			destrect->x = maxx + 1;
X			destrect->width = x + width - maxx - 1;
X			destrect->y = miny;
X			destrect->height = maxy - miny + 1;
X			destrect++;
X			destrect->x = x;
X			destrect->width = width;
X			destrect->y = maxy + 1;
X			destrect->height = y + height - maxy - 1;
X			return 3;
X	}
X}
X
X
X/*
X * Find the window which is currently visible for the specified coordinates.
X * This just walks down the window tree looking for the deepest mapped
X * window which contains the specified point.  If the coordinates are
X * off the screen, the root window is returned.
X */
XGR_WINDOW *
XGsFindVisibleWindow(x, y)
X	GR_COORD	x;		/* x position of cursor */
X	GR_COORD	y;		/* y position of cursor */
X{
X	GR_WINDOW	*wp;		/* current window */
X	GR_WINDOW	*retwp;		/* returned window */
X
X	wp = rootwp;
X	retwp = wp;
X	while (wp) {
X		if ((wp->unmapcount == 0) && (wp->x <= x) && (wp->y <= y) &&
X			(wp->x + wp->width > x) && (wp->y + wp->height > y))
X		{
X			retwp = wp;
X			wp = wp->children;
X			continue;
X		}
X		wp = wp->siblings;
X	}
X	return retwp;
X}
X
X
X/*
X * Check to see if the cursor shape is the correct shape for its current
X * location.  If not, its shape is changed.
X */
Xvoid
XGsCheckCursor()
X{
X	GR_WINDOW	*wp;		/* window cursor is in */
X	GR_CURSOR	*cp;		/* cursor definition */
X
X	/*
X	 * Get the cursor at its current position, and if it is not the
X	 * currently defined one, then set the new cursor.  However,
X	 * if the pointer is currently grabbed, then leave it alone.
X	 */
X	wp = grabbuttonwp;
X	if (wp == NULL)
X		wp = mousewp;
X
X	cp = wp->cursor;
X	if (cp == curcursor)
X		return;
X
X	/*
X	 * It needs redefining, so do it.
X	 */
X	curcursor = cp;
X	GdSetCursor(cp->width, cp->height, cp->foreground,
X		cp->background, cp->fgbitmap, cp->bgbitmap);
X}
X
X
X/*
X * Check to see if the window the mouse is currently in has changed.
X * If so, generate enter and leave events as required.  The newest
X * mouse window is remembered in mousewp.  However, do not change the
X * window while it is grabbed.
X */
Xvoid
XGsCheckMouseWindow()
X{
X	GR_WINDOW	*wp;		/* newest window for mouse */
X
X	wp = grabbuttonwp;
X	if (wp == NULL)
X		wp = GsFindVisibleWindow(cursorx, cursory);
X	if (wp == mousewp)
X		return;
X
X	GsDeliverGeneralEvent(mousewp, GR_EVENT_TYPE_MOUSE_EXIT);
X
X	mousewp = wp;
X
X	GsDeliverGeneralEvent(wp, GR_EVENT_TYPE_MOUSE_ENTER);
X}
X
X
X/*
X * Determine the current focus window for the current mouse coordinates.
X * The mouse coordinates only matter if the focus is not fixed.  Otherwise,
X * the selected window is dependant on the window which wants keyboard
X * events.  This also sets the current focus for that found window.
X * The window with focus is remembered in focuswp.
X */
Xvoid
XGsCheckFocusWindow()
X{
X	GR_WINDOW		*wp;		/* current window */
X	GR_EVENT_CLIENT		*ecp;		/* current event client */
X	GR_EVENT_MASK		eventmask;	/* event mask */
X
X	if (focusfixed)
X		return;
X
X	eventmask = GR_EVENT_MASK_KEY_DOWN;
X
X	/*
X	 * Walk upwards from the current window containing the mouse
X	 * looking for the first window which would accept a keyboard event.
X	 */
X	for (wp = mousewp; ;wp = wp->parent) {
X		for (ecp = wp->eventclients; ecp; ecp = ecp->next) {
X			if (ecp->eventmask & eventmask) {
X				GsWpSetFocus(wp);
X				return;
X			}
X		}
X		if ((wp == rootwp) || (wp->nopropmask & eventmask)) {
X			GsWpSetFocus(rootwp);
X			return;
X		}
X	}
X}
X
X
X/*
X * Set the input focus to the specified window.
X * This generates focus out and focus in events as necessary.
X */
Xvoid
XGsWpSetFocus(wp)
X	GR_WINDOW	*wp;		/* window to get the focus */
X{
X	if (wp == focuswp)
X		return;
X
X	GsDeliverGeneralEvent(focuswp, GR_EVENT_TYPE_FOCUS_OUT);
X
X	focuswp = wp;
X
X	GsDeliverGeneralEvent(wp, GR_EVENT_TYPE_FOCUS_IN);
X}
X
X/* END CODE */
END_OF_FILE
if test 26728 -ne `wc -c <'mini-x/server/serv_util.c'`; then
    echo shar: \"'mini-x/server/serv_util.c'\" unpacked with wrong size!
fi
# end of 'mini-x/server/serv_util.c'
fi
echo shar: End of archive 7 \(of 9\).
cp /dev/null ark7isdone
MISSING=""
for I in 1 2 3 4 5 6 7 8 9 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked all 9 archives.
    rm -f ark[1-9]isdone ark[1-9][0-9]isdone
else
    echo You still need to unpack the following archives:
    echo "        " ${MISSING}
fi
##  End of shell archive.
exit 0

dbell@pdact.pd.necisa.oz.au (David I. Bell) (04/22/91)

#! /bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of archive 8 (of 9)."
# Contents:  mini-x/server/serv_func.c
# Wrapped by dbell@elm on Mon Apr 22 11:21:51 1991
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'mini-x/server/serv_func.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'mini-x/server/serv_func.c'\"
else
echo shar: Extracting \"'mini-x/server/serv_func.c'\" \(33072 characters\)
sed "s/^X//" >'mini-x/server/serv_func.c' <<'END_OF_FILE'
X/*
X * Copyright (c) 1991 David I. Bell
X * Permission is granted to use, distribute, or modify this source,
X * provided that this copyright notice remains intact.
X *
X * Graphics server top level routines to execute client functions.
X * These functions are the server side of the client GrXXXX functions.
X * Clients should not call these GsXXXX functions, but should only call
X * the GrXXXX functions.  In this way, when the server becomes a separate
X * process, the client code will not need changes.
X *
X * When the server is its own process, these functions will be called by
X * a dispatcher routine which can read messages from multiple clients.
X * The dispatcher should set the curclient variable to the client which
X * is being executed, and the curfunc variable to the current function name.
X * Then the setting of curfunc throughout this file can be removed.
X */
X#include <stdio.h>
X#include "graph_serv.h"
X
X
X/*
X * Open a connection from a new client to the server.
X * This returns the first resource id to be allocated by the client.
X * On an error, zero is returned.
X */
XGR_ID
XGsOpen()
X{
X	curfunc = "GrOpen";		/* temporary */
X
X	if (GsInitialize())
X		return 0;
X
X	curclient = &clients[0];
X	curclient->num = 1;
X	curclient->infd = -1;		/* not used yet */
X	curclient->outfd = -1;
X	curclient->allocid = GR_ID_BASE(curclient->num);
X	curclient->errorevent.type = GR_EVENT_TYPE_NONE;
X	curclient->eventhead = NULL;
X	curclient->eventhead = NULL;
X
X	return curclient->allocid;
X}
X
X
X/*
X * Close the connection to the server.
X */
Xvoid
XGsClose()
X{
X	curfunc = "GrClose";		/* temporary */
X
X	/* MUST RELEASE ALL RESOURCES ALLOCATED BY THIS CLIENT */
X
X	curclient->num = 0;
X	curclient->infd = -1;		/* not used yet */
X	curclient->outfd = -1;
X
X	GsTerminate();
X}
X
X
X/*
X * Flush graphics to the device.
X */
Xvoid
XGsFlush()
X{
X	curfunc = "GrFlush";		/* temporary */
X
X	GdFlush();
X}
X
X
X/*
X * Return information about the screen for clients to use.
X */
Xvoid
XGsGetScreenInfo(sip)
X	GR_SCREEN_INFO	*sip;		/* pointer to screen info */
X{
X	curfunc = "GrGetScreenInfo";	/* temporary */
X
X	*sip = sinfo;
X}
X
X
X/*
X * Return the size of a text string for the font in a graphics context.
X * This is the width of the string, the height of the string,
X * and the height above the bottom of the font of the baseline for the font.
X */
Xvoid
XGsGetGCTextSize(gc, cp, len, retwidth, retheight, retbase)
X	GR_GC_ID	gc;		/* graphics context containing font */
X	GR_CHAR		*cp;		/* address of text string */
X	GR_SIZE		len;		/* length of text string */
X	GR_SIZE		*retwidth;	/* returned width of string */
X	GR_SIZE		*retheight;	/* returned height of string */
X	GR_SIZE		*retbase;	/* returned height of baseline */
X{
X	GR_GC		*gcp;		/* graphics context */
X	GR_FONT_INFO	*fip;		/* current font info */
X
X	curfunc = "GrGCTextSize";	/* temporary */
X
X	gcp = GsFindGC(gc);
X	if (gcp == NULL) {
X		*retwidth = 0;
X		*retheight = 1;
X		*retbase = 0;
X		return;
X	}
X
X	fip = &curfont;
X	if (fip->font != gcp->font)
X		GdGetFontInfo(gcp->font, fip);
X
X	*retheight = fip->height;
X	*retbase = fip->baseline;
X	if (fip->fixed) {
X		*retwidth = fip->maxwidth * len;
X		return;
X	}
X
X	*retwidth = 0;
X	while (len-- > 0)
X		*retwidth += fip->widths[*cp++];
X}
X
X
X/*
X * Return the next waiting event for a client, or wait for one if there
X * is none yet.  The event is copied into the specified structure, and
X * then is moved from the event queue to the free event queue.  If there
X * is an error event waiting, it is delivered before any other events.
X */
Xvoid
XGsGetNextEvent(ep)
X	GR_EVENT	*ep;		/* pointer to element to return */
X{
X	GR_EVENT_LIST	*elp;		/* current element list */
X
X	curfunc = "GrGetNextEvent";	/* temporary */
X
X	if (curclient->errorevent.type == GR_EVENT_TYPE_ERROR) {
X		*((GR_EVENT_ERROR *) ep) = curclient->errorevent;
X		curclient->errorevent.type = GR_EVENT_TYPE_NONE;
X		return;
X	}
X
X	if (curclient->eventhead == NULL)
X		GsCheckEvent(GR_TRUE);
X	if (curclient->eventhead == NULL) {
X		ep->type = GR_EVENT_TYPE_NONE;
X		return;
X	}
X	elp = curclient->eventhead;
X	*ep = elp->event;
X	curclient->eventhead = elp->next;
X	if (curclient->eventhead == NULL)
X		curclient->eventtail = NULL;
X	elp->next = eventfree;
X	eventfree = elp;
X}
X
X
X/*
X * Peek at the event queue for the current client to see if there are any
X * outstanding events.  Returns the event at the head of the queue, or
X * else a null event type.  The event is still left in the queue, however.
X */
Xvoid
XGsPeekEvent(ep)
X	GR_EVENT	*ep;		/* pointer to element to return */
X{
X	curfunc = "GrPeekEvent";	/* temporary */
X
X	if (curclient->errorevent.type == GR_EVENT_TYPE_ERROR) {
X		*((GR_EVENT_ERROR *) ep) = curclient->errorevent;
X		return;
X	}
X
X	if (curclient->eventhead == NULL)
X		GsCheckEvent(GR_FALSE);
X
X	if (curclient->eventhead) {
X		*ep = curclient->eventhead->event;
X		return;
X	}
X	ep->type = GR_EVENT_TYPE_NONE;
X}
X
X
X/*
X * Return information about a window id.
X */
Xvoid
XGsGetWindowInfo(wid, infoptr)
X	GR_WINDOW_ID		wid;		/* window to find out about */
X	GR_WINDOW_INFO		*infoptr;	/* pointer to returned data */
X{
X	GR_WINDOW	*wp;		/* window structure */
X	GR_EVENT_CLIENT	*evp;		/* event-client structure */
X
X	curfunc = "GrGetWindowInfo";	/* temporary */
X
X	/*
X	 * Find the window manually so that an error is not generated.
X	 */
X	for (wp = listwp; wp && (wp->id != wid); wp = wp->next)
X		continue;
X
X	if (wp == NULL) {
X		infoptr->wid = 0;
X		return;
X	}
X
X	infoptr->wid = wid;
X	infoptr->parent = wp->parent->id;
X	infoptr->child = wp->children->id;
X	infoptr->sibling = wp->siblings->id;
X	infoptr->mapped = wp->mapped;
X	infoptr->unmapcount = wp->unmapcount;
X	infoptr->inputonly = !wp->output;
X	infoptr->x = wp->x;
X	infoptr->y = wp->y;
X	infoptr->width = wp->width;
X	infoptr->height = wp->height;
X	infoptr->bordersize = wp->bordersize;
X	infoptr->bordercolor = wp->bordercolor;
X	infoptr->background = wp->background;
X	infoptr->eventmask = 0;
X
X	for (evp = wp->eventclients; evp; evp = evp->next) {
X		if (evp->client == curclient)
X			infoptr->eventmask = evp->eventmask;
X	}
X}
X
X
X/*
X * Destroy an existing window and all of its children.
X */
Xvoid
XGsDestroyWindow(wid)
X	GR_WINDOW_ID	wid;		/* window to destroy */
X{
X	GR_WINDOW	*wp;		/* window structure */
X
X	curfunc = "GrDestroyWindow";	/* temporary */
X
X	wp = GsFindWindow(wid);
X	if (wp)
X		GsWpDestroyWindow(wp);
X}
X
X
X/*
X * Raise a window to the highest level among its siblings.
X */
Xvoid
XGsRaiseWindow(wid)
X	GR_WINDOW_ID	wid;		/* window to be raised */
X{
X	GR_WINDOW	*wp;		/* window structure */
X	GR_WINDOW	*prevwp;	/* previous window pointer */
X	GR_BOOL		overlap;	/* TRUE if there was overlap */
X
X	curfunc = "GrRaiseWindow";	/* temporary */
X
X	wp = GsFindWindow(wid);
X	if ((wp == NULL) || (wp == rootwp))
X		return;
X
X	/*
X	 * If this is already the highest window then we are done.
X	 */
X	prevwp = wp->parent->children;
X	if (prevwp == wp)
X		return;
X
X	/*
X	 * Find the sibling just before this window so we can unlink it.
X	 * Also, determine if any sibling ahead of us overlaps the window.
X	 * Remember that for exposure events.
X	 */
X	overlap = GR_FALSE;
X	while (prevwp->siblings != wp) {
X		overlap |= GsCheckOverlap(prevwp, wp);
X		prevwp = prevwp->siblings;
X	}
X	overlap |= GsCheckOverlap(prevwp, wp);
X
X	/*
X	 * Now unlink the window and relink it in at the front of the
X	 * sibling chain.
X	 */
X	prevwp->siblings = wp->siblings;
X	wp->siblings = wp->parent->children;
X	wp->parent->children = wp;
X
X	/*
X	 * Finally redraw the window if necessary.
X	 */
X	if (overlap) {
X		GsDrawBorder(wp);
X		GsExposeArea(wp, wp->x, wp->y, wp->width, wp->height);
X	}
X}
X
X
X/*
X * Lower a window to the lowest level among its siblings.
X */
Xvoid
XGsLowerWindow(wid)
X	GR_WINDOW_ID	wid;		/* window to be lowered */
X{
X	GR_WINDOW	*wp;		/* window structure */
X	GR_WINDOW	*prevwp;	/* previous window pointer */
X	GR_WINDOW	*sibwp;		/* sibling window */
X	GR_WINDOW	*expwp;		/* siblings being exposed */
X
X	curfunc = "GrLowerWindow";	/* temporary */
X
X	wp = GsFindWindow(wid);
X	if ((wp == NULL) || (wp == rootwp) || (wp->siblings == NULL))
X		return;
X
X	/*
X	 * Find the sibling just before this window so we can unlink us.
X	 */
X	prevwp = wp->parent->children;
X	if (prevwp != wp) {
X		while (prevwp->siblings != wp)
X			prevwp = prevwp->siblings;
X	}
X
X	/*
X	 * Remember the first sibling that is after us, so we can
X	 * generate exposure events for the remaining siblings.  Then
X	 * walk down the sibling chain looking for the last sibling.
X	 */
X	expwp = wp->siblings;
X	sibwp = wp;
X	while (sibwp->siblings)
X		sibwp = sibwp->siblings;
X
X	/*
X	 * Now unlink the window and relink it in at the end of the
X	 * sibling chain.
X	 */
X	if (prevwp == wp)
X		wp->parent->children = wp->siblings;
X	else
X		prevwp->siblings = wp->siblings;
X	sibwp->siblings = wp;
X
X	wp->siblings = NULL;
X
X	/*
X	 * Finally redraw the sibling windows which this window covered
X	 * if they overlapped our window.
X	 */
X	while (expwp && (expwp != wp)) {
X		if (GsCheckOverlap(wp, expwp)) {
X			GsExposeArea(expwp, wp->x - wp->bordersize,
X				wp->y - wp->bordersize,
X				wp->width + wp->bordersize * 2,
X				wp->height + wp->bordersize * 2);
X		}
X		expwp = expwp->siblings;
X	}
X}
X
X
X/*
X * Move the window to the specified position relative to its parent.
X */
Xvoid
XGsMoveWindow(wid, x, y)
X	GR_WINDOW_ID	wid;		/* window to be lowered */
X	GR_COORD	x;		/* new relative x position */
X	GR_COORD	y;		/* new relative y position */
X{
X	GR_WINDOW	*wp;		/* window structure */
X
X	curfunc = "GrMoveWindow";	/* temporary */
X
X	wp = GsFindWindow(wid);
X	if (wp == NULL)
X		return;
X	if (wp == rootwp) {
X		GsError(GR_ERROR_ILLEGAL_ON_ROOT_WINDOW, wid);
X		return;
X	}
X
X	x += wp->parent->x;
X	y += wp->parent->y;
X
X	if ((wp->x == x) && (wp->y == y))
X		return;
X
X	if (wp->unmapcount || !wp->output) {
X		wp->x = x;
X		wp->y = y;
X		return;
X	}
X
X	/*
X	 * This should be optimized to not require redrawing of the window
X	 * when possible.
X	 */
X	GsWpUnmapWindow(wp);
X	wp->x = x;
X	wp->y = y;
X	GsWpMapWindow(wp);
X}
X
X
X/*
X * Resize the window to be the specified size.
X */
Xvoid
XGsResizeWindow(wid, width, height)
X	GR_WINDOW_ID	wid;		/* window to be lowered */
X	GR_SIZE		width;		/* new width of window */
X	GR_SIZE		height;		/* new height of window */
X{
X	GR_WINDOW	*wp;		/* window structure */
X
X	curfunc = "GrResizeWindow";	/* temporary */
X
X	wp = GsFindWindow(wid);
X	if (wp == NULL)
X		return;
X	if (wp == rootwp) {
X		GsError(GR_ERROR_ILLEGAL_ON_ROOT_WINDOW, wid);
X		return;
X	}
X	if ((width <= 0) || (height <= 0)) {
X		GsError(GR_ERROR_BAD_WINDOW_SIZE, wid);
X		return;
X	}
X
X	if ((wp->width == width) && (wp->height == height))
X		return;
X
X	if (wp->unmapcount || !wp->output) {
X		wp->width = width;
X		wp->height = height;
X		return;
X	}
X
X	/*
X	 * This should be optimized to not require redrawing of the window
X	 * when possible.
X	 */
X	GsWpUnmapWindow(wp);
X	wp->width = width;
X	wp->height = height;
X	GsWpMapWindow(wp);
X}
X
X
X/*
X * Allocate a new GC with default parameters.
X * The GC is owned by the current client.
X */
XGR_GC_ID
XGsNewGC()
X{
X	GR_GC	*gcp;
X
X	curfunc = "GrNewGC";		/* temporary */
X
X	/*
X	 * Increment this before checking for errors since the client
X	 * always increments his.
X	 */
X	curclient->allocid++;
X
X	gcp = (GR_GC *) malloc(sizeof(GR_GC));
X	if (gcp == NULL) {
X		GsError(GR_ERROR_MALLOC_FAILED, 0);
X		return 0;
X	}
X
X	gcp->id = curclient->allocid;
X	gcp->mode = GR_MODE_SET;
X	gcp->font = 0;
X	gcp->foreground = sinfo.white;
X	gcp->background = sinfo.black;
X	gcp->usebackground = GR_TRUE;
X	gcp->changed = GR_TRUE;
X	gcp->next = listgcp;
X
X	listgcp = gcp;
X
X	return gcp->id;
X}
X
X
X/*
X * Destroy an existing graphics context.
X */
Xvoid
XGsDestroyGC(gc)
X	GR_GC_ID	gc;		/* graphics context to destroy */
X{
X	GR_GC		*gcp;		/* graphics context */
X	GR_GC		*prevgcp;	/* previous graphics context */
X
X	curfunc = "GrDestroyGC";	/* temporary */
X
X	gcp = GsFindGC(gc);
X	if (gcp == NULL)
X		return;
X
X	if (gc == cachegcid) {
X		cachegcid = 0;
X		cachegcp = NULL;
X	}
X
X	if (listgcp == gcp) {
X		listgcp = gcp->next;
X		free(gcp);
X		return;
X	}
X
X	prevgcp = listgcp;
X	while (prevgcp->next != gcp)
X		prevgcp = prevgcp->next;
X
X	prevgcp->next = gcp->next;
X	free(gcp);
X}
X
X
X/*
X * Allocate a new GC which is a copy of another one.
X * The GC is owned by the current client.
X */
XGR_GC_ID
XGsCopyGC(gc)
X	GR_GC_ID	gc;		/* GC to be copied */
X{
X	GR_GC		*oldgcp;	/* old graphics context */
X	GR_GC		*gcp;		/* new graphics context */
X
X	curfunc = "GrCopyGC";		/* temporary */
X
X	/*
X	 * Increment this before checking for errors since the client
X	 * always increments his.
X	 */
X	curclient->allocid++;
X
X	oldgcp = GsFindGC(gc);
X	if (oldgcp == NULL)
X		return 0;
X
X	gcp = (GR_GC *) malloc(sizeof(GR_GC));
X	if (gcp == NULL) {
X		GsError(GR_ERROR_MALLOC_FAILED, 0);
X		return 0;
X	}
X
X	/*
X	 * Copy all the old gcp values into the new one, except allocate
X	 * a new id for it and link it into the list of GCs.
X	 */
X	*gcp = *oldgcp;
X	gcp->id = curclient->allocid;
X	gcp->changed = GR_TRUE;
X	gcp->next = listgcp;
X	listgcp = gcp;
X
X	return gcp->id;
X}
X
X
X/*
X * Return information about the specified graphics context.
X */
Xvoid
XGsGetGCInfo(gcid, gcip)
X	GR_GC_ID	gcid;		/* graphics context */
X	GR_GC_INFO	*gcip;		/* address of graphics context info */
X{
X	GR_GC		*gcp;
X
X	/*
X	 * Find the GC manually so that an error is not generated.
X	 */
X	for (gcp = listgcp; gcp && (gcp->id != gcid); gcp = gcp->next)
X		continue;
X
X	if (gcp == NULL) {
X		gcip->gcid = 0;
X		return;
X	}
X
X	gcip->gcid = gcid;
X	gcip->mode = gcp->mode;
X	gcip->font = gcp->font;
X	gcip->foreground = gcp->foreground;
X	gcip->background = gcp->background;
X	gcip->usebackground = gcp->usebackground;
X}
X
X
X/*
X * Return useful information about the specified font.
X */
Xvoid
XGsGetFontInfo(font, fip)
X	GR_FONT		font;		/* font number */
X	GR_FONT_INFO	*fip;		/* address of font info */
X{
X	/*
X	 * See if the font is built-in or not.  Someday for non-builtin
X	 * fonts, we can return something for them.
X	 */
X	if (font >= sinfo.fonts) {
X		fip->font = 0;
X		return;
X	}
X	GdGetFontInfo(font, fip);
X}
X
X
X/*
X * Select events for a window for this client.
X * The events are a bitmask for the events desired.
X */
Xvoid
XGsSelectEvents(wid, eventmask)
X	GR_WINDOW_ID	wid;		/* window id */
X	GR_EVENT_MASK	eventmask;	/* mask of events wanted */
X{
X	GR_WINDOW	*wp;		/* window structure */
X	GR_EVENT_CLIENT	*evp;		/* event-client structure */
X
X	curfunc = "GrSelectEvents";	/* temporary */
X
X	wp = GsFindWindow(wid);
X	if (wp == NULL)
X		return;
X
X	/*
X	 * See if this client is already in the event client list.
X	 * If so, then just replace the events he is selecting for.
X	 */
X	for (evp = wp->eventclients; evp; evp = evp->next) {
X		if (evp->client == curclient) {
X			evp->eventmask = eventmask;
X			return;
X		}
X	}
X
X	/*
X	 * A new client for this window, so allocate a new event client
X	 * structure and insert it into the front of the list in the window.
X	 */
X	evp = (GR_EVENT_CLIENT *) malloc(sizeof(GR_EVENT_CLIENT));
X	if (evp == NULL) {
X		GsError(GR_ERROR_MALLOC_FAILED, wid);
X		return;
X	}
X
X	evp->client = curclient;
X	evp->eventmask = eventmask;
X	evp->next = wp->eventclients;
X	wp->eventclients = evp;
X}
X
X
X/*
X * Allocate a new window which is a child of the specified window.
X * The window inherits the cursor of the parent window.
X * The window is owned by the current client.
X */
XGR_WINDOW_ID
XGsNewWindow(parent, x, y, width, height, bordersize, background, bordercolor)
X	GR_WINDOW_ID	parent;		/* parent id */
X	GR_COORD	x;		/* x position relative to parent */
X	GR_COORD	y;		/* y position relative to parent */
X	GR_SIZE		width;		/* width */
X	GR_SIZE		height;		/* height */
X	GR_SIZE		bordersize;	/* size of border */
X	GR_COLOR	background;	/* background color */
X	GR_COLOR	bordercolor;	/* border color */
X{
X	GR_WINDOW	*pwp;		/* parent window */
X	GR_WINDOW	*wp;		/* new window */
X
X	curfunc = "GrNewWindow";	/* temporary */
X
X	/*
X	 * Increment this before checking for errors since the client
X	 * always increments his.
X	 */
X	curclient->allocid++;
X
X	if ((width <= 0) || (height <= 0) || (bordersize < 0)) {
X		GsError(GR_ERROR_BAD_WINDOW_SIZE, 0);
X		return 0;
X	}
X
X	pwp = GsFindWindow(parent);
X	if (pwp == NULL)
X		return 0;
X
X	if (!pwp->output) {
X		GsError(GR_ERROR_INPUT_ONLY_WINDOW, pwp->id);
X		return 0;
X	}
X
X	wp = (GR_WINDOW *) malloc(sizeof(GR_WINDOW));
X	if (wp == NULL) {
X		GsError(GR_ERROR_MALLOC_FAILED, 0);
X		return 0;
X	}
X
X	wp->id = curclient->allocid;
X	wp->parent = pwp;
X	wp->children = NULL;
X	wp->siblings = pwp->children;
X	wp->next = listwp;
X	wp->x = pwp->x + x;
X	wp->y = pwp->y + y;
X	wp->width = width;
X	wp->height = height;
X	wp->bordersize = bordersize;
X	wp->background = background;
X	wp->bordercolor = bordercolor;
X	wp->nopropmask = 0;
X	wp->eventclients = NULL;
X	wp->cursor = pwp->cursor;
X	wp->mapped = GR_FALSE;
X	wp->unmapcount = pwp->unmapcount + 1;
X	wp->output = GR_TRUE;
X
X	wp->cursor->usecount++;
X	pwp->children = wp;
X	listwp = wp;
X
X	return wp->id;
X}
X
X
X/*
X * Allocate a new input-only window which is a child of the specified window.
X * Such a window is invisible, cannot be drawn into, and is only used to
X * return events.  The window inherits the cursor of the parent window.
X * The window is owned by the current client.
X */
XGR_WINDOW_ID
XGsNewInputWindow(parent, x, y, width, height)
X	GR_WINDOW_ID	parent;		/* parent id */
X	GR_COORD	x;		/* x position relative to parent */
X	GR_COORD	y;		/* y position relative to parent */
X	GR_SIZE		width;		/* width */
X	GR_SIZE		height;		/* height */
X{
X	GR_WINDOW	*pwp;		/* parent window */
X	GR_WINDOW	*wp;		/* new window */
X
X	curfunc = "GrNewInputWindow";	/* temporary */
X
X	/*
X	 * Increment this before checking for errors since the client
X	 * always increments his.
X	 */
X	curclient->allocid++;
X
X	if ((width <= 0) || (height <= 0)) {
X		GsError(GR_ERROR_BAD_WINDOW_SIZE, 0);
X		return 0;
X	}
X
X	pwp = GsFindWindow(parent);
X	if (pwp == NULL)
X		return 0;
X
X	wp = (GR_WINDOW *) malloc(sizeof(GR_WINDOW));
X	if (wp == NULL) {
X		GsError(GR_ERROR_MALLOC_FAILED, 0);
X		return 0;
X	}
X
X	wp->id = curclient->allocid;
X	wp->parent = pwp;
X	wp->children = NULL;
X	wp->siblings = pwp->children;
X	wp->next = listwp;
X	wp->x = pwp->x + x;
X	wp->y = pwp->y + y;
X	wp->width = width;
X	wp->height = height;
X	wp->bordersize = 0;
X	wp->background = sinfo.black;
X	wp->bordercolor = sinfo.black;
X	wp->nopropmask = 0;
X	wp->eventclients = NULL;
X	wp->cursor = pwp->cursor;
X	wp->mapped = GR_FALSE;
X	wp->unmapcount = pwp->unmapcount + 1;
X	wp->output = GR_FALSE;
X
X	wp->cursor->usecount++;
X	pwp->children = wp;
X	listwp = wp;
X
X	return wp->id;
X}
X
X
X/*
X * Map the window to make it (and possibly its children) visible on the screen.
X */
Xvoid
XGsMapWindow(wid)
X	GR_WINDOW_ID	wid;		/* window to be mapped */
X{
X	GR_WINDOW	*wp;		/* window structure */
X
X	curfunc = "GrMapWindow";	/* temporary */
X
X	wp = GsFindWindow(wid);
X	if ((wp == NULL) || wp->mapped)
X		return;
X
X	wp->mapped = GR_TRUE;
X
X	GsWpMapWindow(wp);
X}
X
X
X/*
X * Unmap the window to make it and its children invisible on the screen.
X */
Xvoid
XGsUnmapWindow(wid)
X	GR_WINDOW_ID	wid;		/* window to be unmapped */
X{
X	GR_WINDOW	*wp;		/* window structure */
X
X	curfunc = "GrUnmapWindow";	/* temporary */
X
X	wp = GsFindWindow(wid);
X	if ((wp == NULL) || !wp->mapped)
X		return;
X
X	GsWpUnmapWindow(wp);
X
X	wp->mapped = GR_FALSE;
X}
X
X
X/*
X * Clear the specified window.
X * This sets the window to its background color.
X * If the exposeflag is nonzero, then this also creates an exposure
X * event for the window.
X */
Xvoid
XGsClearWindow(wid, exposeflag)
X	GR_WINDOW_ID	wid;		/* window id */
X	GR_BOOL		exposeflag;	/* nonzero to cause an exposure */
X{
X	GR_WINDOW		*wp;	/* window structure */
X
X	curfunc = "GrClearWindow";	/* temporary */
X
X	wp = GsPrepareWindow(wid);
X	if (wp)
X		GsWpClearWindow(wp, 0, 0, wp->width, wp->height, exposeflag);
X}
X
X
X/*
X * Set the focus to a particular window.
X * This makes keyboard events only visible to that window or children of it,
X * depending on the pointer location.
X */
Xvoid
XGsSetFocus(wid)
X	GR_WINDOW_ID	wid;		/* window id */
X{
X	GR_WINDOW	*wp;		/* window structure */
X
X	curfunc = "GrSetFocus";		/* temporary */
X
X	wp = GsFindWindow(wid);
X	if (wp == NULL)
X		return;
X
X	if (wp->unmapcount) {
X		GsError(GR_ERROR_UNMAPPED_FOCUS_WINDOW, wid);
X		return;
X	}
X
X	focusfixed = (wp != rootwp);
X	GsWpSetFocus(wp);
X}
X
X
X/*
X * Set the border of a window to the specified color.
X */
Xvoid
XGsSetBorderColor(wid, color)
X	GR_WINDOW_ID	wid;		/* window id */
X	GR_COLOR	color;		/* color for border */
X{
X	GR_WINDOW	*wp;		/* window structure */
X
X	curfunc = "GrSetBorderColor";	/* temporary */
X
X	wp = GsFindWindow(wid);
X	if ((wp == NULL) || (wp->bordercolor == color) ||
X		(wp->bordersize == 0))
X			return;
X
X	wp->bordercolor = color;
X	if (wp->unmapcount == 0)
X		GsDrawBorder(wp);
X}
X
X
X/*
X * Specify a cursor for a window.
X * This cursor will only be used within that window, and by default
X * for its new children.  If the cursor is currently within this
X * window, it will be changed to the new one immediately.
X */
Xvoid
XGsSetCursor(wid, width, height, hotx, hoty, foreground, background,
X	fgbitmap, bgbitmap)
X
X	GR_WINDOW_ID	wid;		/* window id to set cursor for */
X	GR_SIZE		width;		/* width of cursor */
X	GR_SIZE		height;		/* height of cursor */
X	GR_COORD	hotx;		/* relative x position of hot spot */
X	GR_COORD	hoty;		/* relative y position of hot spot */
X	GR_COLOR	foreground;	/* foreground color of cursor */
X	GR_COLOR	background;	/* background color of cursor */
X	GR_BITMAP	*fgbitmap;	/* foreground bitmap */
X	GR_BITMAP	*bgbitmap;	/* background bitmap */
X{
X	GR_WINDOW	*wp;		/* window structure */
X	GR_CURSOR	*cp;		/* cursor structure */
X	int		bytes;		/* number of bytes of bitmap */
X
X	curfunc = "GrSetCursor";	/* temporary */
X
X	wp = GsFindWindow(wid);
X	if (wp == NULL)
X		return;
X
X	/*
X	 * Make sure the size of the bitmap is reasonable.
X	 */
X	if ((width <= 0) || (width > GR_MAX_CURSOR_SIZE) ||
X		(height <= 0) || (height > GR_MAX_CURSOR_SIZE))
X	{
X		GsError(GR_ERROR_BAD_CURSOR_SIZE, 0);
X		return;
X	}
X	bytes = GR_BITMAP_SIZE(width, height) * sizeof(GR_BITMAP);
X
X	/*
X	 * See if the window is using a shared cursor definition.
X	 * If so, then allocate a new private one, otherwise reuse it.
X	 */
X	cp = wp->cursor;
X	if (cp->usecount-- > 1) {
X		cp = (GR_CURSOR *) malloc(sizeof(GR_CURSOR));
X		if (cp == NULL) {
X			GsError(GR_ERROR_MALLOC_FAILED, 0);
X			return;
X		}
X	}
X
X	cp->usecount = 1;
X	cp->width = width;
X	cp->height = height;
X	cp->hotx = hotx;
X	cp->hoty = hoty;
X	cp->foreground = foreground;
X	cp->background = background;
X	memcpy((char *) cp->fgbitmap, (char *) fgbitmap, bytes);
X	memcpy((char *) cp->bgbitmap, (char *) bgbitmap, bytes);
X	wp->cursor = cp;
X
X	/*
X	 * If this was the current cursor, then draw the new one.
X	 */
X	if (cp == curcursor) {
X		GdSetCursor(cp->width, cp->height, cp->foreground,
X			cp->background, cp->fgbitmap, cp->bgbitmap);
X		GdMoveCursor(cursorx - cp->hotx, cursory - cp->hoty);
X	}
X}
X
X
X/*
X * Move the cursor to the specified absolute screen coordinates.
X * The coordinates are that of the defined hot spot of the cursor.
X * The cursor's appearance is changed to that defined for the window
X * in which the cursor is moved to.  In addition, mouse enter, mouse
X * exit, focus in, and focus out events are generated if necessary.
X */
Xvoid
XGsMoveCursor(x, y)
X	GR_COORD	x;		/* new x position of cursor */
X	GR_COORD	y;		/* new y position of cursor */
X{
X	curfunc = "GrMoveCursor";	/* temporary */
X
X	/*
X	 * Move the cursor only if necessary, offsetting it to
X	 * place the hot spot at the specified coordinates.
X	 */
X	if ((x != cursorx) || (y != cursory)) {
X		GdMoveCursor(x - curcursor->hotx, y - curcursor->hoty);
X		cursorx = x;
X		cursory = y;
X	}
X
X	/*
X	 * Now check to see which window the mouse is in, whether or
X	 * not the cursor shape should be changed, and whether or not
X	 * the input focus window should be changed.
X	 */
X	GsCheckMouseWindow();
X	GsCheckFocusWindow();
X	GsCheckCursor();
X}
X
X
X/*
X * Set the foreground color in a graphics context.
X */
Xvoid
XGsSetGCForeground(gc, foreground)
X	GR_GC_ID	gc;		/* graphics context id */
X	GR_COLOR	foreground;	/* foreground color */
X{
X	GR_GC		*gcp;		/* graphics context */
X
X	curfunc = "GrSetGCForeground";	/* temporary */
X
X	gcp = GsFindGC(gc);
X	if ((gcp == NULL) || (gcp->foreground == foreground))
X		return;
X	gcp->foreground = foreground;
X	gcp->changed = GR_TRUE;
X}
X
X
X/*
X * Set the background color in a graphics context.
X */
Xvoid
XGsSetGCBackground(gc, background)
X	GR_GC_ID	gc;		/* graphics context id */
X	GR_COLOR	background;	/* background color */
X{
X	GR_GC		*gcp;		/* graphics context */
X
X	curfunc = "GrSetGCBackground";	/* temporary */
X
X	gcp = GsFindGC(gc);
X	if ((gcp == NULL) || (gcp->background == background))
X		return;
X	gcp->background = background;
X	gcp->changed = GR_TRUE;
X}
X
X
X/*
X * Set whether or not the background color is drawn in bitmaps and text.
X */
Xvoid
XGsSetGCUseBackground(gc, flag)
X	GR_GC_ID	gc;		/* graphics context id */
X	GR_BOOL		flag;		/* TRUE if background is drawn */
X{
X	GR_GC		*gcp;		/* graphics context */
X
X	curfunc = "GrSetGCUseBackground";	/* temporary */
X
X	flag = (flag != 0);
X	gcp = GsFindGC(gc);
X	if ((gcp == NULL) || (gcp->usebackground == flag))
X		return;
X	gcp->usebackground = flag;
X	gcp->changed = GR_TRUE;
X}
X
X
X/*
X * Set the drawing mode in a graphics context.
X */
Xvoid
XGsSetGCMode(gc, mode)
X	GR_GC_ID	gc;		/* graphics context id */
X	GR_MODE		mode;		/* drawing mode */
X{
X	GR_GC		*gcp;		/* graphics context */
X
X	curfunc = "GrSetGCMode";	/* temporary */
X
X	gcp = GsFindGC(gc);
X	if ((gcp == NULL) || (gcp->mode == mode))
X		return;
X	if (mode > GR_MAX_MODE) {
X		GsError(GR_ERROR_BAD_DRAWING_MODE, gc);
X		return;
X	}
X	gcp->mode = mode;
X	gcp->changed = GR_TRUE;
X}
X
X
X/*
X * Set the text font in a graphics context.
X */
Xvoid
XGsSetGCFont(gc, font)
X	GR_GC_ID	gc;		/* graphics context id */
X	GR_FONT		font;		/* text font */
X{
X	GR_GC		*gcp;		/* graphics context */
X
X	curfunc = "GrSetGCFont";	/* temporary */
X
X	gcp = GsFindGC(gc);
X	if ((gcp == NULL) || (gcp->font == font))
X		return;
X	gcp->font = font;
X	gcp->changed = GR_TRUE;
X}
X
X
X/*
X * Draw a line in the specified drawable using the specified graphics context.
X */
Xvoid
XGsLine(id, gc, x1, y1, x2, y2)
X	GR_DRAW_ID	id;
X	GR_GC_ID	gc;
X	GR_COORD	x1;
X	GR_COORD	y1;
X	GR_COORD	x2;
X	GR_COORD	y2;
X{
X	GR_WINDOW	*wp;
X	GR_PIXMAP	*pmp;
X
X	curfunc = "GrLine";		/* temporary */
X
X	switch (GsPrepareDrawing(id, gc, &wp, &pmp)) {
X		case GR_DRAW_TYPE_WINDOW:
X			GdLine(wp->x + x1, wp->y + y1, wp->x + x2, wp->y + y2);
X			break;
X	}
X}
X
X
X/*
X * Draw the boundary of a rectangle in the specified drawable using the
X * specified graphics context.
X */
Xvoid
XGsRect(id, gc, x, y, width, height)
X	GR_DRAW_ID	id;
X	GR_GC_ID	gc;
X	GR_COORD	x;
X	GR_COORD	y;
X	GR_SIZE		width;
X	GR_SIZE		height;
X{
X	GR_WINDOW	*wp;
X	GR_PIXMAP	*pmp;
X
X	curfunc = "GrRect";		/* temporary */
X
X	switch (GsPrepareDrawing(id, gc, &wp, &pmp)) {
X		case GR_DRAW_TYPE_WINDOW:
X			GdRect(wp->x + x, wp->y + y, width, height);
X			break;
X	}
X}
X
X
X/*
X * Fill a rectangle in the specified drawable using the specified
X * graphics context.
X */
Xvoid
XGsFillRect(id, gc, x, y, width, height)
X	GR_DRAW_ID	id;
X	GR_GC_ID	gc;
X	GR_COORD	x;
X	GR_COORD	y;
X	GR_SIZE		width;
X	GR_SIZE		height;
X{
X	GR_WINDOW	*wp;
X	GR_PIXMAP	*pmp;
X
X	curfunc = "GrFillRect";		/* temporary */
X
X	switch (GsPrepareDrawing(id, gc, &wp, &pmp)) {
X		case GR_DRAW_TYPE_WINDOW:
X			GdFillRect(wp->x + x, wp->y + y, width, height);
X			break;
X	}
X}
X
X
X/*
X * Draw the boundary of an ellipse in the specified drawable with
X * the specified graphics context.
X */
Xvoid
XGsEllipse(id, gc, x, y, rx, ry)
X	GR_DRAW_ID	id;
X	GR_GC_ID	gc;
X	GR_COORD	x;
X	GR_COORD	y;
X	GR_SIZE		rx;
X	GR_SIZE		ry;
X{
X	GR_WINDOW	*wp;
X	GR_PIXMAP	*pmp;
X
X	curfunc = "GrEllipse";		/* temporary */
X
X	switch (GsPrepareDrawing(id, gc, &wp, &pmp)) {
X		case GR_DRAW_TYPE_WINDOW:
X			GdEllipse(wp->x + x, wp->y + y, rx, ry);
X			break;
X	}
X}
X
X
X/*
X * Fill an ellipse in the specified drawable using the specified
X * graphics context.
X */
Xvoid
XGsFillEllipse(id, gc, x, y, rx, ry)
X	GR_DRAW_ID	id;
X	GR_GC_ID	gc;
X	GR_COORD	x;
X	GR_COORD	y;
X	GR_SIZE		rx;
X	GR_SIZE		ry;
X{
X	GR_WINDOW	*wp;
X	GR_PIXMAP	*pmp;
X
X	curfunc = "GrFillEllipse";	/* temporary */
X
X	switch (GsPrepareDrawing(id, gc, &wp, &pmp)) {
X		case GR_DRAW_TYPE_WINDOW:
X			GdFillEllipse(wp->x + x, wp->y + y, rx, ry);
X			break;
X	}
X}
X
X
X/*
X * Draw a rectangular area in the specified drawable using the specified
X * graphics, as determined by the specified bit map.  This differs from
X * rectangle drawing in that the rectangle is drawn using the foreground
X * color and possibly the background color as determined by the bit map.
X * Each row of bits is aligned to the next bitmap word boundary (so there
X * is padding at the end of the row).  The background bit values are only
X * written if the usebackground flag is set in the GC.
X */
Xvoid
XGsBitmap(id, gc, x, y, width, height, bitmaptable)
X	GR_DRAW_ID	id;
X	GR_GC_ID	gc;
X	GR_COORD	x;
X	GR_COORD	y;
X	GR_SIZE		width;
X	GR_SIZE		height;
X	GR_BITMAP	*bitmaptable;
X{
X	GR_WINDOW	*wp;
X	GR_PIXMAP	*pmp;
X
X	curfunc = "GrBitmap";		/* temporary */
X
X	switch (GsPrepareDrawing(id, gc, &wp, &pmp)) {
X		case GR_DRAW_TYPE_WINDOW:
X			GdBitmap(wp->x + x, wp->y + y, width, height,
X				bitmaptable);
X			break;
X	}
X}
X
X
X/*
X * Draw a rectangular area in the specified drawable using the specified
X * graphics context.  This differs from rectangle drawing in that the
X * color values for each pixel in the rectangle are specified.  The color
X * values are restricted to 8 bit values.  The color table is indexed
X * row by row.
X */
Xvoid
XGsArea8(id, gc, x, y, width, height, colortable)
X	GR_DRAW_ID	id;
X	GR_GC_ID	gc;
X	GR_COORD	x;
X	GR_COORD	y;
X	GR_SIZE		width;
X	GR_SIZE		height;
X	GR_COLOR8	*colortable;
X{
X	GR_WINDOW	*wp;
X	GR_PIXMAP	*pmp;
X
X	curfunc = "GrArea8";		/* temporary */
X
X	switch (GsPrepareDrawing(id, gc, &wp, &pmp)) {
X		case GR_DRAW_TYPE_WINDOW:
X			GdArea8(wp->x + x, wp->y + y, width, height,
X				colortable);
X			break;
X	}
X}
X
X
X/*
X * Read the color values from the specified rectangular area of the
X * specified drawable into a supplied buffer.  If the drawable is a
X * window which is obscured by other windows, then the returned values
X * will include the values from the covering windows.  Regions outside
X * of the screen boundaries, or unmapped windows will return black.
X */
Xvoid
XGsReadArea8(id, x, y, width, height, colortable)
X	GR_DRAW_ID	id;
X	GR_COORD	x;
X	GR_COORD	y;
X	GR_SIZE		width;
X	GR_SIZE		height;
X	GR_COLOR8	*colortable;
X{
X	GR_WINDOW	*wp;
X	long		count;
X
X	wp = GsFindWindow(id);			/* wrong, should check pixmap */
X	if ((wp == NULL) || wp->unmapcount || (x >= wp->width) ||
X		(y >= wp->height) || (x + width <= 0) || (y + height <= 0))
X	{
X		count = width * height;
X		while (count-- > 0)
X			*colortable++ = sinfo.black;
X		return;
X	}
X	GdReadArea8(wp->x, wp->y, width, height, colortable);
X}
X
X
X/*
X * Draw a point in the specified drawable using the specified
X * graphics context.
X */
Xvoid
XGsPoint(id, gc, x, y)
X	GR_DRAW_ID	id;
X	GR_GC_ID	gc;
X	GR_COORD	x;
X	GR_COORD	y;
X{
X	GR_WINDOW	*wp;
X	GR_PIXMAP	*pmp;
X
X	curfunc = "GrPoint";		/* temporary */
X
X	switch (GsPrepareDrawing(id, gc, &wp, &pmp)) {
X		case GR_DRAW_TYPE_WINDOW:
X			GdPoint(wp->x + x, wp->y + y);
X			break;
X	}
X}
X
X
X/*
X * Draw a polygon in the specified drawable using the specified
X * graphics context.  The polygon is only complete if the first
X * point is repeated at the end.
X */
Xvoid
XGsPoly(id, gc, count, pointtable)
X	GR_DRAW_ID	id;
X	GR_GC_ID	gc;
X	GR_COUNT	count;
X	GR_POINT	*pointtable;
X{
X	GR_WINDOW	*wp;
X	GR_PIXMAP	*pmp;
X	GR_POINT	*pp;
X	GR_COUNT	i;
X
X	curfunc = "GrPoly";		/* temporary */
X
X	switch (GsPrepareDrawing(id, gc, &wp, &pmp)) {
X		case GR_DRAW_TYPE_WINDOW:
X			break;
X		default:
X			return;
X	}
X
X	/*
X	 * Here for drawing to a window.
X	 * Relocate all the points relative to the window.
X	 */
X	pp = pointtable;
X	for (i = count; i-- > 0; pp++) {
X		pp->x += wp->x;
X		pp->y += wp->y;
X	}
X
X	GdPoly(count, pointtable);
X
X	/*
X	 * The following is temporarily necessary until the server
X	 * becomes a separate process.  We don't want to change the
X	 * user's arguments!
X	 */
X	pp = pointtable;
X	for (i = count; i-- > 0; pp++) {
X		pp->x -= wp->x;
X		pp->y -= wp->y;
X	}
X}
X
X
X/*
X * Draw a filled polygon in the specified drawable using the specified
X * graphics context.  The last point may be a duplicate of the first
X * point, but this is not required.
X */
Xvoid
XGsFillPoly(id, gc, count, pointtable)
X	GR_DRAW_ID	id;
X	GR_GC_ID	gc;
X	GR_COUNT	count;
X	GR_POINT	*pointtable;
X{
X	GR_WINDOW	*wp;
X	GR_PIXMAP	*pmp;
X	GR_POINT	*pp;
X	GR_COUNT	i;
X
X	curfunc = "GrFillPoly";		/* temporary */
X
X	switch (GsPrepareDrawing(id, gc, &wp, &pmp)) {
X		case GR_DRAW_TYPE_WINDOW:
X			break;
X		default:
X			return;
X	}
X
X	/*
X	 * Here for drawing to a window.
X	 * Relocate all the points relative to the window.
X	 */
X	pp = pointtable;
X	for (i = count; i-- > 0; pp++) {
X		pp->x += wp->x;
X		pp->y += wp->y;
X	}
X
X	GdFillPoly(count, pointtable);
X
X	/*
X	 * The following is temporarily necessary until the server
X	 * becomes a separate process.  We don't want to change the
X	 * user's arguments!
X	 */
X	pp = pointtable;
X	for (i = count; i-- > 0; pp++) {
X		pp->x -= wp->x;
X		pp->y -= wp->y;
X	}
X}
X
X
X/*
X * Draw a text string in the specified drawable using the
X * specified graphics context.
X */
Xvoid
XGsText(id, gc, x, y, str, count)
X	GR_DRAW_ID	id;
X	GR_GC_ID	gc;
X	GR_COORD	x;
X	GR_COORD	y;
X	GR_CHAR		*str;
X	GR_COUNT	count;
X{
X	GR_WINDOW	*wp;
X	GR_PIXMAP	*pmp;
X
X	curfunc = "GrText";		/* temporary */
X
X	switch (GsPrepareDrawing(id, gc, &wp, &pmp)) {
X		case GR_DRAW_TYPE_WINDOW:
X			GdText(wp->x + x, wp->y + y, str, count);
X			break;
X	}
X}
X
X/* END CODE */
END_OF_FILE
if test 33072 -ne `wc -c <'mini-x/server/serv_func.c'`; then
    echo shar: \"'mini-x/server/serv_func.c'\" unpacked with wrong size!
fi
# end of 'mini-x/server/serv_func.c'
fi
echo shar: End of archive 8 \(of 9\).
cp /dev/null ark8isdone
MISSING=""
for I in 1 2 3 4 5 6 7 8 9 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked all 9 archives.
    rm -f ark[1-9]isdone ark[1-9][0-9]isdone
else
    echo You still need to unpack the following archives:
    echo "        " ${MISSING}
fi
##  End of shell archive.
exit 0

dbell@pdact.pd.necisa.oz.au (David I. Bell) (04/22/91)

#! /bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of archive 9 (of 9)."
# Contents:  mini-x/TUTORIAL
# Wrapped by dbell@elm on Mon Apr 22 11:21:53 1991
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'mini-x/TUTORIAL' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'mini-x/TUTORIAL'\"
else
echo shar: Extracting \"'mini-x/TUTORIAL'\" \(45475 characters\)
sed "s/^X//" >'mini-x/TUTORIAL' <<'END_OF_FILE'
X			MINI-X TUTORIAL
X			David I. Bell
X			22 Apr 91
X
XThis is a simple tutorial on using the mini-X graphics system.  Much of this
Xis a lot easier to understand if you are familiar to X.  I am not going to
Xtry to explain every concept in detail here, nor how to put it all together
Xto make really fancy programs.  Instead, I am only going to tell you just
Xenough to let you make some simple graphics programs which work.  Experience
Xwith simple test programs will enable you to build much fancier graphics
Xprograms much easier than trying to decipher what I could tell you.
X
XI am assuming that you basically know what a screen, pixels, colors,
Xkeyboards, mice, buttons, and windows are.  However, you probably don't
Xknow exactly what the properties of windows in this system are.  Also, you
Xmight not know two other concepts which are important here, which are
Xgraphics contexts and events.  So these things will be explained in this
Xtutorial.
X
X
XWINDOWS
X
XWindows are rectangular areas which can be drawn into.  Windows have a
Xposition, specified by the x and y coordinates of their upper left corners,
Xand also a size, specified by their width and height.  Windows are arranged
Xin a tree structure, with the parent windows controlling the child windows.
XThe top of the tree is known as the root window.  The root window is always
Xpresent, and represents the total screen area.
X
XEach child window is clipped by its parent window.  This means that a window
Xcan be very large, but the only part of the window that can ever be seen is
Xthe part which shows through its parent window.  This applies recursively,
Xso that all of the parents of a window limit its visibility.  The position
Xof a window is specified relative to its parent, and not absolutely.  This
Xmeans that for example, when a window is moved, then all of its children will
Xmove with it.  The position of a window can be negative.
X
XWindows which have the same parent can clip each other.  That is, there is a
Xdefined order among the children of a window as to which is more important.
XIf two sibling windows overlap, then the more important window will be visible
Xin preference to the less important window.  The precedence of visibility
Xof siblings can be dynamically adjusted.  Clipping can also occur on a window
Xby earlier siblings of any of the window's parents.
X
XWindows can be mapped or unmapped.  Unmapped windows are not visible, and
Xcause no events.  They can be thought of as "in storage" or offscreen.
XWhen a window is mapped, then it can become visible on the screen.  Children
Xof an unmapped window are implicitly also unmapped.  So a window is not
Xvisible until it and all of its parents are mapped.  A newly created window
Xstarts off unmapped.
X
XWindows have a background color.  A newly mapped window is filled with its
Xbackground color.  Clearing the window later, or having obscured portions
Xof the window become visible again, will fill the region with the background.
XThe client program can then draw into the window to make it look correct.
X
XWindows may have a border.  A border is a set of rectangles adjacent to the
Xfour sides of the window which is drawn in a specified color, with a
Xspecified width.  This makes pretty lines around the window, for example.
XThe border cannot be drawn in by the program.  Borders are optional, so
Xthat a window with a border width of zero has no border at all.  Borders
Xare "around" the window, so that they do not affect the coordinates of the
Xwindow.  Whether or not a window has borders, its position determines the
Xlocation of the upper left corner which can be drawn into.
X
XWindows can have a cursor associated with them.  The graphics server tracks
Xthe location of the mouse, and maintains the position of a graphics cursor
Xon the screen.  This cursor can automatically change its shape and colors as
Xit moves between different windows.  The use of different cursors for different
Xwindows can be used to provide a powerful clue to the user as to what will
Xhappen if a mouse button is pressed in a window.  Newly created windows
Xinherit the same cursor as their parent.
X
XThere are two types of windows, input-output and input-only windows.
XInput-output windows are normal windows which are visible and can be drawn
Xinto.  Input-only windows are invisible, have no border, and cannot be
Xdrawn into.  Their purpose is to catch events, and to enable the cursor
Xto be changed in different regions of a visible window.  The only children
Xof input-only windows are also input-only windows.
X
XWindows are identified by integers called window ids.  The root window has
Xa constant window id value of GR_ROOT_WINDOW_ID.  The root window does not
Xneed creating, and cannot be unmapped, moved, resized, or destroyed.
XHowever, it can be drawn into and events can be delivered to it.  New windows
Xcan be created from existing windows.  Their window ids are not constants,
Xbut once created the window id remains until the window is destroyed.  Window
Xids are not reused as windows are created and destroyed.
X
X
XGRAPHICS CONTEXTS
X
XWhen drawing objects such as lines, there are many parameters that can be
Xspecified for the function call that affect the operation.  Besides the
Xminimum information needed for the function such as the endpoint coordinates,
Xthere are extra parameters that are less important and less variable.
XExamples of these extra parameters are color, width (thin or thick), style
X(dashed, dotted), and drawing operation (setting, XORing).  Instead of
Xrequiring the specifying of each of these extra parameters for every function
Xcall, graphics contexts are used.  Graphics contexts are just a collection
Xof specific combinations of these extra parameters.  The many possible
Xextra parameters to each function are replaced by just one extra parameter,
Xwhich is the graphics context.
X
XFor example, instead of a function call like:
X	drawline(window, x1, y1, x2, y2, color, width, style, operation);
X
Xyou have instead
X	drawline(window, gc, x1, y1, x2, y2),
X
Xwhere the graphics context contains within itself the parameters color, width,
Xstyle, and operation.
X
XGraphics contexts are stored in the graphics server, and are identified by
Xunique numbers in a way similar to window ids.  Your program must allocate
Xgraphic contexts, which then can be used in drawing functions.  A newly
Xallocated graphics context is supplied with default parameters, such as a
Xforeground color of white, drawing operation of setting, and width of 0.
XYou can modify the parameters associated with the graphics context one by
Xone, by for example, setting the foreground color to black.
X
XA single graphics context could be used for every drawing operation by
Xconstantly setting the parameters associated with it to the values needed
Xfor each drawing call.  But this is inefficient.  The reason that multiple
Xgraphics contexts can be allocated is so that you can minimize the setting of
Xtheir parameters.  By presetting the parameters of several graphics contexts
Xto commonly used values in your program, you can avoid changing them later.
XFor example, you can call one graphics context white_gc, and another graphics
Xcontext black_gc, and then use the correct graphics context in the drawing
Xfunctions to draw in either black or white.
X
XThe parameters contained within a graphics context are currently the
Xfollowing:
X
XDrawing mode.
XSpecifies the operation performed when drawing each pixel.  One of:
X	GR_MODE_SET	draw pixels as given (default)
X	GR_MODE_XOR	draw pixels using XOR
X	GR_MODE_OR	draw pixels using OR
X	GR_MODE_AND	draw pixels using AND
X
XText font.
XA small integer identifying the font for drawing text.  The first few are
Xbuilt-in to the device driver, others must be loaded by the graphics server.
XThe default font is 0.
X
XForeground color.
XThe color that is used to draw almost all objects with, such as lines,
Xpoints, ellipses, text, bitmaps, and filled areas.  Default is white.
X
XBackground color.
XThe color used for some functions in addition to the foreground color.
XFor bitmaps and text, this is the color used for the zero bits.  The
Xdefault background color is black.  The drawing of this color can be
Xdisabled by the next parameter.
X
XUseBackground flag.
XThis is a boolean value which indicates whether or not the background
Xcolor is actually to be drawn for bitmaps, text, and the GrArea8 function.
XThe default is GR_TRUE.
X
X
XEVENTS
X
XEvents are the way in which the graphics system notifies your program
Xof asychronous changes in the state of the screen, mouse, or keyboard.
XWhenever the state changes, your program is notified of this change and
Xcan act on it.  The word "event" is used both for the actual change
Xthat took place, and also for the data that is returned to your program
Xwhich describes the change.
X
XEvents are generated for various different types of changes that may be useful
Xfor your program to know.  Events directly related to the hardware are the
Xkeyboard and mouse events.  Keyboard events are generated for each key which
Xis pressed (and released, if possible).  The event contains the character
Xwhich caused the event.  Mouse events are generated when a button on the
Xmouse is pressed or released, or when the mouse position moves.  The event
Xcontains the buttons which are pressed, and the current position of the mouse.
XOther events are more subtle, and are based on non-physical changes, such
Xas having the mouse move into or out of specific windows.
X
XEvents are generally tied to individual windows.  Your program can enable
Xor disable which kinds of events it wants for each window.  Part of the data
Xassociated with an event is the window associated with the event.  For
Xexample, if a key is pressed on the keyboard, the event for that key will
Xindicate which window that key is for.  You program can then act differently
Xfor different windows.  Events which you have not indicated an interest in
Xare simply discarded.
X
XThe keyboard and mouse events can propagate upwards through the window tree
Xand be delivered to some parent window.  This occurs if the window does
Xnot select for the event, but one of the parent windows does.  Part of the
Xinformation returned about these events is the window that accepted the event,
Xand also the original window which caused the event.  Therefore, your program
Xcan determine which child window an event was for without having to select
Xfor the event for each child.  Events other than keyboard and mouse events
Xnever propagate.
X
XThe window that keyboard events are delivered to depends on the current
Xmouse position or on the "input focus".  The input focus is a way of
Xspecifying that keyboard events are to be delivered to a particular window,
Xno matter where the mouse is currently pointing.  Your program can change
Xthe input focus as desired.  If the input focus is set to the root window,
Xthen the keyboard events will be delivered to the window which contains
Xthe mouse pointer (or one of its parents).
X
XEvents are returned to your program as a structure containing the information
Xabout the event.  This information is the event type, the window id which
Xthe event is associated with, and other event-specific data.  Events are
Xstored in a queue, and are delivered to your program one by one as requested.
XThe order of the events is preserved.  Your program can either simply ask
Xfor the next available event (waiting for one if none are yet available),
Xor it can check to see if an event is available without waiting.  The
Xdelivering of events only occurs when you request an event.  So even though
Xevents themselves are asychronous, the reading of them is synchronous.
XThere are no "interrupts" for events, you must explicitly ask for them.
X
XThe important thing about programming with events is that your program
Xshould be written to run "upside-down".  That is, you do not have a main
Xroutine which checks that the mouse has been moved, or the keyboard has
Xbeen typed on, or which window the mouse is in.  Instead, your main routine
Xjust waits for an event, and then dispatches on its type and which window
Xit is for.  Generally, you must keep some state information to remember
Xwhat is happening in your program.  For example, if the user wants to click
Xthe button in a window to indicate where some text should be inserted, then
Xyour program cannot simply detect the mouse click, and then wait for the
Xtext to be typed.  Instead, when the mouse is clicked, it should just
Xremember the position of the mouse and set a flag to indicate that text
Xtyping is allowed,  When the keyboard event arrives, this saved information
Xthen enables you to draw the text at the correct location.  Your program
Xbasically becomes one large state machine.
X
XOne obscure event is the exposure event.  This is sent to your program when
Xa window requires redrawing.  Due to lack of memory space, the graphics server
Xdoes not attempt to save the data from the parts of windows which are
Xcovered by other windows.  Therefore, when the obscured parts of the window
Xare uncovered, your program must be told to redraw those parts.  The exposure
Xevent contains a rectangular area which requires drawing (which may in fact
Xbe larger than the area which was actually uncovered).  Your program can
Xeither just redraw that area, or if more convenient, redraw the whole window.
XThe area to be redrawn has already been cleared to the window's background
Xcolor.  When a window is mapped, an exposure event is sent for the window.
XTherefore, you should not explicitly draw into a window when it is first
Xcreated and mapped, but should instead just wait for the exposure event, and
Xthen draw it.  In this way, the code to draw the window only resides in one
Xplace in your program, and you prevent redundant drawing of the window.
XIf you are drawing the complete window on all exposure events, then it
Xmight be useful to use GrPeekEvent to examine the next event too.  If it
Xis also an exposure event for the same window, then you can read it by using
XGrGetNextEvent, and thereby prevent redundant redrawing.  Of course, to
Xbe able to redraw the window, you may need to save extra data in order to
Xregenerate the drawing commands.  (Pixmaps are one way of doing this in
Xthe future, but they are not currently implemented.)
X
XThe following is a description of the various types of events which are
Xavailable, and (in parenthesis) the typedef name for the structure that
Xreturns the event.  Each event has a type field, which can be used to
Xdistinguish between the various events.  For details on the other data
Xwithin the structures, refer to graphics.h.  The typedef GR_EVENT is a
Xunion which contains all of the possible event structures.
X
X
XGR_EVENT_TYPE_NONE	(GR_EVENT)
X	This indicates that no event has occurred.
X
XGR_EVENT_TYPE_EXPOSURE	(GR_EVENT_EXPOSURE)
X	This is generated when a window needs redrawing because it is either
X	newly mapped, or has been uncovered by another window.  This returns
X	the window id, and the x, y, width, and height of the area within
X	the window which needs redrawing.
X
XGR_EVENT_TYPE_BUTTON_DOWN	(GR_EVENT_BUTTON)
X	This is generated when a button is pressed down on the mouse.
X	This returns the window id which generated the event, the window id
X	which actually contains the mouse, the current position of the mouse,
X	the buttons which are currently down on the mouse, the buttons
X	which were just pressed down, and the current modifier flags.
X
XGR_EVENT_TYPE_BUTTON_UP		(GR_EVENT_BUTTON)
X	This is generated when a button is released on the mouse.  This
X	returns data similarly to button down.
X
XGR_EVENT_TYPE_MOUSE_ENTER	(GR_EVENT_GENERAL)
X	This is generated when the mouse enters a window.  This returns the
X	window id which generated the event.
X
XGR_EVENT_TYPE_MOUSE_EXIT	(GR_EVENT_GENERAL)
X	This is generated when the mouse leaves a window.  This returns
X	the window id which generated the event.
X
XGR_EVENT_TYPE_MOUSE_MOTION	(GR_EVENT_MOUSE)
X	Mouse motion is generated for every motion of the mouse, and is
X	used to	track the entire history of the mouse.  Mouse motion
X	generates many events and causes lots of overhead.  This returns
X	data similarly to mouse enter.
X
XGR_EVENT_TYPE_MOUSE_POSITION	(GR_EVENT_MOUSE)
X	Mouse position ignores the history of the motion, and only reports the
X	latest position of the mouse by only queuing the latest such event for
X	any single client (good for rubber-banding).  This returns data
X	similarly to mouse enter.
X
XGR_EVENT_TYPE_KEY_DOWN		(GR_EVENT_KEYSTROKE)
X	This indicates that a key has been pressed on the keyboard.
X	This returns the window id which generated the event, the window id
X	which actually contains the pointer (if the pointer is outside of
X	the event window, this will be the event window), the current position
X	of the mouse, the current buttons on the mouse which are down, the
X	current modifier flags, and the character which was typed.
X
XGR_EVENT_TYPE_KEY_UP		(GR_EVENT_KEYSTROKE)
X	This indicates that a key has been released on the keyboard.  This
X	event is not necessarily available, and should not be depended on.
X	This returns data similarly to key down.
X
XGR_EVENT_TYPE_FOCUS_IN		(GR_EVENT_GENERAL)
X	This indicates that the input focus has just changed to this window.
X	This returns the window id which got focus.
X
XGR_EVENT_TYPE_FOCUS_OUT		(GR_EVENT_GENERAL)
X	This indicates that the input focus has just left this window.
X	This returns the window id which lost focus.
X
X
XTo select for events, you use GrSelectEvents, and specify the window which
Xwants to receive the events, and also specify a mask indicating the events
Xyou wish to receive.  The mask is the logical OR of individual bit values
Xrepresenting the event types.  The mask names are the same as the event
Xnames, except that the "_TYPE_" string is replaced by "_MASK_".  For
Xexample, the mask associated with the event GR_EVENT_TYPE_FOCUS_IN is
XGR_EVENT_MASK_FOCUS_IN.
X
XIf you select for both button down and button up events, then the mouse
Xwill be implicitly "grabbed" when any button is pressed down in that window.
XThis means that the mouse position and button down and up events will be
Xdelivered only to that window, and the cursor shape won't change, even if
Xthe mouse leaves that window.  The implicit grabbing ends after the last
Xbutton is released.  While this grabbing occurs, the input focus is also
Xnot changed as the mouse is moved.
X
X
XMODIFIER AND MOUSE BUTTONS
X
XModifiers are the status of special keyboard shift-like keys.  The state
Xof these keys can be read as up or down, and don't generate any characters
Xby themselves.  These keys are for things like SHIFT, CTRL, and ALT.
XThey are returned as bit values OR'd together in various events.  Not all
Xof these modifiers may be implemented.  The GrGetScreenInfo function returns
Xthe modifiers that are implemented.  The following modifiers are defined:
X
X	GR_MODIFIER_SHIFT	shift key is down
X	GR_MODIFIER_CTRL	ctrl key is down
X	GR_MODIFIER_META	meta (or ALT) key is down
X	GR_MODIFIER_ANY		any of the modifiers is down
X
X
XThe mouse button state are returned as bit values OR'd together in various
Xevents.  Not all of these buttons may be implemented.  The GrGetScreenInfo
Xfunction returns the buttons that are implemented.  The following mouse
Xbuttons are defined:
X
X	GR_BUTTON_1		button 1 is down (left)
X	GR_BUTTON_2		button 2 is down (middle)
X	GR_BUTTON_3		button 3 is down (right)
X	GR_BUTTON_ANY		any of the buttons is down
X
X
XBITMAPS
X
XBitmaps are defined as an array of GR_BITMAP values, which are unsigned shorts.
XEach word is 16 bits, which specify foreground and background values, with 1
Xbeing foreground and 0 being background.  Higher order bits in the word
Xrepresent pixels to the left of the lower order bits.  Bitmaps have a width
Xand a height, measured in pixels.  The width does not need to be a multiple
Xof 16.  In this case, remaining bits in the last word of a row are unused,
Xso that each row starts with a new bitmap word.  The GR_BITMAP_SIZE macro can
Xbe used to allocate the proper number of bitmap words for a bitmap, as in:
X
X	GR_BITMAP_SIZE(width, height).
X
XThe symbol GR_MAX_BITMAP_SIZE is the number of bitmap words required for
Xthe maximum sized cursor.
X
X
XERROR CODES
X
XCalls to the graphics libraries may produce errors.  Most errors that
Xoccur are due to specifying a window or graphics context which does not
Xexist, or attempting an operation which is illegal.  Many things are allowed
Xeven if pointless, such as drawing outside of the window boundaries, or
Xwhile a window is not mapped.  The things which return errors are those
Xwhich definitely indicate a program bug, attempts to exceed the system
Xlimits, or a fatal device error.
X
XIn order to be as efficient as possible, error codes are not returned by
Xindividual function calls.  Instead, if a function fails, an error event
Xis generated which will eventually be noticed by the program at a possibly
Xmuch later time.  This allows many drawing requests to be sent at one time
Xwithout having to worry about the status of each one.
X
XError events are detected when the program checks for events, such as
Xby calling GrGetNextEvent.  At this point, if an error had occurred, a
Xspecial error handler routine is called to notice the error.  If the program
Xhad not set up its own error handler, a default one is called which will
Xdisconnect from the server, print out an indication of the error, and exit
Xthe program.
X
XThe following is a list of the possible errors:
X
XGR_ERROR_BAD_WINDOW_ID		the specified window id is unknown
XGR_ERROR_BAD_GC_ID		the specified graphics context id is unknown
XGR_ERROR_BAD_CURSOR_SIZE	the specified cursor is too large
XGR_ERROR_MALLOC_FAILED		no more memory is available in the server
XGR_ERROR_BAD_WINDOW_SIZE	the specified window size is illegal
XGR_ERROR_KEYBOARD_ERROR		an error occurred reading from the keyboard
XGR_ERROR_MOUSE_ERROR		an error occurred reading from the mouse
XGR_ERROR_INPUT_ONLY_WINDOW	drawing was attempted in an input-only window
XGR_ERROR_ILLEGAL_ON_ROOT_WINDOW	an illegal operation was attempted on the root
XGR_ERROR_TOO_MUCH_CLIPPING	complexity of windows exceeded clipping limits
XGR_ERROR_SCREEN_ERROR		an error occurred talking to the screen driver
XGR_ERROR_UNMAPPED_FOCUS_WINDOW	attempted to set focus to an unmapped window
XGR_ERROR_BAD_DRAWING_MODE	illegal drawing mode specified for a GC
X
X
XSCREEN PROPERTIES
X
XYou do not have to hard code the size of the screen or the number of colors
Xavailable in your program.  Instead, you can find this information out
Xdynamically after the connection is made to the graphics server, by using
Xthe GrGetScreenInfo call.  This returns the above information, and in addition
Xreturns the color values for black and white, the aspect ratio of pixels,
Xthe number of built-in fonts available, and the modifiers and buttons which
Xare available.  The aspect ratio is useful for drawing objects which need
Xto be scaled correctly, such as circles.  The aspect ratio is the quotient
Xof xdpcm and ydpcm, which are integer values.
X
X
Xtypedef struct {
X	GR_SIZE		rows;		/* number of rows on screen */
X	GR_SIZE		cols;		/* number of columns on screen */
X	GR_SIZE		xdpcm;		/* dots/centimeter in x direction */
X	GR_SIZE		ydpcm;		/* dots/centimeter in y direction */
X	GR_COLOR	maxcolor;	/* maximum legal color value */
X	GR_COLOR	black;		/* the color black */
X	GR_COLOR	white;		/* the color white */
X	GR_COUNT	fonts;		/* number of built-in fonts */
X	GR_BUTTON	buttons;	/* buttons which are implemented */
X	GR_MODIFIER	modifiers;	/* modifiers which are implemented */
X} GR_SCREEN_INFO;
X
X
XINCLUDE FILE AND GRAPHICS LIBRARY
X
XTo use the graphics server, your program must include "graphics.h".
XThis should be put into /usr/include, so that your program simply has
Xthe following line at the top:
X	#include <graphics.h>
X
XIncluding this file gives you all of the definitions you need to use the
Xgraphics library.  These are the typedefs, function declarations, event
Xstructures, and various constants.
X
XWhen loading your program, you need to load the graphics server into the
Xprogram by using the -lgraph option in the cc command.  For example, if
Xyour program is called myprog, then you could build it using the following:
X	cc -o myprog myprog.c -lgraph
X
X
XTYPEDEFS
X
XThe following is a list of the typedefs in the include file, and a short
Xdescription of their purpose.  Refer to their definitions in graphics.h
Xto find out what their actual C base type is.  Most are shorts, unsigned
Xshorts, or longs.
X
XGR_COORD	coordinate value (x, y locations, signed)
XGR_SIZE		size value (widths, heights, signed)
XGR_COUNT	number of items (signed)
XGR_COLOR	full color value (32 bit value for full generality)
XGR_COLOR8	eight bit color value (8 bit value for efficient storage)
XGR_BITMAP	bitmap unit (single words of 16 bits for bitmaps)
XGR_MODE		drawing mode (setting, xoring, anding, oring)
XGR_CHAR		text character (normal chars)
XGR_ID		resource ids (window, graphics context, pixmap)
XGR_DRAW_ID	drawable id (window, pixmap)
XGR_WINDOW_ID	window id (identifies individual window)
XGR_PIXMAP_ID	pixmap id (identifies individual pixmaps, not yet used)
XGR_GC_ID	graphics context id (identifies indiviual graphics contexts)
XGR_FONT		font number (identifies individual fonts, first few built-in)
XGR_BOOL		boolean value (GR_TRUE or GR_FALSE)
XGR_FUNC		function codes (not for clients to use)
XGR_ERROR	error value (reasons for graphics calls to fail)
XGR_EVENT_TYPE	event types (identifies the type of event)
XGR_BUTTON	button flags (which mouse buttons are depressed)
XGR_MODIFIER	modifier flags (CTRL, SHIFT, etc)
XGR_EVENT_MASK	event masks (mask values corresponding to event types)
XGR_FUNC_NAME	function name (for error reporting)
XGR_ERROR_FUNC	error function (for defining error handlers)
X
X
XThe following typedefs may be useful to your program.  None of the library
Xfunctions (currently) accept any of these structures as arguments, except
Xfor the GrPoly and GrFillPoly routines, which use GR_POINT.
X
X
Xtypedef struct {
X	GR_COORD	x;		/* x coordinate */
X	GR_COORD	y;		/* y coordinate */
X} GR_POINT;
X
Xtypedef struct {
X	GR_COORD	x1;		/* x coordinate of first point */
X	GR_COORD	y1;		/* y coordinate of first point */
X	GR_COORD	x2;		/* x coordinate of second point */
X	GR_COORD	y2;		/* y coordinate of second point */
X} GR_LINE;
X
Xtypedef struct {
X	GR_COORD	x;		/* x coordinate of center */
X	GR_COORD	y;		/* y coordinate of center */
X	GR_SIZE		rx;		/* radius in x direction */
X	GR_SIZE		ry;		/* radius in y direction */
X} GR_ELLIPSE;
X
Xtypedef struct {
X	GR_COORD	x;		/* x coordinate of top left corner */
X	GR_COORD	y;		/* y coordinate of top left corner */
X	GR_SIZE		width;		/* width of rectangle */
X	GR_SIZE		height;		/* height of rectangle */
X} GR_RECT;
X
X
XLIMITS
X
XThe coordinate system is limited to integers in the range GR_COORD_MIN
Xto GR_COORD_MAX.  This is -32768 to 32767, and fits in a short.
X
XThe maximum size of a cursor definition is GR_MAX_CURSOR_SIZE, which is
X16 pixels by 16 pixels.
X
XThe complexity of overlapping windows is limited to GR_MAX_CLIPRECTS regions,
Xwhich is 200.  Each window which overlaps another requires another 1 to 4
Xregions depending on its position and size.
X
X
XGRAPHICS CALLS
X
X
Xint
XGrOpen()
XOpen a connection to the graphics server.  This must be the first graphics
Xfunction used by your program.  Currently, this sets the screen into
Xgraphics mode.  Returns zero if successful, -1 on failure.
X
X
Xvoid
XGrClose()
XClose the connection to the graphics server, first flushing any graphics
Xcalls that have been buffered.  Currently, this sets the screen back into
Xtext mode.  This (currently) should be called before your program exits,
Xotherwise the screen will be left in graphics mode.  If this occurs, you
Xcan run the 'tm' program to reset the terminal to text mode.
X
X
XGR_ERROR_FUNC
XGrSetErrorHandler(func)
X	GR_ERROR_FUNC	func;		/* function to handle errors */
XSet an error handling routine, which will be called on any errors from
Xthe server (when events are asked for by the client).  If zero is given,
Xthen a default routine will be used which will describe the error and exit.
XReturns the previous error handler (0 if none).  When an error occurs,
Xthe error handling function is called with the following parameters:
XGR_ERROR, GR_FUNC_NAME, and GR_ID.  These are the error code, the name
Xof the function which failed, and a resource id (0 if not meaningful).
XThe error routine can return if desired, but without corrective action
Xnew errors will probably occur soon.
X
X
Xvoid
XGrGetScreenInfo(sip)
X	GR_SCREEN_INFO	*sip;		/* location to return info into */
XReturn useful information about the screen.  This information returned
Xhas been documented above.
X
X
Xvoid
XGrGetFontInfo(font, fip)
X	GR_FONT		font;		/* font number */
X	GR_FONT_INFO	*fip;		/* address of font info */
XReturn useful information about the specified font number.  This information
Xis the font number, the height of the font, the maximum width of any
Xcharacter in the font, the height of the baseline, a flag indicating whether
Xor not the font is fixed-width, and a table of the individual widths of each
Xcharacter in the font.  If the font is unknown, the returned font number is
Xset to zero and the remainder of the information is undefined.  Refer to
Xgraphics.h for a definition of the fields of GR_FONT_INFO.
X
X
Xvoid
XGrGetGCInfo(gc, gcip)
X	GR_GC_ID	gc;		/* graphics context */
X	GR_GC_INFO	*gcip;		/* address of graphics context info */
XReturn useful information about the specified graphics context.  This
Xinformation is the graphics context id, the current font, the foreground
Xand background colors, and so on.  If the graphics context is unknown,
Xthe returned id is 0, and the other information is undefined.  Refer to
Xgraphics.h for a definition of the fields of GR_GC_INFO.
X
X
Xvoid
XGrGetGCTextSize(gc, cp, len, retwidth, retheight, retbase)
X	GR_GC_ID	gc;		/* graphics context containing font */
X	GR_CHAR		*cp;		/* address of text string */
X	GR_SIZE		len;		/* length of text string */
X	GR_SIZE		*retwidth;	/* returned width of string */
X	GR_SIZE		*retheight;	/* returned height of string */
X	GR_SIZE		*retbase;	/* returned height of baseline */
XReturn the size of a text string for the font in a graphics context.
XThis is the width of the string, the height of the string, and the height
Xabove the bottom of the font of the baseline for the font.  The returned
Xsizes are in pixels.
X
X
Xvoid
XGrGetNextEvent(ep)
X	GR_EVENT	*ep;		/* address where event is returned */
XReturn the next event from the event queue, waiting for it if necessary.
XIf a graphics error had occurred, the error handler will be called at this
Xpoint.  This routine first flushes any buffered graphics commands.  The
XGR_EVENT is a union of all the possible events.  The type field of the union
Xindicates which of the possible events took place, and then the correct
Xelement of the union can be used to access that particular event type's data.
X
X
Xvoid
XGrCheckNextEvent(ep)
X	GR_EVENT	*ep;		/* address where event is returned */
XReturn the next event from the event queue if one is ready.
XIf one is not ready, then the event type GR_EVENT_TYPE_NONE is returned.
XTherefore, this routine never blocks.  This routine first flushes any
Xbuffered graphics commands.
X
X
Xvoid
XGrPeekEvent(ep)
X	GR_EVENT	*ep;		/* address where event is returned */
XReturn the next event from the event queue if one is ready, without removing
Xit from the queue.  If one is not ready, then the type GR_EVENT_TYPE_NONE
Xis returned.  This routine never blocks.  This routine first flushes any
Xbuffered graphics commands.
X
X
Xvoid
XGrSelectEvents(wid, eventmask)
X	GR_WINDOW_ID	wid;		/* window id */
X	GR_EVENT_MASK	eventmask;	/* mask of events wanted */
XSelect events for a window for this client.  The events are a bitmask
Xspecifying the events desired for this window.  This totally replaces
Xany previously selected event mask for the window.
X
X
XGR_WINDOW_ID
XGrNewWindow(parent, x, y, width, height, bordersize, background, bordercolor)
X	GR_WINDOW_ID	parent;		/* parent id */
X	GR_COORD	x;		/* x position relative to parent */
X	GR_COORD	y;		/* y position relative to parent */
X	GR_SIZE		width;		/* width */
X	GR_SIZE		height;		/* height */
X	GR_SIZE		bordersize;	/* size of border */
X	GR_COLOR	background;	/* background color */
X	GR_COLOR	bordercolor;	/* border color */
XAllocate a new input-output window which is a child of the specified window.
XA new top-level window is made by specifying a parent of GR_ROOT_WINDOW_ID.
XThe x and y position is the upper left corner of the window, relative to
Xthe parent's upper left corner.  These corners are only for the drawable
Xarea of the windows, so that the border does not affect the position.  An
Xinput-output window cannot be made as a child of an input-only window.  The
Xnew window starts off unmapped, and must be mapped before it can be seen.
XThe new window inherits the cursor of the parent window, and initially is
Xset to select no events.  This routine returns the window id of the window
Xwhich can be used in other calls.
X
X
XGR_WINDOW_ID
XGrNewInputWindow(parent, x, y, width, height)
X	GR_WINDOW_ID	parent;		/* parent id */
X	GR_COORD	x;		/* x position relative to parent */
X	GR_COORD	y;		/* y position relative to parent */
X	GR_SIZE		width;		/* width */
X	GR_SIZE		height;		/* height */
XAllocate a new input-only window which is a child of the specified window.
XAn input-only window is invisible, and cannot be drawn into.  It's only
Xpurposes are that it can select events, and can have it's own cursor.  The
Xnew window starts off unmapped, and must be mapped before it is effective.
XThe new window inherits the cursor of the parent window, and initially is
Xset to select no events.  This routine returns the window id of the window
Xwhich can be used in other calls.
X
X
Xvoid
XGrDestroyWindow(wid)
X	GR_WINDOW_ID	wid;		/* window to destroy */
XThis unmaps and then destroys the specified window, and all of its children.
XThe root window cannot be destroyed.  After destroying a window, you must be
Xcareful about handling events which refer to the dead window, but which have
Xnot been read yet.
X
X
Xvoid
XGrGetWindowInfo(wid, wip)
X	GR_WINDOW_ID	wid;		/* window id to find out about */
X	GR_WINDOW_INFO	*wip;		/* location to return info into */
XReturn useful information about the specified window.  Refer to the
Xgraphics.h include file for the definition of GR_WINDOW_INFO to see
Xwhat data is returned.  If the window id is not valid, an error is NOT
Xgenerated.  Instead, the wid value in the returned structure is set to
Xzero, and the other fields are not defined.
X
X
XGR_GC_ID
XGrNewGC()
XAllocate a new graphics context with default parameters.  These defaults are:
Xbackground of black, foreground of white, font as font 0, and drawing mode
Xas setting.  This routine returns the id for the graphics context which can
Xbe used in other calls.
X
X
XGR_GC_ID
XGrCopyGC(gc)
X	GR_GC_ID	gc;		/* graphics context to copy */
XAllocate a new graphics context which is a copy of another one.  The new
Xgraphics context has the same parameter values as the old one, but is then
Xindependent.  This routine returns the id for the graphics context which
Xcan be used in other calls.
X
X
Xvoid
XGrDestroyGC(gc)
X	GR_GC_ID	gc;		/* graphics context to destroy */
XDestroy an existing graphics context.
X
X
Xvoid
XGrMapWindow(wid)
X	GR_WINDOW_ID	wid;		/* window to be mapped */
XMap the window to make it (and possibly its children) visible on the screen.
XThis paints the border and background of the window, and creates an
Xexposure event to tell the client to draw into it.
X
X
Xvoid
XGrUnmapWindow(wid)
X	GR_WINDOW_ID	wid;		/* window to be unmapped */
XUnmap the window to make it and its children invisible on the screen.
X
X
Xvoid
XGrRaiseWindow(wid)
X	GR_WINDOW_ID	wid;		/* window to be raised */
XRaise the window to the highest level among its siblings.  This means that
Xthis window will be visible in preference to those siblings.  Siblings are
Xwindows which have the same parent as this window.
X
X
Xvoid
XGrLowerWindow(wid)
X	GR_WINDOW_ID	wid;		/* window to be lowered */
XLower the window to the lowest level among its siblings.  This means that
Xthis window will be covered by any siblings which overlap it.
X
X
Xvoid
XGrMoveWindow(wid, x, y)
X	GR_WINDOW_ID	wid;		/* window to be lowered */
X	GR_COORD	x;		/* new relative x position */
X	GR_COORD	y;		/* new relative y position */
XMove the window to the specified position relative to its parent.
X
X
Xvoid
XGrResizeWindow(wid, width, height)
X	GR_WINDOW_ID	wid;		/* window to be lowered */
X	GR_SIZE		width;		/* new width of window */
X	GR_SIZE		height;		/* new height of window */
XResize the window to be the specified size.  If the window is grown, then
Xan exposure event will be generated for the new area.  A resize event is
Xalso given.
X
X
Xvoid
XGrClearWindow(wid, exposeflag)
X	GR_WINDOW_ID	wid;		/* window id */
X	GR_BOOL		exposeflag;	/* nonzero to cause an exposure */
XClear the specified window by setting it to its background color.
XIf the exposeflag is nonzero, then this also creates an exposure
Xevent for the window.
X
X
Xvoid
XGrSetFocus(wid)
X	GR_WINDOW_ID	wid;		/* window id */
XSet the focus to a particular window.  This makes keyboard events only
Xvisible to that window or children of it, depending on the pointer location.
XSetting the focus window to the root window makes the input focus track
Xthe pointer (which is the default).
X
X
Xvoid
XGrSetBorderColor(wid, color)
X	GR_WINDOW_ID	wid;		/* window id */
X	GR_COLOR	color;		/* color for border */
XSet the border of a window to the specified color.
X
X
Xvoid
XGrSetCursor(wid, width, height, hotx, hoty, foreground, background,
X	fgbitmap, bgbitmap)
X
X	GR_WINDOW_ID	wid;		/* window id to set cursor for */
X	GR_SIZE		width;		/* width of cursor */
X	GR_SIZE		height;		/* height of cursor */
X	GR_COORD	hotx;		/* relative x position of hot spot */
X	GR_COORD	hoty;		/* relative y position of hot spot */
X	GR_COLOR	foreground;	/* foreground color of cursor */
X	GR_COLOR	background;	/* background color of cursor */
X	GR_BITMAP	*fgbitmap;	/* foreground bitmap */
X	GR_BITMAP	*bgbitmap;	/* background bitmap */
XSpecify a new cursor for a window.  This cursor will only be used within
Xthat window, and by default for its new children.  The cursor is defined
Xby giving its width and height, its foreground and background colors, its
Xforeground and background bitmaps, and its "hot spot" position.  If a pixel
Xis specified for both the foreground and background bitmaps, then the
Xforeground has precedence.  The hot spot is an offset from the upper left
Xcorner of the bitmap, and is the location in the cursor which is important.
X
X
Xvoid
XGrMoveCursor(x, y)
X	GR_COORD	x;		/* new x position of cursor */
X	GR_COORD	y;		/* new y position of cursor */
XMove the cursor to the specified absolute screen coordinates.
XThe coordinates are that of the defined hot spot of the cursor.
XThe cursor's appearance is changed to that defined for the window
Xin which the cursor is moved to.
X
X
Xvoid
XGrFlush()
XFlush the graphics buffer so that all previous requests will be executed.
XThis is only needed if you do not check events quickly and want to see the
Xresults on the screen soon, since checking for events does an automatic flush.
X
X
Xvoid
XGrSetGCForeground(gc, foreground)
X	GR_GC_ID	gc;		/* graphics context id */
X	GR_COLOR	foreground;	/* foreground color */
XSet the foreground color in a graphics context.  The default is white.
X
X
Xvoid
XGrSetGCBackground(gc, background)
X	GR_GC_ID	gc;		/* graphics context id */
X	GR_COLOR	background;	/* background color */
XSet the background color in a graphics context.  The default is black.
X
X
Xvoid
XGrSetGCUseBackground(gc, flag)
X	GR_GC_ID	gc;		/* graphics context id */
X	GR_BOOL		flag;		/* TRUE if background is drawn */
XSet whether or not the background color is drawn in bitmaps and text.
XThis affects GrBitmap, GrArea8, and GrText.  The default is GR_TRUE.
X
X
Xvoid
XGrSetGCMode(gc, mode)
X	GR_GC_ID	gc;		/* graphics context id */
X	GR_MODE		mode;		/* drawing mode */
XSet the drawing mode in a graphics context.  The drawing mode is one of
XGR_MODE_SET, GR_MODE_XOR, GR_MODE_AND, or GR_MODE_OR.  The default is
XGR_MODE_SET.
X
X
Xvoid
XGrSetGCFont(gc, font)
X	GR_GC_ID	gc;		/* graphics context id */
X	GR_FONT		font;		/* text font */
XSet the font used for text drawing in a graphics context.
XThe font is a number identifying one of several fonts.
XFont number 0 is always available, and is the default font.
X
X
Xvoid
XGrLine(id, gc, x1, y1, x2, y2)
X	GR_DRAW_ID	id;
X	GR_GC_ID	gc;
X	GR_COORD	x1;
X	GR_COORD	y1;
X	GR_COORD	x2;
X	GR_COORD	y2;
XDraw a line in the specified drawable using the specified graphics context.
X
X
Xvoid
XGrRect(id, gc, x, y, width, height)
X	GR_DRAW_ID	id;
X	GR_GC_ID	gc;
X	GR_COORD	x;
X	GR_COORD	y;
X	GR_SIZE		width;
X	GR_SIZE		height;
XDraw the boundary of a rectangle in the specified drawable using the
Xspecified graphics context.
X
X
Xvoid
XGrFillRect(id, gc, x, y, width, height)
X	GR_DRAW_ID	id;
X	GR_GC_ID	gc;
X	GR_COORD	x;
X	GR_COORD	y;
X	GR_SIZE		width;
X	GR_SIZE		height;
XFill a rectangle in the specified drawable using the specified
Xgraphics context.
X
X
Xvoid
XGrEllipse(id, gc, x, y, rx, ry)
X	GR_DRAW_ID	id;
X	GR_GC_ID	gc;
X	GR_COORD	x;
X	GR_COORD	y;
X	GR_SIZE		rx;
X	GR_SIZE		ry;
XDraw the boundary of an ellipse in the specified drawable with
Xthe specified graphics context.
X
X
Xvoid
XGrFillEllipse(id, gc, x, y, rx, ry)
X	GR_DRAW_ID	id;
X	GR_GC_ID	gc;
X	GR_COORD	x;
X	GR_COORD	y;
X	GR_SIZE		rx;
X	GR_SIZE		ry;
XFill an ellipse in the specified drawable using the specified
Xgraphics context.
X
X
Xvoid
XGrBitmap(id, gc, x, y, width, height, bitmaptable)
X	GR_DRAW_ID	id;
X	GR_GC_ID	gc;
X	GR_COORD	x;
X	GR_COORD	y;
X	GR_SIZE		width;
X	GR_SIZE		height;
X	GR_BITMAP	*bitmaptable;
XDraw a rectangular area in the specified drawable using the specified
Xgraphics context, as determined by the specified bit map.  This differs
Xfrom rectangle drawing in that the rectangle is drawn using the foreground
Xcolor and possibly the background color as determined by the bit map.
XBits which are 1 are the foreground, and bits which are 0 are the background.
XEach row of bits is aligned to the next bitmap word boundary (so there can
Xbe padding at the end of each row).  The background bit values are only
Xwritten if the usebackground flag is set in the GC.
X
X
Xvoid
XGrArea8(id, gc, x, y, width, height, colortable)
X	GR_DRAW_ID	id;
X	GR_GC_ID	gc;
X	GR_COORD	x;
X	GR_COORD	y;
X	GR_SIZE		width;
X	GR_SIZE		height;
X	GR_COLOR8	*colortable;
XDraw a rectangular area in the specified drawable using the specified
Xgraphics context.  This differs from rectangle drawing in that the
Xcolor values for each pixel in the rectangle are specified.  The color
Xvalues are estricted to 8 bit values.  The color table is indexed row by
Xrow from left to right.  Table values whose color matches the background
Xcolor are only written if the usebackground flag is set in the GC.
X
X
Xvoid
XGrReadArea8(id, x, y, width, height, colortable)
X	GR_DRAW_ID	id;
X	GR_COORD	x;
X	GR_COORD	y;
X	GR_SIZE		width;
X	GR_SIZE		height;
X	GR_COLOR8	*colortable;
XRead the color values from the specified rectangular area of the specified
Xdrawable into a supplied buffer.  If the drawable is a window which is
Xobscured by other windows, then the returned values will include the values
Xfrom the covering windows.  Regions outside of the screen boundaries, or
Xfrom unmapped windows will return black.
X
X
Xvoid
XGrPoint(id, gc, x, y)
X	GR_DRAW_ID	id;
X	GR_GC_ID	gc;
X	GR_COORD	x;
X	GR_COORD	y;
XDraw a point in the specified drawable using the specified graphics context.
X
X
Xvoid
XGrPoly(id, gc, count, pointtable)
X	GR_DRAW_ID	id;
X	GR_GC_ID	gc;
X	GR_COUNT	count;
X	GR_POINT	*pointtable;
XDraw a polygon in the specified drawable using the specified graphics
Xcontext.  The polygon is only complete if the first point is repeated at
Xthe end.  Note: currently if the polygon crosses itself, and the drawing
Xmode is set to XOR, then the individual line segments will affect each
Xother.  The endpoints of the lines are correct, however.
X
X
Xvoid
XGrFillPoly(id, gc, count, pointtable)
X	GR_DRAW_ID	id;
X	GR_GC_ID	gc;
X	GR_COUNT	count;
X	GR_POINT	*pointtable;
XDraw a filled polygon in the specified drawable using the specified
Xgraphics context.  The last point may be a duplicate of the first point,
Xbut this is not required.  Note: currently only convex polygons are
Xfilled properly.
X
X
Xvoid
XGrText(id, gc, x, y, str, count)
X	GR_DRAW_ID	id;
X	GR_GC_ID	gc;
X	GR_COORD	x;
X	GR_COORD	y;
X	GR_CHAR		*str;
X	GR_COUNT	count;
XDraw a text string at the specified location in the specified drawable
Xusing the specified graphics context.  The background of the characters
Xare only drawn if the usebackground flag in the GC is set.
X
X
XEXAMPLE PROGRAM
X
XThe following simple program opens the graphics, creates a window, prints
Xsome text in it, waits for the mouse to be clicked in the window, then exits.
X
X
X#include <stdio.h>
X#include <graphics.h>
X
X#define	MARGIN	50			/* margin around window */
X
X
Xmain()
X{
X	GR_WINDOW_ID	wid;		/* window id */
X	GR_GC_ID	gc;		/* graphics context id */
X	GR_EVENT	event;		/* current event */
X	GR_SCREEN_INFO	si;		/* screen information */
X
X	if (GrOpen() < 0) {
X		fprintf(stderr, "Cannot open graphics\n");
X		exit(1);
X	}
X
X	GrGetScreenInfo(&si);
X
X	wid = GrNewWindow(GR_ROOT_WINDOW_ID, MARGIN, MARGIN,
X		si.cols - MARGIN * 2, si.rows - MARGIN * 2,
X		1, si.black, si.white);
X
X	GrSelectEvents(wid, GR_EVENT_MASK_BUTTON_DOWN | GR_EVENT_MASK_EXPOSURE);
X	GrMapWindow(wid);
X	gc = GrNewGC();
X
X	while (1) {
X		GrGetNextEvent(&event);
X		switch (event.type) {
X			case GR_EVENT_TYPE_BUTTON_DOWN:
X				if (event.button.wid != wid)
X					break;
X				GrClose();
X				exit(0);
X
X			case GR_EVENT_TYPE_EXPOSURE:
X				if (event.exposure.wid == wid)
X					GrText(wid, gc, 50, 50, "EXIT", 4);
X				break;
X		}
X	}
X}
X
X
XFor a more complete demonstration program, see the file "demo.c" in the
X/usr/src/graphics/clients directory.
END_OF_FILE
if test 45475 -ne `wc -c <'mini-x/TUTORIAL'`; then
    echo shar: \"'mini-x/TUTORIAL'\" unpacked with wrong size!
fi
# end of 'mini-x/TUTORIAL'
fi
echo shar: End of archive 9 \(of 9\).
cp /dev/null ark9isdone
MISSING=""
for I in 1 2 3 4 5 6 7 8 9 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked all 9 archives.
    rm -f ark[1-9]isdone ark[1-9][0-9]isdone
else
    echo You still need to unpack the following archives:
    echo "        " ${MISSING}
fi
##  End of shell archive.
exit 0