Path: utzoo!utgpu!news-server.csri.toronto.edu!rpi!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 9/9) Message-ID: <1000@pdact.pd.necisa.oz.au> Date: 22 Apr 91 00:59:43 GMT Organization: NEC Information Systems Australia, Canberra Lines: 1142 #! /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/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 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 X#include 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