]> git.karo-electronics.de Git - karo-tx-redboot.git/blob - packages/services/gfx/mw/v2_0/doc/original_mini-x.txt
Initial revision
[karo-tx-redboot.git] / packages / services / gfx / mw / v2_0 / doc / original_mini-x.txt
1                         MINI-X TUTORIAL
2                         David I. Bell
3                         19 May 91
4
5 This is a simple tutorial on using the mini-X graphics system.  Much of this
6 is a lot easier to understand if you are familiar to X.  I am not going to
7 try to explain every concept in detail here, nor how to put it all together
8 to make really fancy programs.  Instead, I am only going to tell you just
9 enough to let you make some simple graphics programs which work.  Experience
10 with simple test programs will enable you to build much fancier graphics
11 programs much easier than trying to decipher what I could tell you.
12
13 I am assuming that you basically know what a screen, pixels, colors,
14 keyboards, mice, buttons, and windows are.  However, you probably don't
15 know exactly what the properties of windows in this system are.  Also, you
16 might not know two other concepts which are important here, which are
17 graphics contexts and events.  So these things will be explained in this
18 tutorial.
19
20
21 WINDOWS
22
23 Windows are rectangular areas which can be drawn into.  Windows have a
24 position, specified by the x and y coordinates of their upper left corners,
25 and also a size, specified by their width and height.  Windows are arranged
26 in a tree structure, with the parent windows controlling the child windows.
27 The top of the tree is known as the root window.  The root window is always
28 present, and represents the total screen area.
29
30 Each child window is clipped by its parent window.  This means that a window
31 can be very large, but the only part of the window that can ever be seen is
32 the part which shows through its parent window.  This applies recursively,
33 so that all of the parents of a window limit its visibility.  The position
34 of a window is specified relative to its parent, and not absolutely.  This
35 means that for example, when a window is moved, then all of its children will
36 move with it.  The position of a window can be negative.
37
38 Windows which have the same parent can clip each other.  That is, there is a
39 defined order among the children of a window as to which is more important.
40 If two sibling windows overlap, then the more important window will be visible
41 in preference to the less important window.  The precedence of visibility
42 of siblings can be dynamically adjusted.  Clipping can also occur on a window
43 by earlier siblings of any of the window's parents.
44
45 Windows can be mapped or unmapped.  Unmapped windows are not visible, and
46 cause no events.  They can be thought of as "in storage" or offscreen.
47 When a window is mapped, then it can become visible on the screen.  Children
48 of an unmapped window are implicitly also unmapped.  So a window is not
49 visible until it and all of its parents are mapped.  A newly created window
50 starts off unmapped.
51
52 Windows have a background color.  A newly mapped window is filled with its
53 background color.  Clearing the window later, or having obscured portions
54 of the window become visible again, will fill the region with the background.
55 The client program can then draw into the window to make it look correct.
56
57 Windows may have a border.  A border is a set of rectangles adjacent to the
58 four sides of the window which is drawn in a specified color, with a
59 specified width.  This makes pretty lines around the window, for example.
60 The border cannot be drawn in by the program.  Borders are optional, so
61 that a window with a border width of zero has no border at all.  Borders
62 are "around" the window, so that they do not affect the coordinates of the
63 window.  Whether or not a window has borders, its position determines the
64 location of the upper left corner which can be drawn into.
65
66 Windows can have a cursor associated with them.  The graphics server tracks
67 the location of the mouse, and maintains the position of a graphics cursor
68 on the screen.  This cursor can automatically change its shape and colors as
69 it moves between different windows.  The use of different cursors for different
70 windows can be used to provide a powerful clue to the user as to what will
71 happen if a mouse button is pressed in a window.  Newly created windows
72 inherit the same cursor as their parent.
73
74 There are two types of windows, input-output and input-only windows.
75 Input-output windows are normal windows which are visible and can be drawn
76 into.  Input-only windows are invisible, have no border, and cannot be
77 drawn into.  Their purpose is to catch events, and to enable the cursor
78 to be changed in different regions of a visible window.  The only children
79 of input-only windows are also input-only windows.
80
81 Windows are identified by integers called window ids.  The root window has
82 a constant window id value of GR_ROOT_WINDOW_ID.  The root window does not
83 need creating, and cannot be unmapped, moved, resized, or destroyed.
84 However, it can be drawn into and events can be delivered to it.  New windows
85 can be created from existing windows.  Their window ids are not constants,
86 but once created the window id remains until the window is destroyed.  Window
87 ids are not reused as windows are created and destroyed.
88
89
90 GRAPHICS CONTEXTS
91
92 When drawing objects such as lines, there are many parameters that can be
93 specified for the function call that affect the operation.  Besides the
94 minimum information needed for the function such as the endpoint coordinates,
95 there are extra parameters that are less important and less variable.
96 Examples of these extra parameters are color, width (thin or thick), style
97 (dashed, dotted), and drawing operation (setting, XORing).  Instead of
98 requiring the specifying of each of these extra parameters for every function
99 call, graphics contexts are used.  Graphics contexts are just a collection
100 of specific combinations of these extra parameters.  The many possible
101 extra parameters to each function are replaced by just one extra parameter,
102 which is the graphics context.
103
104 For example, instead of a function call like:
105         drawline(window, x1, y1, x2, y2, color, width, style, operation);
106
107 you have instead
108         drawline(window, gc, x1, y1, x2, y2),
109
110 where the graphics context contains within itself the parameters color, width,
111 style, and operation.
112
113 Graphics contexts are stored in the graphics server, and are identified by
114 unique numbers in a way similar to window ids.  Your program must allocate
115 graphic contexts, which then can be used in drawing functions.  A newly
116 allocated graphics context is supplied with default parameters, such as a
117 foreground color of white, drawing operation of setting, and width of 0.
118 You can modify the parameters associated with the graphics context one by
119 one, by for example, setting the foreground color to black.
120
121 A single graphics context could be used for every drawing operation by
122 constantly setting the parameters associated with it to the values needed
123 for each drawing call.  But this is inefficient.  The reason that multiple
124 graphics contexts can be allocated is so that you can minimize the setting of
125 their parameters.  By presetting the parameters of several graphics contexts
126 to commonly used values in your program, you can avoid changing them later.
127 For example, you can call one graphics context white_gc, and another graphics
128 context black_gc, and then use the correct graphics context in the drawing
129 functions to draw in either black or white.
130
131 The parameters contained within a graphics context are currently the
132 following:
133
134 Drawing mode.
135 Specifies the operation performed when drawing each pixel.  One of:
136         GR_MODE_SET     draw pixels as given (default)
137         GR_MODE_XOR     draw pixels using XOR
138         GR_MODE_OR      draw pixels using OR
139         GR_MODE_AND     draw pixels using AND
140
141 Text font.
142 A small integer identifying the font for drawing text.  The first few are
143 built-in to the device driver, others must be loaded by the graphics server.
144 The default font is 0.
145
146 Foreground color.
147 The color that is used to draw almost all objects with, such as lines,
148 points, ellipses, text, bitmaps, and filled areas.  Default is white.
149
150 Background color.
151 The color used for some functions in addition to the foreground color.
152 For bitmaps and text, this is the color used for the zero bits.  The
153 default background color is black.  The drawing of this color can be
154 disabled by the next parameter.
155
156 UseBackground flag.
157 This is a boolean value which indicates whether or not the background
158 color is actually to be drawn for bitmaps, text, and the GrArea8 function.
159 The default is GR_TRUE.
160
161
162 EVENTS
163
164 Events are the way in which the graphics system notifies your program
165 of asychronous changes in the state of the screen, mouse, or keyboard.
166 Whenever the state changes, your program is notified of this change and
167 can act on it.  The word "event" is used both for the actual change
168 that took place, and also for the data that is returned to your program
169 which describes the change.
170
171 Events are generated for various different types of changes that may be useful
172 for your program to know.  Events directly related to the hardware are the
173 keyboard and mouse events.  Keyboard events are generated for each key which
174 is pressed (and released, if possible).  The event contains the character
175 which caused the event.  Mouse events are generated when a button on the
176 mouse is pressed or released, or when the mouse position moves.  The event
177 contains the buttons which are pressed, and the current position of the mouse.
178 Other events are more subtle, and are based on non-physical changes, such
179 as having the mouse move into or out of specific windows.
180
181 Events are generally tied to individual windows.  Your program can enable
182 or disable which kinds of events it wants for each window.  Part of the data
183 associated with an event is the window associated with the event.  For
184 example, if a key is pressed on the keyboard, the event for that key will
185 indicate which window that key is for.  You program can then act differently
186 for different windows.  Events which you have not indicated an interest in
187 are simply discarded.
188
189 The keyboard and mouse events can propagate upwards through the window tree
190 and be delivered to some parent window.  This occurs if the window does
191 not select for the event, but one of the parent windows does.  Part of the
192 information returned about these events is the window that accepted the event,
193 and also the original window which caused the event.  Therefore, your program
194 can determine which child window an event was for without having to select
195 for the event for each child.  Events other than keyboard and mouse events
196 never propagate.
197
198 The window that keyboard events are delivered to depends on the current
199 mouse position or on the "input focus".  The input focus is a way of
200 specifying that keyboard events are to be delivered to a particular window,
201 no matter where the mouse is currently pointing.  Your program can change
202 the input focus as desired.  If the input focus is set to the root window,
203 then the keyboard events will be delivered to the window which contains
204 the mouse pointer (or one of its parents).
205
206 Events are returned to your program as a structure containing the information
207 about the event.  This information is the event type, the window id which
208 the event is associated with, and other event-specific data.  Events are
209 stored in a queue, and are delivered to your program one by one as requested.
210 The order of the events is preserved.  Your program can either simply ask
211 for the next available event (waiting for one if none are yet available),
212 or it can check to see if an event is available without waiting.  The
213 delivering of events only occurs when you request an event.  So even though
214 events themselves are asychronous, the reading of them is synchronous.
215 There are no "interrupts" for events, you must explicitly ask for them.
216
217 The important thing about programming with events is that your program
218 should be written to run "upside-down".  That is, you do not have a main
219 routine which checks that the mouse has been moved, or the keyboard has
220 been typed on, or which window the mouse is in.  Instead, your main routine
221 just waits for an event, and then dispatches on its type and which window
222 it is for.  Generally, you must keep some state information to remember
223 what is happening in your program.  For example, if the user wants to click
224 the button in a window to indicate where some text should be inserted, then
225 your program cannot simply detect the mouse click, and then wait for the
226 text to be typed.  Instead, when the mouse is clicked, it should just
227 remember the position of the mouse and set a flag to indicate that text
228 typing is allowed,  When the keyboard event arrives, this saved information
229 then enables you to draw the text at the correct location.  Your program
230 basically becomes one large state machine.
231
232 One obscure event is the exposure event.  This is sent to your program when
233 a window requires redrawing.  Due to lack of memory space, the graphics server
234 does not attempt to save the data from the parts of windows which are
235 covered by other windows.  Therefore, when the obscured parts of the window
236 are uncovered, your program must be told to redraw those parts.  The exposure
237 event contains a rectangular area which requires drawing (which may in fact
238 be larger than the area which was actually uncovered).  Your program can
239 either just redraw that area, or if more convenient, redraw the whole window.
240 The area to be redrawn has already been cleared to the window's background
241 color.  When a window is mapped, an exposure event is sent for the window.
242 Therefore, you should not explicitly draw into a window when it is first
243 created and mapped, but should instead just wait for the exposure event, and
244 then draw it.  In this way, the code to draw the window only resides in one
245 place in your program, and you prevent redundant drawing of the window.
246 If you are drawing the complete window on all exposure events, then it
247 might be useful to use GrPeekEvent to examine the next event too.  If it
248 is also an exposure event for the same window, then you can read it by using
249 GrGetNextEvent, and thereby prevent redundant redrawing.  Of course, to
250 be able to redraw the window, you may need to save extra data in order to
251 regenerate the drawing commands.  (Pixmaps are one way of doing this in
252 the future, but they are not currently implemented.)
253
254 The following is a description of the various types of events which are
255 available, and (in parenthesis) the typedef name for the structure that
256 returns the event.  Each event has a type field, which can be used to
257 distinguish between the various events.  For details on the other data
258 within the structures, refer to graphics.h.  The typedef GR_EVENT is a
259 union which contains all of the possible event structures.
260
261
262 GR_EVENT_TYPE_NONE      (GR_EVENT)
263         This indicates that no event has occurred.
264
265 GR_EVENT_TYPE_EXPOSURE  (GR_EVENT_EXPOSURE)
266         This is generated when a window needs redrawing because it is either
267         newly mapped, or has been uncovered by another window.  This returns
268         the window id, and the x, y, width, and height of the area within
269         the window which needs redrawing.
270
271 GR_EVENT_TYPE_BUTTON_DOWN       (GR_EVENT_BUTTON)
272         This is generated when a button is pressed down on the mouse.
273         This returns the window id which generated the event, the window id
274         which actually contains the mouse, the current position of the mouse,
275         the buttons which are currently down on the mouse, the buttons
276         which were just pressed down, and the current modifier flags.
277
278 GR_EVENT_TYPE_BUTTON_UP         (GR_EVENT_BUTTON)
279         This is generated when a button is released on the mouse.  This
280         returns data similarly to button down.
281
282 GR_EVENT_TYPE_MOUSE_ENTER       (GR_EVENT_GENERAL)
283         This is generated when the mouse enters a window.  This returns the
284         window id which generated the event.
285
286 GR_EVENT_TYPE_MOUSE_EXIT        (GR_EVENT_GENERAL)
287         This is generated when the mouse leaves a window.  This returns
288         the window id which generated the event.
289
290 GR_EVENT_TYPE_MOUSE_MOTION      (GR_EVENT_MOUSE)
291         Mouse motion is generated for every motion of the mouse, and is
292         used to track the entire history of the mouse.  Mouse motion
293         generates many events and causes lots of overhead.  This returns
294         data similarly to mouse enter.
295
296 GR_EVENT_TYPE_MOUSE_POSITION    (GR_EVENT_MOUSE)
297         Mouse position ignores the history of the motion, and only reports the
298         latest position of the mouse by only queuing the latest such event for
299         any single client (good for rubber-banding).  This returns data
300         similarly to mouse enter.
301
302 GR_EVENT_TYPE_KEY_DOWN          (GR_EVENT_KEYSTROKE)
303         This indicates that a key has been pressed on the keyboard.
304         This returns the window id which generated the event, the window id
305         which actually contains the pointer (if the pointer is outside of
306         the event window, this will be the event window), the current position
307         of the mouse, the current buttons on the mouse which are down, the
308         current modifier flags, and the character which was typed.
309
310 GR_EVENT_TYPE_KEY_UP            (GR_EVENT_KEYSTROKE)
311         This indicates that a key has been released on the keyboard.  This
312         event is not necessarily available, and should not be depended on.
313         This returns data similarly to key down.
314
315 GR_EVENT_TYPE_FOCUS_IN          (GR_EVENT_GENERAL)
316         This indicates that the input focus has just changed to this window.
317         This returns the window id which got focus.
318
319 GR_EVENT_TYPE_FOCUS_OUT         (GR_EVENT_GENERAL)
320         This indicates that the input focus has just left this window.
321         This returns the window id which lost focus.
322
323
324 To select for events, you use GrSelectEvents, and specify the window which
325 wants to receive the events, and also specify a mask indicating the events
326 you wish to receive.  The mask is the logical OR of individual bit values
327 representing the event types.  The mask names are the same as the event
328 names, except that the "_TYPE_" string is replaced by "_MASK_".  For
329 example, the mask associated with the event GR_EVENT_TYPE_FOCUS_IN is
330 GR_EVENT_MASK_FOCUS_IN.
331
332 If you select for both button down and button up events, then the mouse
333 will be implicitly "grabbed" when any button is pressed down in that window.
334 This means that the mouse position and button down and up events will be
335 delivered only to that window, and the cursor shape won't change, even if
336 the mouse leaves that window.  The implicit grabbing ends after the last
337 button is released.  While this grabbing occurs, the input focus is also
338 not changed as the mouse is moved.
339
340
341 MODIFIER AND MOUSE BUTTONS
342
343 Modifiers are the status of special keyboard shift-like keys.  The state
344 of these keys can be read as up or down, and don't generate any characters
345 by themselves.  These keys are for things like SHIFT, CTRL, and ALT.
346 They are returned as bit values OR'd together in various events.  Not all
347 of these modifiers may be implemented.  The GrGetScreenInfo function returns
348 the modifiers that are implemented.  The following modifiers are defined:
349
350         GR_MODIFIER_SHIFT       shift key is down
351         GR_MODIFIER_CTRL        ctrl key is down
352         GR_MODIFIER_META        meta (or ALT) key is down
353         GR_MODIFIER_ANY         any of the modifiers is down
354
355
356 The mouse button state are returned as bit values OR'd together in various
357 events.  Not all of these buttons may be implemented.  The GrGetScreenInfo
358 function returns the buttons that are implemented.  The following mouse
359 buttons are defined:
360
361         GR_BUTTON_1             button 1 is down (left)
362         GR_BUTTON_2             button 2 is down (middle)
363         GR_BUTTON_3             button 3 is down (right)
364         GR_BUTTON_ANY           any of the buttons is down
365
366
367 BITMAPS
368
369 Bitmaps are defined as an array of GR_BITMAP values, which are unsigned shorts.
370 Each word is 16 bits, which specify foreground and background values, with 1
371 being foreground and 0 being background.  Higher order bits in the word
372 represent pixels to the left of the lower order bits.  Bitmaps have a width
373 and a height, measured in pixels.  The width does not need to be a multiple
374 of 16.  In this case, remaining bits in the last word of a row are unused,
375 so that each row starts with a new bitmap word.  The GR_BITMAP_SIZE macro can
376 be used to allocate the proper number of bitmap words for a bitmap, as in:
377
378         GR_BITMAP_SIZE(width, height).
379
380 The symbol GR_MAX_BITMAP_SIZE is the number of bitmap words required for
381 the maximum sized cursor.
382
383
384 ERROR CODES
385
386 Calls to the graphics libraries may produce errors.  Most errors that
387 occur are due to specifying a window or graphics context which does not
388 exist, or attempting an operation which is illegal.  Many things are allowed
389 even if pointless, such as drawing outside of the window boundaries, or
390 while a window is not mapped.  The things which return errors are those
391 which definitely indicate a program bug, attempts to exceed the system
392 limits, or a fatal device error.
393
394 In order to be as efficient as possible, error codes are not returned by
395 individual function calls.  Instead, if a function fails, an error event
396 is generated which will eventually be noticed by the program at a possibly
397 much later time.  This allows many drawing requests to be sent at one time
398 without having to worry about the status of each one.
399
400 Error events are detected when the program checks for events, such as
401 by calling GrGetNextEvent.  At this point, if an error had occurred, a
402 special error handler routine is called to notice the error.  If the program
403 had not set up its own error handler, a default one is called which will
404 disconnect from the server, print out an indication of the error, and exit
405 the program.
406
407 The following is a list of the possible errors:
408
409 GR_ERROR_BAD_WINDOW_ID          the specified window id is unknown
410 GR_ERROR_BAD_GC_ID              the specified graphics context id is unknown
411 GR_ERROR_BAD_CURSOR_SIZE        the specified cursor is too large
412 GR_ERROR_MALLOC_FAILED          no more memory is available in the server
413 GR_ERROR_BAD_WINDOW_SIZE        the specified window size is illegal
414 GR_ERROR_KEYBOARD_ERROR         an error occurred reading from the keyboard
415 GR_ERROR_MOUSE_ERROR            an error occurred reading from the mouse
416 GR_ERROR_INPUT_ONLY_WINDOW      drawing was attempted in an input-only window
417 GR_ERROR_ILLEGAL_ON_ROOT_WINDOW an illegal operation was attempted on the root
418 GR_ERROR_TOO_MUCH_CLIPPING      complexity of windows exceeded clipping limits
419 GR_ERROR_SCREEN_ERROR           an error occurred talking to the screen driver
420 GR_ERROR_UNMAPPED_FOCUS_WINDOW  attempted to set focus to an unmapped window
421 GR_ERROR_BAD_DRAWING_MODE       illegal drawing mode specified for a GC
422
423
424 SCREEN PROPERTIES
425
426 You do not have to hard code the size of the screen or the number of colors
427 available in your program.  Instead, you can find this information out
428 dynamically after the connection is made to the graphics server, by using
429 the GrGetScreenInfo call.  This returns the above information, and in addition
430 returns the color values for black and white, the aspect ratio of pixels,
431 the number of built-in fonts available, and the modifiers and buttons which
432 are available.  The aspect ratio is useful for drawing objects which need
433 to be scaled correctly, such as circles.  The aspect ratio is the quotient
434 of xdpcm and ydpcm, which are integer values.
435
436
437 typedef struct {
438         GR_SIZE         rows;           /* number of rows on screen */
439         GR_SIZE         cols;           /* number of columns on screen */
440         GR_SIZE         xdpcm;          /* dots/centimeter in x direction */
441         GR_SIZE         ydpcm;          /* dots/centimeter in y direction */
442         GR_COLOR        maxcolor;       /* maximum legal color value */
443         GR_COLOR        black;          /* the color black */
444         GR_COLOR        white;          /* the color white */
445         GR_COUNT        fonts;          /* number of built-in fonts */
446         GR_BUTTON       buttons;        /* buttons which are implemented */
447         GR_MODIFIER     modifiers;      /* modifiers which are implemented */
448 } GR_SCREEN_INFO;
449
450
451 INCLUDE FILE AND GRAPHICS LIBRARY
452
453 To use the graphics server, your program must include "graphics.h".
454 This should be put into /usr/include, so that your program simply has
455 the following line at the top:
456         #include <graphics.h>
457
458 Including this file gives you all of the definitions you need to use the
459 graphics library.  These are the typedefs, function declarations, event
460 structures, and various constants.
461
462 When loading your program, you need to load the graphics server into the
463 program by using the -lgraph option in the cc command.  For example, if
464 your program is called myprog, then you could build it using the following:
465         cc -o myprog myprog.c -lgraph
466
467
468 TYPEDEFS
469
470 The following is a list of the typedefs in the include file, and a short
471 description of their purpose.  Refer to their definitions in graphics.h
472 to find out what their actual C base type is.  Most are shorts, unsigned
473 shorts, or longs.
474
475 GR_COORD        coordinate value (x, y locations, signed)
476 GR_SIZE         size value (widths, heights, signed)
477 GR_COUNT        number of items (signed)
478 GR_COLOR        full color value (32 bit value for full generality)
479 GR_COLOR8       eight bit color value (8 bit value for efficient storage)
480 GR_BITMAP       bitmap unit (single words of 16 bits for bitmaps)
481 GR_MODE         drawing mode (setting, xoring, anding, oring)
482 GR_CHAR         text character (normal chars)
483 GR_ID           resource ids (window, graphics context, pixmap)
484 GR_DRAW_ID      drawable id (window, pixmap)
485 GR_WINDOW_ID    window id (identifies individual window)
486 GR_PIXMAP_ID    pixmap id (identifies individual pixmaps, not yet used)
487 GR_GC_ID        graphics context id (identifies indiviual graphics contexts)
488 GR_FONT         font number (identifies individual fonts, first few built-in)
489 GR_BOOL         boolean value (GR_TRUE or GR_FALSE)
490 GR_FUNC         function codes (not for clients to use)
491 GR_ERROR        error value (reasons for graphics calls to fail)
492 GR_EVENT_TYPE   event types (identifies the type of event)
493 GR_BUTTON       button flags (which mouse buttons are depressed)
494 GR_MODIFIER     modifier flags (CTRL, SHIFT, etc)
495 GR_EVENT_MASK   event masks (mask values corresponding to event types)
496 GR_FUNC_NAME    function name (for error reporting)
497 GR_ERROR_FUNC   error function (for defining error handlers)
498
499
500 The following typedefs may be useful to your program.  None of the library
501 functions (currently) accept any of these structures as arguments, except
502 for the GrPoly and GrFillPoly routines, which use GR_POINT.
503
504
505 typedef struct {
506         GR_COORD        x;              /* x coordinate */
507         GR_COORD        y;              /* y coordinate */
508 } GR_POINT;
509
510 typedef struct {
511         GR_COORD        x1;             /* x coordinate of first point */
512         GR_COORD        y1;             /* y coordinate of first point */
513         GR_COORD        x2;             /* x coordinate of second point */
514         GR_COORD        y2;             /* y coordinate of second point */
515 } GR_LINE;
516
517 typedef struct {
518         GR_COORD        x;              /* x coordinate of center */
519         GR_COORD        y;              /* y coordinate of center */
520         GR_SIZE         rx;             /* radius in x direction */
521         GR_SIZE         ry;             /* radius in y direction */
522 } GR_ELLIPSE;
523
524 typedef struct {
525         GR_COORD        x;              /* x coordinate of top left corner */
526         GR_COORD        y;              /* y coordinate of top left corner */
527         GR_SIZE         width;          /* width of rectangle */
528         GR_SIZE         height;         /* height of rectangle */
529 } GR_RECT;
530
531
532 LIMITS
533
534 The coordinate system is limited to integers in the range GR_COORD_MIN
535 to GR_COORD_MAX.  This is -32768 to 32767, and fits in a short.
536
537 The maximum size of a cursor definition is GR_MAX_CURSOR_SIZE, which is
538 16 pixels by 16 pixels.
539
540 The complexity of overlapping windows is limited to GR_MAX_CLIPRECTS regions,
541 which is 200.  Each window which overlaps another requires another 1 to 4
542 regions depending on its position and size.
543
544
545 GRAPHICS CALLS
546
547
548 int
549 GrOpen()
550 Open a connection to the graphics server.  This must be the first graphics
551 function used by your program.  Currently, this sets the screen into
552 graphics mode.  Returns zero if successful, -1 on failure.
553
554
555 void
556 GrClose()
557 Close the connection to the graphics server, first flushing any graphics
558 calls that have been buffered.  Currently, this sets the screen back into
559 text mode.  This (currently) should be called before your program exits,
560 otherwise the screen will be left in graphics mode.  If this occurs, you
561 can run the 'tm' program to reset the terminal to text mode.
562
563
564 GR_ERROR_FUNC
565 GrSetErrorHandler(func)
566         GR_ERROR_FUNC   func;           /* function to handle errors */
567 Set an error handling routine, which will be called on any errors from
568 the server (when events are asked for by the client).  If zero is given,
569 then a default routine will be used which will describe the error and exit.
570 Returns the previous error handler (0 if none).  When an error occurs,
571 the error handling function is called with the following parameters:
572 GR_ERROR, GR_FUNC_NAME, and GR_ID.  These are the error code, the name
573 of the function which failed, and a resource id (0 if not meaningful).
574 The error routine can return if desired, but without corrective action
575 new errors will probably occur soon.
576
577
578 void
579 GrGetScreenInfo(sip)
580         GR_SCREEN_INFO  *sip;           /* location to return info into */
581 Return useful information about the screen.  This information returned
582 has been documented above.
583
584
585 void
586 GrGetFontInfo(font, fip)
587         GR_FONT         font;           /* font number */
588         GR_FONT_INFO    *fip;           /* address of font info */
589 Return useful information about the specified font number.  This information
590 is the font number, the height of the font, the maximum width of any
591 character in the font, the height of the baseline, a flag indicating whether
592 or not the font is fixed-width, and a table of the individual widths of each
593 character in the font.  If the font is unknown, the returned font number is
594 set to zero and the remainder of the information is undefined.  Refer to
595 graphics.h for a definition of the fields of GR_FONT_INFO.
596
597
598 void
599 GrGetGCInfo(gc, gcip)
600         GR_GC_ID        gc;             /* graphics context */
601         GR_GC_INFO      *gcip;          /* address of graphics context info */
602 Return useful information about the specified graphics context.  This
603 information is the graphics context id, the current font, the foreground
604 and background colors, and so on.  If the graphics context is unknown,
605 the returned id is 0, and the other information is undefined.  Refer to
606 graphics.h for a definition of the fields of GR_GC_INFO.
607
608
609 void
610 GrGetGCTextSize(gc, cp, len, retwidth, retheight, retbase)
611         GR_GC_ID        gc;             /* graphics context containing font */
612         GR_CHAR         *cp;            /* address of text string */
613         GR_SIZE         len;            /* length of text string */
614         GR_SIZE         *retwidth;      /* returned width of string */
615         GR_SIZE         *retheight;     /* returned height of string */
616         GR_SIZE         *retbase;       /* returned height of baseline */
617 Return the size of a text string for the font in a graphics context.
618 This is the width of the string, the height of the string, and the height
619 above the bottom of the font of the baseline for the font.  The returned
620 sizes are in pixels.
621
622
623 void
624 GrGetNextEvent(ep)
625         GR_EVENT        *ep;            /* address where event is returned */
626 Return the next event from the event queue, waiting for it if necessary.
627 If a graphics error had occurred, the error handler will be called at this
628 point.  This routine first flushes any buffered graphics commands.  The
629 GR_EVENT is a union of all the possible events.  The type field of the union
630 indicates which of the possible events took place, and then the correct
631 element of the union can be used to access that particular event type's data.
632
633
634 void
635 GrCheckNextEvent(ep)
636         GR_EVENT        *ep;            /* address where event is returned */
637 Return the next event from the event queue if one is ready.
638 If one is not ready, then the event type GR_EVENT_TYPE_NONE is returned.
639 Therefore, this routine never blocks.  This routine first flushes any
640 buffered graphics commands.
641
642
643 void
644 GrPeekEvent(ep)
645         GR_EVENT        *ep;            /* address where event is returned */
646 Return the next event from the event queue if one is ready, without removing
647 it from the queue.  If one is not ready, then the type GR_EVENT_TYPE_NONE
648 is returned.  This routine never blocks.  This routine first flushes any
649 buffered graphics commands.
650
651
652 void
653 GrSelectEvents(wid, eventmask)
654         GR_WINDOW_ID    wid;            /* window id */
655         GR_EVENT_MASK   eventmask;      /* mask of events wanted */
656 Select events for a window for this client.  The events are a bitmask
657 specifying the events desired for this window.  This totally replaces
658 any previously selected event mask for the window.
659
660
661 GR_WINDOW_ID
662 GrNewWindow(parent, x, y, width, height, bordersize, background, bordercolor)
663         GR_WINDOW_ID    parent;         /* parent id */
664         GR_COORD        x;              /* x position relative to parent */
665         GR_COORD        y;              /* y position relative to parent */
666         GR_SIZE         width;          /* width */
667         GR_SIZE         height;         /* height */
668         GR_SIZE         bordersize;     /* size of border */
669         GR_COLOR        background;     /* background color */
670         GR_COLOR        bordercolor;    /* border color */
671 Allocate a new input-output window which is a child of the specified window.
672 A new top-level window is made by specifying a parent of GR_ROOT_WINDOW_ID.
673 The x and y position is the upper left corner of the window, relative to
674 the parent's upper left corner.  These corners are only for the drawable
675 area of the windows, so that the border does not affect the position.  An
676 input-output window cannot be made as a child of an input-only window.  The
677 new window starts off unmapped, and must be mapped before it can be seen.
678 The new window inherits the cursor of the parent window, and initially is
679 set to select no events.  This routine returns the window id of the window
680 which can be used in other calls.
681
682
683 GR_WINDOW_ID
684 GrNewInputWindow(parent, x, y, width, height)
685         GR_WINDOW_ID    parent;         /* parent id */
686         GR_COORD        x;              /* x position relative to parent */
687         GR_COORD        y;              /* y position relative to parent */
688         GR_SIZE         width;          /* width */
689         GR_SIZE         height;         /* height */
690 Allocate a new input-only window which is a child of the specified window.
691 An input-only window is invisible, and cannot be drawn into.  It's only
692 purposes are that it can select events, and can have it's own cursor.  The
693 new window starts off unmapped, and must be mapped before it is effective.
694 The new window inherits the cursor of the parent window, and initially is
695 set to select no events.  This routine returns the window id of the window
696 which can be used in other calls.
697
698
699 void
700 GrDestroyWindow(wid)
701         GR_WINDOW_ID    wid;            /* window to destroy */
702 This unmaps and then destroys the specified window, and all of its children.
703 The root window cannot be destroyed.  After destroying a window, you must be
704 careful about handling events which refer to the dead window, but which have
705 not been read yet.
706
707
708 void
709 GrGetWindowInfo(wid, wip)
710         GR_WINDOW_ID    wid;            /* window id to find out about */
711         GR_WINDOW_INFO  *wip;           /* location to return info into */
712 Return useful information about the specified window.  Refer to the
713 graphics.h include file for the definition of GR_WINDOW_INFO to see
714 what data is returned.  If the window id is not valid, an error is NOT
715 generated.  Instead, the wid value in the returned structure is set to
716 zero, and the other fields are not defined.
717
718
719 GR_GC_ID
720 GrNewGC()
721 Allocate a new graphics context with default parameters.  These defaults are:
722 background of black, foreground of white, font as font 0, and drawing mode
723 as setting.  This routine returns the id for the graphics context which can
724 be used in other calls.
725
726
727 GR_GC_ID
728 GrCopyGC(gc)
729         GR_GC_ID        gc;             /* graphics context to copy */
730 Allocate a new graphics context which is a copy of another one.  The new
731 graphics context has the same parameter values as the old one, but is then
732 independent.  This routine returns the id for the graphics context which
733 can be used in other calls.
734
735
736 void
737 GrDestroyGC(gc)
738         GR_GC_ID        gc;             /* graphics context to destroy */
739 Destroy an existing graphics context.
740
741
742 void
743 GrMapWindow(wid)
744         GR_WINDOW_ID    wid;            /* window to be mapped */
745 Map the window to make it (and possibly its children) visible on the screen.
746 This paints the border and background of the window, and creates an
747 exposure event to tell the client to draw into it.
748
749
750 void
751 GrUnmapWindow(wid)
752         GR_WINDOW_ID    wid;            /* window to be unmapped */
753 Unmap the window to make it and its children invisible on the screen.
754
755
756 void
757 GrRaiseWindow(wid)
758         GR_WINDOW_ID    wid;            /* window to be raised */
759 Raise the window to the highest level among its siblings.  This means that
760 this window will be visible in preference to those siblings.  Siblings are
761 windows which have the same parent as this window.
762
763
764 void
765 GrLowerWindow(wid)
766         GR_WINDOW_ID    wid;            /* window to be lowered */
767 Lower the window to the lowest level among its siblings.  This means that
768 this window will be covered by any siblings which overlap it.
769
770
771 void
772 GrMoveWindow(wid, x, y)
773         GR_WINDOW_ID    wid;            /* window to be lowered */
774         GR_COORD        x;              /* new relative x position */
775         GR_COORD        y;              /* new relative y position */
776 Move the window to the specified position relative to its parent.
777
778
779 void
780 GrResizeWindow(wid, width, height)
781         GR_WINDOW_ID    wid;            /* window to be lowered */
782         GR_SIZE         width;          /* new width of window */
783         GR_SIZE         height;         /* new height of window */
784 Resize the window to be the specified size.  Resizing of a window can
785 generate exposure events.
786
787
788 void
789 GrClearWindow(wid, exposeflag)
790         GR_WINDOW_ID    wid;            /* window id */
791         GR_BOOL         exposeflag;     /* nonzero to cause an exposure */
792 Clear the specified window by setting it to its background color.
793 If the exposeflag is nonzero, then this also creates an exposure
794 event for the window.
795
796
797 void
798 GrSetFocus(wid)
799         GR_WINDOW_ID    wid;            /* window id */
800 Set the focus to a particular window.  This makes keyboard events only
801 visible to that window or children of it, depending on the pointer location.
802 Setting the focus window to the root window makes the input focus track
803 the pointer (which is the default).
804
805
806 void
807 GrSetBorderColor(wid, color)
808         GR_WINDOW_ID    wid;            /* window id */
809         GR_COLOR        color;          /* color for border */
810 Set the border of a window to the specified color.
811
812
813 void
814 GrSetCursor(wid, width, height, hotx, hoty, foreground, background,
815         fgbitmap, bgbitmap)
816
817         GR_WINDOW_ID    wid;            /* window id to set cursor for */
818         GR_SIZE         width;          /* width of cursor */
819         GR_SIZE         height;         /* height of cursor */
820         GR_COORD        hotx;           /* relative x position of hot spot */
821         GR_COORD        hoty;           /* relative y position of hot spot */
822         GR_COLOR        foreground;     /* foreground color of cursor */
823         GR_COLOR        background;     /* background color of cursor */
824         GR_BITMAP       *fgbitmap;      /* foreground bitmap */
825         GR_BITMAP       *bgbitmap;      /* background bitmap */
826 Specify a new cursor for a window.  This cursor will only be used within
827 that window, and by default for its new children.  The cursor is defined
828 by giving its width and height, its foreground and background colors, its
829 foreground and background bitmaps, and its "hot spot" position.  If a pixel
830 is specified for both the foreground and background bitmaps, then the
831 foreground has precedence.  The hot spot is an offset from the upper left
832 corner of the bitmap, and is the location in the cursor which is important.
833
834
835 void
836 GrMoveCursor(x, y)
837         GR_COORD        x;              /* new x position of cursor */
838         GR_COORD        y;              /* new y position of cursor */
839 Move the cursor to the specified absolute screen coordinates.
840 The coordinates are that of the defined hot spot of the cursor.
841 The cursor's appearance is changed to that defined for the window
842 in which the cursor is moved to.
843
844
845 void
846 GrFlush()
847 Flush the graphics buffer so that all previous requests will be executed.
848 This is only needed if you do not check events quickly and want to see the
849 results on the screen soon, since checking for events does an automatic flush.
850
851
852 void
853 GrSetGCForeground(gc, foreground)
854         GR_GC_ID        gc;             /* graphics context id */
855         GR_COLOR        foreground;     /* foreground color */
856 Set the foreground color in a graphics context.  The default is white.
857
858
859 void
860 GrSetGCBackground(gc, background)
861         GR_GC_ID        gc;             /* graphics context id */
862         GR_COLOR        background;     /* background color */
863 Set the background color in a graphics context.  The default is black.
864
865
866 void
867 GrSetGCUseBackground(gc, flag)
868         GR_GC_ID        gc;             /* graphics context id */
869         GR_BOOL         flag;           /* TRUE if background is drawn */
870 Set whether or not the background color is drawn in bitmaps and text.
871 This affects GrBitmap, GrArea8, and GrText.  The default is GR_TRUE.
872
873
874 void
875 GrSetGCMode(gc, mode)
876         GR_GC_ID        gc;             /* graphics context id */
877         GR_MODE         mode;           /* drawing mode */
878 Set the drawing mode in a graphics context.  The drawing mode is one of
879 GR_MODE_SET, GR_MODE_XOR, GR_MODE_AND, or GR_MODE_OR.  The default is
880 GR_MODE_SET.
881
882
883 void
884 GrSetGCFont(gc, font)
885         GR_GC_ID        gc;             /* graphics context id */
886         GR_FONT         font;           /* text font */
887 Set the font used for text drawing in a graphics context.
888 The font is a number identifying one of several fonts.
889 Font number 0 is always available, and is the default font.
890
891
892 void
893 GrLine(id, gc, x1, y1, x2, y2)
894         GR_DRAW_ID      id;
895         GR_GC_ID        gc;
896         GR_COORD        x1;
897         GR_COORD        y1;
898         GR_COORD        x2;
899         GR_COORD        y2;
900 Draw a line in the specified drawable using the specified graphics context.
901
902
903 void
904 GrRect(id, gc, x, y, width, height)
905         GR_DRAW_ID      id;
906         GR_GC_ID        gc;
907         GR_COORD        x;
908         GR_COORD        y;
909         GR_SIZE         width;
910         GR_SIZE         height;
911 Draw the boundary of a rectangle in the specified drawable using the
912 specified graphics context.
913
914
915 void
916 GrFillRect(id, gc, x, y, width, height)
917         GR_DRAW_ID      id;
918         GR_GC_ID        gc;
919         GR_COORD        x;
920         GR_COORD        y;
921         GR_SIZE         width;
922         GR_SIZE         height;
923 Fill a rectangle in the specified drawable using the specified graphics
924 context.  The boundary of this rectangle is identical to that drawn by
925 the GrRect function.
926
927
928 void
929 GrEllipse(id, gc, x, y, rx, ry)
930         GR_DRAW_ID      id;
931         GR_GC_ID        gc;
932         GR_COORD        x;
933         GR_COORD        y;
934         GR_SIZE         rx;
935         GR_SIZE         ry;
936 Draw the boundary of an ellipse in the specified drawable with
937 the specified graphics context.
938
939
940 void
941 GrFillEllipse(id, gc, x, y, rx, ry)
942         GR_DRAW_ID      id;
943         GR_GC_ID        gc;
944         GR_COORD        x;
945         GR_COORD        y;
946         GR_SIZE         rx;
947         GR_SIZE         ry;
948 Fill an ellipse in the specified drawable using the specified
949 graphics context.
950
951
952 void
953 GrBitmap(id, gc, x, y, width, height, bitmaptable)
954         GR_DRAW_ID      id;
955         GR_GC_ID        gc;
956         GR_COORD        x;
957         GR_COORD        y;
958         GR_SIZE         width;
959         GR_SIZE         height;
960         GR_BITMAP       *bitmaptable;
961 Draw a rectangular area in the specified drawable using the specified
962 graphics context, as determined by the specified bit map.  This differs
963 from rectangle drawing in that the rectangle is drawn using the foreground
964 color and possibly the background color as determined by the bit map.
965 Bits which are 1 are the foreground, and bits which are 0 are the background.
966 Each row of bits is aligned to the next bitmap word boundary (so there can
967 be padding at the end of each row).  The background bit values are only
968 written if the usebackground flag is set in the GC.
969
970
971 void
972 GrArea8(id, gc, x, y, width, height, colortable)
973         GR_DRAW_ID      id;
974         GR_GC_ID        gc;
975         GR_COORD        x;
976         GR_COORD        y;
977         GR_SIZE         width;
978         GR_SIZE         height;
979         GR_COLOR8       *colortable;
980 Draw a rectangular area in the specified drawable using the specified
981 graphics context.  This differs from rectangle drawing in that the
982 color values for each pixel in the rectangle are specified.  The color
983 values are estricted to 8 bit values.  The color table is indexed row by
984 row from left to right.  Table values whose color matches the background
985 color are only written if the usebackground flag is set in the GC.
986
987
988 void
989 GrReadArea8(id, x, y, width, height, colortable)
990         GR_DRAW_ID      id;
991         GR_COORD        x;
992         GR_COORD        y;
993         GR_SIZE         width;
994         GR_SIZE         height;
995         GR_COLOR8       *colortable;
996 Read the color values from the specified rectangular area of the specified
997 drawable into a supplied buffer.  If the drawable is a window which is
998 obscured by other windows, then the returned values will include the values
999 from the covering windows.  Regions outside of the screen boundaries, or
1000 from unmapped windows will return black.
1001
1002
1003 void
1004 GrPoint(id, gc, x, y)
1005         GR_DRAW_ID      id;
1006         GR_GC_ID        gc;
1007         GR_COORD        x;
1008         GR_COORD        y;
1009 Draw a point in the specified drawable using the specified graphics context.
1010
1011
1012 void
1013 GrPoly(id, gc, count, pointtable)
1014         GR_DRAW_ID      id;
1015         GR_GC_ID        gc;
1016         GR_COUNT        count;
1017         GR_POINT        *pointtable;
1018 Draw a polygon in the specified drawable using the specified graphics
1019 context.  The polygon is only complete if the first point is repeated at
1020 the end.  Note: currently if the polygon crosses itself, and the drawing
1021 mode is set to XOR, then the individual line segments will affect each
1022 other.  The endpoints of the lines are correct, however.
1023
1024
1025 void
1026 GrFillPoly(id, gc, count, pointtable)
1027         GR_DRAW_ID      id;
1028         GR_GC_ID        gc;
1029         GR_COUNT        count;
1030         GR_POINT        *pointtable;
1031 Draw a filled polygon in the specified drawable using the specified
1032 graphics context.  The last point may be a duplicate of the first point,
1033 but this is not required.  Note: currently only convex polygons are
1034 filled properly.
1035
1036
1037 void
1038 GrText(id, gc, x, y, str, count)
1039         GR_DRAW_ID      id;
1040         GR_GC_ID        gc;
1041         GR_COORD        x;
1042         GR_COORD        y;
1043         GR_CHAR         *str;
1044         GR_COUNT        count;
1045 Draw a text string at the specified location in the specified drawable
1046 using the specified graphics context.  The background of the characters
1047 are only drawn if the usebackground flag in the GC is set.
1048
1049
1050 EXAMPLE PROGRAM
1051
1052 The following simple program opens the graphics, creates a window, prints
1053 some text in it, waits for the mouse to be clicked in the window, then exits.
1054
1055
1056 #include <stdio.h>
1057 #include <graphics.h>
1058
1059 #define MARGIN  50                      /* margin around window */
1060
1061
1062 main()
1063 {
1064         GR_WINDOW_ID    wid;            /* window id */
1065         GR_GC_ID        gc;             /* graphics context id */
1066         GR_EVENT        event;          /* current event */
1067         GR_SCREEN_INFO  si;             /* screen information */
1068
1069         if (GrOpen() < 0) {
1070                 fprintf(stderr, "Cannot open graphics\n");
1071                 exit(1);
1072         }
1073
1074         GrGetScreenInfo(&si);
1075
1076         wid = GrNewWindow(GR_ROOT_WINDOW_ID, MARGIN, MARGIN,
1077                 si.cols - MARGIN * 2, si.rows - MARGIN * 2,
1078                 1, si.black, si.white);
1079
1080         GrSelectEvents(wid, GR_EVENT_MASK_BUTTON_DOWN | GR_EVENT_MASK_EXPOSURE);
1081         GrMapWindow(wid);
1082         gc = GrNewGC();
1083
1084         while (1) {
1085                 GrGetNextEvent(&event);
1086                 switch (event.type) {
1087                         case GR_EVENT_TYPE_BUTTON_DOWN:
1088                                 if (event.button.wid != wid)
1089                                         break;
1090                                 GrClose();
1091                                 exit(0);
1092
1093                         case GR_EVENT_TYPE_EXPOSURE:
1094                                 if (event.exposure.wid == wid)
1095                                         GrText(wid, gc, 50, 50, "EXIT", 4);
1096                                 break;
1097                 }
1098         }
1099 }
1100
1101
1102 For a more complete demonstration program, see the file "demo.c" in the
1103 /usr/src/graphics/clients directory.