Path: utzoo!utgpu!news-server.csri.toronto.edu!rpi!zaphod.mps.ohio-state.edu!uwm.edu!spool.mu.edu!munnari.oz.au!manuel!csis!anucsd!pdact!dbell From: dbell@pdact.pd.necisa.oz.au (David I. Bell) Newsgroups: comp.os.minix Subject: MINI-X graphics package (part 5/9) Message-ID: <996@pdact.pd.necisa.oz.au> Date: 22 Apr 91 00:54:09 GMT Organization: NEC Information Systems Australia, Canberra Lines: 1692 #! /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 '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 X#include X#include 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 X#include 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