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