§1  PICTURES  INTRODUCTION AND MAIN DATA STRUCTURES 1

1. Introduction and main data structures. This is the file that contains the central part of the source code for graphical interface under the ‘X Windows’ enviroment to a library of algorithms to manipulate mathematical “pictures” as defined in [Zel]. That library, which is contained in the file , was written by Marc van Leeuwen, while the graphical interface, contained in this file and the remaining

files,  ,  ,  and  , was written by James Faux.

2. As this interface relies mostly on the functionality provided by ‘Xlib’, relatively little use is made of the standard ‘C’ libraries; nevertheless a few functions are occasionaly needed, so we load these standard header files. #include /∗ stderr , fprintf , sprintf ∗/ #include /∗ strlen, strcpy , strcmp ∗/ #include /∗ atoi , exit , free ∗/ #include /∗ isdigit ∗/

3. There is one general header file that does all the includes needed for the graphical interface compilation units, in a proper order; it will be defined by this file. #include

4. There is one header file that is only needed here, and not in the other compilation units. The file defines the bitmap picts bits that can be used by some window managers as an icon for the main window; it also defines the related quantities picts width and picts height . #include

5. Local functions will precede the globally visible ones (which are defined in unnamed sections); this slightly facilitates a top-down presentation of the functions. #define local static

format local static

⟨ Global variable definitions 14 ⟩

⟨ Local typedefs 12 ⟩

⟨ Local function definitions 27 ⟩

6. The include file is shared by all the graphical interface compilation units. It makes sure that all common typedefs are seen before the header files of the individual units are read in. The external declarations for this compilation unit go directly into the file. ⟨ 6 ⟩ ≡

⟨ X Header files 8 ⟩ #include

⟨ Global constant and macro definitions 10 ⟩ ⟨ Global typedefs 11 ⟩ ⟨ Inter module include files 7 ⟩ ⟨ Global function declarations 40 ⟩ ⟨ External variable declarations 13 ⟩

7. These are the external declarations for the other files. ⟨ Inter module include files 7 ⟩ ≡ #include #include #include #include #include

This code is used in section 6.

2  INTRODUCTION AND MAIN DATA STRUCTURES  PICTURES §8

8. Programs that use the ‘X Windows’ enviroment should include certain header files so that they know about the functions available in the libraries. ⟨ X Header files 8 ⟩ ≡ #include #include #include #include

See also section 9. This code is used in section 6.

9. One other ‘X’ header file is required: which defines the identification numbers for the cursor shapes. ⟨ X Header files 8 ⟩ +≡ #include

10. The following macros are used for convenience to access the black and white pixel colours of the screen, and the root window identifier. ⟨ Global constant and macro definitions 10 ⟩ ≡ #define WhitePixel (display , screen) #define BlackPixel (display , screen)

See also sections 32 and 42. This code is used in section 6.

11. The pointer type win w will be used universally instead of Window to refer to the windows of this program. If p is a pointer of type win w then the associated ordinary Window value will be p→w, and p can be recovered from p→w by hash table lookup. The other fields of ∗p contain additional information; the complete structure will be detailed below. ⟨ Global typedefs 11 ⟩ ≡

typedef struct window table entry ∗win p;

typedef struct outer window ∗p outer window; typedef struct inner window ∗p inner window; typedef struct diagram window ∗p diagram window; typedef struct picture window ∗p picture window; typedef struct main window ∗p main window;

See also sections 35, 36, and 37. This code is used in section 6.

12. This structure is used to record values that may have been selected via the command line. There are foreground and background colour fields fg colour and bg colour , and geometry fields geo x and geo y , which represent the x and y coordinates of the origin of the main window, and height which sets its initial height. #define colour length 80 ⟨ Local typedefs 12 ⟩ ≡

typedef struct

{ char fg colour [colour length], bg colour [colour length]; int geo x , geo y ; int height ;

} settings;

This code is used in section 5.

13. Apart from the main window, there are some more global variables. The values display and/or screen are used in nearly every call to an Xlib routine, so it simplifies routine calls to declare them global. For similar reasons the main windows current width and height are declared global. Also there is a global declaration for the variables required to set the foreground pixel colours and border pixel colour as well as the graphics contexts. The two variables buttonfont and coordfont point to two sets of font information, and bf height and cf height contain the heights of these fonts. ⟨ External variable declarations 13 ⟩ ≡

extern win p root window , base window ; extern p main window info; extern unsigned int window width, window height ; extern Display ∗display ; extern int screen; extern unsigned long fg pixel , bg pixel , border pixel ; extern GC gc_{1}, gc_{2}, gc_{3}, gc_{4}; extern XFontStruct ∗button font , ∗coord font ; extern int bf height , cf height ; extern Pixmap icon pixmap;

See also sections 33 and 38. This code is used in section 6.

14. ⟨ Global variable definitions 14 ⟩ ≡

win p root window , base window ; /∗ root and main window handles ∗/ p main window info; /∗ information assiciated with the main window ∗/ unsigned int window width ⇐ ,

window height ⇐ ; Display ∗display ; /∗ identification of X-server controlling the display ∗/ int screen; /∗ ientification of screen used by the X-server ∗/ unsigned long fg pixel , bg pixel , border pixel ; /∗ colour values ∗/ GC gc_{1}, gc_{2}, gc_{3}, gc_{4}; /∗ graphic contexts ∗/ XFontStruct ∗button font , ∗coord font ; /∗ fonts used ∗/ int bf height , cf height ; /∗ font dimensions ∗/ Pixmap icon pixmap; /∗ A structure containing the icon information. ∗/

See also sections 34 and 39. This code is used in section 5.

4  OBLIGATORY MANOEUVRES  PICTURES §15

15. Obligatory manoeuvres. There are a number of things that need to be done before any really interesting actions can be taken, such as connecting to the X-server and displaying the main window. These will be performed by the function main, after which it calls the event handler that takes over control until the user quits the program.

int main (int argc, char ∗∗argv )

{ ⟨ Local variables of main 16 ⟩ ⟨ Parse the command line 17 ⟩ ⟨ Connect to the X-server 19 ⟩ ⟨ Configure the screen 20 ⟩ ⟨ Get the requested colours 21 ⟩ root window ⇐ win enter (RootWindow (display , screen)); ⟨ Create and map the main window 22 ⟩ event handler ( ); return 0;

}

16. On the command line, the user can define some dimensions and colours to be used by the program. These will be recorded in the structure set . ⟨ Local variables of main 16 ⟩ ≡

settings set ;

This code is used in section 15.

17. We are rather strict with respect to what is allowed on the command line: all arguments must come key-value pairs; if anything else is present, the function usage is called which will terminate the program with a message of the proper usage. Since for argc the program name counts as an argument, argc must be odd. ⟨ Parse the command line 17 ⟩ ≡

{ int i; set .geo x ⇐ set .geo y ⇐ 100; set .height ⇐ ; set .bg colour [0] ⇐ set .fg colour [0] ⇐ ; if (argc % 2 = 0) usage( ); for (i ⇐ 1; i < argc; i ⇐ i + 2) if (argv [i][0] ≠ ) usage( ); else ⟨ Set the option in argv [i] and argv [i + 1] 18 ⟩

}

This code is used in section 15.

18. The allowed keys are  ,  ,  , and  . The local functions set geometry and

set height are defined below, and assign values to the appropriate fields of set . ⟨ Set the option in argv [i] and argv [i + 1] 18 ⟩ ≡

if (strcmp(argv [i], ) = 0)

if (strlen(argv [i + 1]) < colour length) strcpy (set .bg colour , argv [i + 1]);

else fprintf (stderr , ␣ ␣ ␣ ␣ , argv [i + 1]); else if (strcmp(argv [i], ) = 0)

if (strlen(argv [i + 1]) < colour length) strcpy (set .fg colour , argv [i + 1]);

else fprintf (stderr , ␣ ␣ ␣ ␣ , argv [i + 1]); else if (strcmp(argv [i], ) = 0) set geometry (&set , argv [i + 1]); else if (strcmp(argv [i], ) = 0) set height (&set , argv [i + 1]); else usage( );

This code is used in section 17.

§19  PICTURES  OBLIGATORY MANOEUVRES 5

19. A connection to the X-server indicated by environment variable is established by calling XOpenDisplay . It returns a pointer to the Display structure for the server, or ⊙ if the connection fails, in which case the program terminates with an error message. ⟨ Connect to the X-server 19 ⟩ ≡

{ if ((display ⇐ XOpenDisplay (⊙)) = ⊙) fatal (  ␣    ␣  ); }

This code is used in section 15.

20. The desired origin position is recorded in set .(geo x , geo y ); if however the screen turns out to be to small to allow the window to fit at this position, these coordinates are decreased to make a fit possible. If the screen is to small to allow for the main window at all, we give up and quit.

#define  400  /∗ initialises window width ∗/
#define  400  /∗ initialises window height ∗/
#define  150  /∗ lower bound for window height ∗/
#define  5000  /∗ upper bound for window height ∗/

⟨ Configure the screen 20 ⟩ ≡

{ screen ⇐ DefaultScreen(display );

{ unsigned long width ⇐ DisplayWidth(display , screen), height ⇐ DisplayHeight (display , screen);

if (width < window width ∨ height < )

fatal ( ␣ ␣ ␣ ␣ ␣ ); if (set .geo x < 0) set .geo x ⇐ 0; if (set .geo y < 0) set .geo y ⇐ 0; if (set .height < ) set .height ⇐ ; if (width < window width + set .geo x ) set .geo x ⇐ width − window width; if (height < window height + set .geo y )

if ((set .geo y ⇐ height − window height ) < 0) set .geo y ⇐ 0, window height ⇐ height ; if (set .height > height ) set .height ⇐ height ;

} }

This code is used in section 15.

21. The user may have specified colours by means of  and  options; if not the defaults are black

and white respectively. Then, if the screen in not black and white (depth = 1), the colours are looked up by XParseColour and allocated into the default colourmap of the screen. If anything goes wrong an error message is issued and the default colour is retained. The foreground colour is used for the border as well. ⟨ Get the requested colours 21 ⟩ ≡

{ char ∗names [2]; int i, colours [2], depth ⇐ DisplayPlanes (display , screen); Colormap cmap ⇐ DefaultColormap(display , screen); XColor exact def ; names [0] ⇐ set .fg colour ; names [1] ⇐ set .bg colour ; colours [0] ⇐ ; colours [1] ⇐ ; if (depth > 1)

for (i ⇐ 0; i < 2; i^{++}) if (names [i][0] ≠ )

if (¬XParseColor (display , cmap, names [i], &exact def ))

fprintf (stderr , ␣ ␣ ␣ ␣ ␣ ␣ , names [i]); else if (¬XAllocColor (display , cmap, &exact def )) { fprintf (stderr , ␣ ); break; } else colours [i] ⇐ exact def .pixel ;

border pixel ⇐ fg pixel ⇐ colours [0]; bg pixel ⇐ colours [1]; }

This code is used in section 15.

22. Before the main window can be displayed (mapped), it must first be registered with the X-server (created) and several attributes must be set. These include an icon, which the window manager might use to represent the window when the user iconifies it, limits imposed on resizing of the window (size hints), the event types that will be transmitted if they occur within this window, the graphic context and the cursor to be used in this window. After the window is mapped, the structure info, containing the data associated by this program to the main window, is initialised. ⟨ Create and map the main window 22 ⟩ ≡

{ ⟨ Create the main window 23 ⟩ ⟨ Define icon pixmap 24 ⟩ ⟨ Set properties for window manager 25 ⟩ load fonts ( ); get graphics context (base window ); /∗ Get the graphics context. ∗/ ⟨ Define cursor for the main window 26 ⟩ map window (base window ); init main data( ); /∗ Initialise the structure info associated to the main window ∗/

}

This code is used in section 15.

23. The main window identification number is called base window ; the number comes into being by a call to XCreateSimpleWindow , which is so called because it has only 9 parameters, the functions of which are as suggested by the actual arguments. ⟨ Create the main window 23 ⟩ ≡

base window ⇐ make window (main win, root window , set .geo x , set .geo y , window width, set .height ); base window →data.main ⇐ info;

This code is used in section 22.

24. Here the icon defined in the file and is converted to a Pixmap value, which is stored in icon pixmap. ⟨ Define icon pixmap 24 ⟩ ≡

icon pixmap ⇐ XCreateBitmapFromData(display , base window →w, picts bits , picts width, picts height );

This code is used in section 22.

25. Initalise size hint property for the window manager to specifies the window position, window size and the smallest size the window can be and still be functional. XSetStandardProperties sets the most important properties for a window. ⟨ Set properties for window manager 25 ⟩ ≡

{ char ∗window name ⇐ ␣ ␣ ␣ ␣ , ∗icon name ⇐ ; XSizeHints h; h.flags ⇐ PPosition | PSize | PMinSize | PMaxSize; h.x ⇐ h.y ⇐ 0; h.width ⇐ window width, h.height ⇐ window height ; h.min width ⇐ window width, h.min height ⇐ window height ; h.max width ⇐ window width, h.max height ⇐ ; XSetStandardProperties

(display , base window →w, window name, icon name, icon pixmap, argv , argc, &h); }

This code is used in section 22.

26. Whenever the cursor is in the main window, its shape is set to XC cross . ⟨ Define cursor for the main window 26 ⟩ ≡

XDefineCursor (display , base window →w, XCreateFontCursor (display , XC cross ));

This code is used in section 22.

27. We come to a few functions that handle the start up details that we have left out so far. First, here is the way we quit is the program is called wrongly.

⟨ Local function definitions 27 ⟩ ≡ local void usage (void) { fprintf (stderr ,

    ␣        ␣    ␣       ␣    ␣       ␣          ␣    ␣        ␣  );

exit (1); }

See also sections 28, 29, 30, and 31. This code is used in section 5.

28. The function set geometry parses the argument following and sets the appropriate fields of set correspondingly.

⟨ Local function definitions 27 ⟩ +≡ local void set geometry (settings ∗set , char ∗s) { char ∗p ⇐ s;

if (¬isdigit (∗p)) usage( ); do ^{++}p; while (isdigit (∗p)); if (∗p ≠ ) usage( ); ∗p ⇐ ; set →geo x ⇐ atoi (s); ∗p^{++} ⇐ ; s ⇐ p; do ^{++}p; while (isdigit (∗p)); if (∗p ≠ ) usage( ); set →geo y ⇐ atoi (s);

}

29. The argument following is similar but simpler.

⟨ Local function definitions 27 ⟩ +≡ local void set height (settings ∗set , char ∗s) { char ∗p ⇐ s;

while (isdigit (∗p)) ^{++}p; if (∗p ≠ ∨ p = s) usage( ); set →height ⇐ atoi (s);

} 30. The functon get graphics context creates the Graphics Context for displaying the text and drawing in various colours, fonts and styles. ⟨ Local function definitions 27 ⟩ +≡

local void get graphics context (win p main win) { XGCValues values ; unsigned long valuemask ⇐ GCLineWidth | GCCapStyle | GCJoinStyle;

values .line width ⇐ 1; values .cap style ⇐ CapRound ; values .join style ⇐ JoinBevel ; gc_{1} ⇐ XCreateGC (display , main win→w, valuemask , &values ); gc_{2} ⇐ XCreateGC (display , main win→w, valuemask , &values ); gc_{3} ⇐ XCreateGC (display , main win→w, valuemask , &values ); gc_{4} ⇐ XCreateGC (display , main win→w, valuemask , &values ); XSetFont (display , gc_{1}, button font →fid ); XSetForeground (display , gc_{1}, fg pixel ); XSetBackground (display , gc_{1}, bg pixel ); XSetFont (display , gc_{2}, button font →fid ); XSetForeground (display , gc_{2}, bg pixel ); XSetBackground (display , gc_{2}, fg pixel ); XSetFont (display , gc_{3}, coord font →fid ); XSetForeground (display , gc_{3}, fg pixel ); XSetBackground (display , gc_{3}, bg pixel ); XSetFont (display , gc_{4}, coord font →fid ); XSetForeground (display , gc_{4}, bg pixel ); XSetBackground (display , gc_{4}, fg pixel );

}

31. The function load fonts loads the fonts needed to display all the characters in the window and exits if the font is not accessable. Finally it sets the font height global variables. #define coord fontname /∗ A narrow font to print coordinates ∗/ #define button fontname /∗ A nice bold font ∗/ ⟨ Local function definitions 27 ⟩ +≡

local void load fonts (void) { if ((coord font ⇐ XLoadQueryFont (display , coord fontname)) = ⊙)

fatal ( ␣ ␣ ␣ coord fontname ); if ((button font ⇐ XLoadQueryFont (display , button fontname)) = ⊙)

fatal ( ␣ ␣ ␣ button fontname ); bf height ⇐ button font →max bounds .ascent + button font →max bounds .descent ; cf height ⇐ coord font →max bounds .ascent + coord font →max bounds .descent ;

§32  PICTURES  THE WINDOW TABLE 9

} 32. The window table. We shall use a central table for adminstrating attributes of the (many) windows the the program uses. One important use of this table is that it allows us to determine the type of window rapidly. There are various kinds of windows, such as the main window, outer and inner windows for diagrams and pictures, the menu bar, its individual menus and many more. The following unemeration gives all the window types. ⟨ Global constant and macro definitions 10 ⟩ +≡

enum window type { main win, diag icon win, pict icon win, outer diag win, outer pict win, inner diag win, pict dom win, pict im win, scrollbar win, scroll up win, scroll down win, scroll left win, scroll right win, comment win, help win, scale win, scale entry win, menu bar win, menu title win, menu list win, menu entry win

};

33. Event handlers for these types of windows will accessed via the following table, which matches precisely the enumeration in the previous section. ⟨ External variable declarations 13 ⟩ +≡

extern event handler table ∗event table[ ], main handlers , icon handlers , outer handlers , inner handlers , scrollbar handlers , scrollarrow handlers , comment handlers , help handlers , scale handlers , scale entry handlers , menu bar handlers , menu title handlers , menu list handlers , menu entry handlers ;

34. ⟨ Global variable definitions 14 ⟩ +≡

event handler table ∗event table[ ] ⇐

{ &main handlers , &icon handlers , &icon handlers

, &outer handlers , &outer handlers , &inner handlers , &inner handlers , &inner handlers , &scrollbar handlers , &scrollarrow handlers , &scrollarrow handlers , &scrollarrow handlers ,

&scrollarrow handlers

, &comment handlers

, &help handlers , &scale handlers , &scale entry handlers

, &menu bar handlers , &menu title handlers , &menu list handlers , &menu entry handlers };

35. The handlers themselves depend not only on the window type of course, but also on the event type. Therefore the pointers like main handlers above point to a structure of type event handler table containing individual event handlers. These are function pointers of types appropriate for the event, which are given convenient names here. ⟨ Global typedefs 11 ⟩ +≡

typedef int windex; /∗ internal index of window ∗/

typedef void (∗SimpleHandler) (win p);

typedef void (∗ButtonPressHandler) (win p, XButtonEvent∗);

typedef void (∗KeyPressHandler) (win p, XKeyEvent∗);

typedef void (∗MotionHandler) (win p, XMotionEvent∗);

10  THE WINDOW TABLE  PICTURES §36

typedef void (∗ConfigureHandler) (win p, XConfigureEvent∗); 36. Here is the type event handler table itself. These tables will be initialised statically with proper function pointers, where unused events will be assigned null pointers as handler. The event mask for the window type is also stored. The actual initialisers will be given where the window type is introduced, so it is important to remember the order of the fields here when reading the initialser lists later. ⟨ Global typedefs 11 ⟩ +≡

typedef struct

{ unsigned long events ; SimpleHandler expose, enter , leave; ButtonPressHandler press , release; KeyPressHandler key ; MotionHandler move; ConfigureHandler configure;

} event handler table;

37. The entries of the window table will contain the Window identification used by ‘X’ so that the proper entry can be located, and the type of the window. Moreover a pointer to the data structure associated to the window is included, so that the handler routines can access the necessary data. Since these data structures vary with the window type, a union is used. ⟨ Global typedefs 11 ⟩ +≡

struct window table entry

{ Window w; enum window type type; union { p main window main; /∗ for main win ∗/

int nr ; /∗ icon number, for diag icon win and pict icon win ∗/

p diagram window diag ; /∗ for outer diag win, inner diag win ∗/ p picture window pict ; /∗ for outer pict win, pict dom win, pict im win ∗/ p inner window inner ; /∗ for comment win ∗/ struct scrollbar ∗scroll ; /∗ for scrollbar win ∗/ struct m list ∗menu; /∗ for menu title win ∗/ struct m entry ∗menu entry ; /∗ for menu entry win ∗/

} data; };

38. The window table itself is simply an array of such entries. #define win tab size 1993 /∗ a recent prime number ∗/ #define win hash(w) (w % win tab size) /∗ simple remainder should be OK ∗/ ⟨ External variable declarations 13 ⟩ +≡

extern struct window table entry win tab[ ];

39. ⟨ Global variable definitions 14 ⟩ +≡

struct window table entry win tab[win tab size];

windex window count ⇐ 0; /∗ number of windows present ∗/ 40. The consversion of a Window value to a win p is achieved by a call to lookup or win enter ; the routines differ in that lookup should only be called for existing windows, or the program will fail, while win enter should only be called for non-existing windows. Windows are never removed from the table, which considerably facilitates its maintenance. Unassigend slots in the table have their w field set to 0; although there appears to be no guarantee that no window ever gets the identification number 0 from the X-server (even if expermental evidence suggests that this is the case), we shall enforce this condition ourselves by some trickery when creating windows. We always keep at least one empty slot to ensure that the loops below will not cycle round indefinitely.

⟨ Global function declarations 40 ⟩ ≡ win p lookup (Window); win p win enter (Window);

See also sections 43, 45, 48, 50, 52, 55, and 58. This code is used in section 6.

41.

win p lookup (Window w)

{ windex i ⇐ win hash(w);

while (win tab[i].w ≠ w)

if (win tab[i].w = 0) fatal ( ␣ ␣ ␣ ␣ ); else i ⇐ (i + 68) % win tab size;

return &win tab[i]; }

win p win enter (Window w)

{ windex i ⇐ win hash(w);

if (^{++}window count = win tab size) fatal (  ␣     ␣  );

while (win tab[i].w ≠ 0)

if (win tab[i].w = w) fatal ( ␣ ␣ ␣ ␣ ); else i ⇐ (i + 68) % win tab size; win tab[i].w ⇐ w; return &win tab[i];

} 42. In order to ensure that all windows will be entered into the table, we define functions to be used instead of direct calls to XCreateSimpleWindow , XSelectInput and XMapWindow ; they will take care of maintaining the table and making the proper calls to ‘X’. ⟨ Global constant and macro definitions 10 ⟩ +≡ #define make window (t, p, x, y, w, h) make simple window (t, p, x, y, w, h, 2) #define make thin window (t, p, x, y, w, h) make simple window (t, p, x, y, w, h, 1) #define make invisible window (t, p, x, y, w, h) make simple window (t, p, x, y, w, h, 0)

43. ⟨ Global function declarations 40 ⟩ +≡

win p make simple window (enum window type, win p, int, int, uint, uint, uint);

44.

win p make simple window

(enum window type t, win p parent , int x, int y, uint w, uint h, uint border ) { Window W ⇐ XCreateSimpleWindow (display , parent →w, x, y, w, h, border , border pixel , bg pixel );

if (W = 0) /∗ then we don’t like it, so let’s but another one ∗/

{ Window tmp ⇐

XCreateSimpleWindow (display , parent →w, x, y, w, h, border , border pixel , bg pixel ); XDestroyWindow (display , W); W ⇐ tmp;

}

{ win p p ⇐ win enter (W); p→type ⇐ t; return p; }

}

45. This function is called in place of XSelectInput and XMapWindow . ⟨ Global function declarations 40 ⟩ +≡

void map window (win p);

46.

void map window (win p p)

{ Window win ⇐ p→w;

XSelectInput (display , win, event table[p→type]→events ); XMapWindow (display , win); }

§47  PICTURES  COORDINATE TRANSFORMATION FUNCTIONS 13

47. Coordinate transformation functions. This group of functions performs coordinate transformations from the pixel coordinates in the respective windows to the logical coordinates within the diagrams and back again.

48. The function window coordinates converts a pair of logical coordinates of for the displayed object to the displayed pixel coordinates of an inner window. ⟨ Global function declarations 40 ⟩ +≡

void window coordinates (p inner window, int, int, int∗ , int∗);

49. Note the interchange of coordinates when going from (i, j) to (x, y) coordinates.

void window coordinates (p inner window w, int i, int j, int ∗x, int ∗y)

{ int scale ⇐ info→scale.box size;

∗x ⇐ scale ∗ j + w→hor →offset ; ∗y ⇐ scale ∗ i + w→vert →offset ; }

50. The function logical coordinates does the opposite to the previous one: it converts a pair of pixel coordinates within an inner window to the logical coordinates of the object displayed in the window. Since we must divide by the scale here and the outcome can be negative, we must work around the defect built into ‘C’ as well as into much hardware, namely that a consistent rounding for positive and negative dividends is not guaranteed respectively offered. The work around is to avoid negative dividends by subtracting from −1 before and after; contrary to ordinary negation, this operation has a translation-invariant effect on the truncation of quotients. If the effect of bitwise operations were guaranteed to be as if the representation were 2’s complement, than this operation could safely (and possibly slightly more efficiently) be performed by ‘∼’. ⟨ Global function declarations 40 ⟩ +≡

void logical coordinates (p inner window w, int, int, int∗ , int∗);

51.

void logical coordinates (p inner window w, int x, int y, int ∗i, int ∗j)

{ int scale ⇐ info→scale.box size; x −⇐ w→hor →offset ; y −⇐ w→vert →offset ; ∗i ⇐ y ≥ 0 ? y/scale : −1 − (−1 − y)/scale; ∗j ⇐ x ≥ 0 ? x/scale : −1 − (−1 − x)/scale;

}

52. Here is a simple wrapper around logical coordinates used to position an anti-diagonal. ⟨ Global function declarations 40 ⟩ +≡

int calculate diagonal (p diagram window, int, int);

53.

int calculate diagonal (p diagram window dw , int x, int y)

{ int i, j;

logical coordinates (&dw →disp, x, y, &i, &j); return i + j; }

14  MISCELLANEOUS FUNCTIONS  PICTURES §54

54. Miscellaneous functions. A set of routines that don’t belong in any of the sections in any of the file used by this program. Instead of construction yet another file, they are to be found below.

55. These functions free all the memory used by a diagram and picture window in there corresponding structures. ⟨ Global function declarations 40 ⟩ +≡

void del diagram memory (p diagram window); void del picture memory (p picture window);

56.

void del diagram memory (p diagram window dw ) { del diag (dw →d); }

57.

void del picture memory (p picture window pw ) { del pict (pw →f);

if (pw →p ≠ ⊙) del pict (pw →p→f), free(pw →p); }

58. When the glissement mode is set, if the standard glissement is required, one of the first two functions are used. If a multiglissement is required, then either the thrid or fourth routine is used. ⟨ Global function declarations 40 ⟩ +≡

void glissement domain window (p picture window, int, int); void glissement image window (p picture window, int, int); void multiglissement domain window (p picture window, int, int); void multiglissement image window (p picture window, int, int);

59.

void glissement domain window (p picture window pw , int x, int y) { int i, j;

logical coordinates (&pw →d, x, y, &i, &j); glissement (&pw →f, i, j);

XClearWindow (display , pw →d.win→w); XClearWindow (display , pw →i.win→w); print complete picture(pw );

}

60.

void glissement image window (p picture window pw , int x, int y) { int i, j; pict p inv ⇐ inverse pict (pw →f);

logical coordinates (&pw →i, x, y, &i, &j); glissement (&inv , i, j); pw →f ⇐ inverse pict (inv ); XClearWindow (display , pw →d.win→w); XClearWindow (display , pw →i.win→w); print complete picture(pw );

}

61.

void multiglissement domain window (p picture window pw , int x, int y) { int i, j;

logical coordinates (&pw →d, x, y, &i, &j); multi glissement (&pw →f, i, j);

XClearWindow (display , pw →d.win→w); XClearWindow (display , pw →i.win→w); print complete picture(pw );

}

§62  PICTURES  MISCELLANEOUS FUNCTIONS 15

62.

void multiglissement image window (p picture window pw , int x, int y) { int i, j; pict p inv ⇐ inverse pict (pw →f);

logical coordinates (&pw →i, x, y, &i, &j); multi glissement (&inv , i, j); pw →f ⇐ inverse pict (inv ); XClearWindow (display , pw →d.win→w); XClearWindow (display , pw →i.win→w); print complete picture(pw );

16  INDEX  PICTURES §63

} 63. Index.

argc: \underline{15}, 17, 25. argv : \underline{15}, 17, 18, 25. ascent : 31. atoi : 28, 29. base window : \underline{13}, \underline{14}, 22, 23, 24, 25, 26. bf height : \underline{13}, \underline{14}, 31. bg colour : \underline{12}, 17, 18, 21. bg pixel : \underline{13}, \underline{14}, 21, 30, 44. : 10, 21. BlackPixel : 10. border : \underline{44}. border pixel : \underline{13}, \underline{14}, 21, 44. box size: 49, 51. button font : \underline{13}, \underline{14}, 30, 31. button fontname: \underline{31}. buttonfont : 13. ButtonPressHandler: \underline{35}, 36. calculate diagonal : \underline{52}, \underline{53}. cap style: 30. CapRound : 30. cf height : \underline{13}, \underline{14}, 31. cmap: \underline{21}. Colormap: 21. colour length: \underline{12}, 18. colours : \underline{21}. comment handlers : \underline{33}, 34. comment win: \underline{32}, 37. configure: \underline{36}. ConfigureHandler: \underline{35}, 36. coord font : \underline{13}, \underline{14}, 30, 31. coord fontname: \underline{31}. coordfont : 13. data: 23, \underline{37}. DefaultColormap: 21. DefaultScreen: 20. del diag : 56. del diagram memory : \underline{55}, \underline{56}. del pict : 57. del picture memory : \underline{55}, \underline{57}. depth: \underline{21}. descent : 31. diag : \underline{37}. diag icon win: \underline{32}, 37. diagram window : 11. disp: 53. display : 10, \underline{13}, \underline{14}, 15, 19, 20, 21, 24, 25, 26, 30,

31, 44, 46, 59, 60, 61, 62. : 19. Display: 13, 14, 19. DisplayHeight : 20. DisplayPlanes : 21.

DisplayWidth: 20.

dw : \underline{53}, \underline{56}. enter : \underline{36}. event handler : 15. event handler table: 33, 34, 35, \underline{36}. event table: \underline{33}, \underline{34}, 46. events : \underline{36}, 46. exact def : \underline{21}. exit : 27. expose: \underline{36}. fatal : 19, 20, 31, 41. fg colour : \underline{12}, 17, 18, 21. fg pixel : \underline{13}, \underline{14}, 21, 30. fid : 30. flags : 25. fprintf : 18, 21, 27. free: 57. GC: 13, 14. GCCapStyle: 30. GCJoinStyle: 30. GCLineWidth: 30. gc_{1}: \underline{13}, \underline{14}, 30. gc_{2}: \underline{13}, \underline{14}, 30. gc_{3}: \underline{13}, \underline{14}, 30. gc_{4}: \underline{13}, \underline{14}, 30. geo x : \underline{12}, 17, 20, 23, 28. geo y : \underline{12}, 17, 20, 23, 28. get graphics context : 22, \underline{30}. glissement : 59, 60. glissement domain window : \underline{58}, \underline{59}. glissement image window : \underline{58}, \underline{60}. h: \underline{25}, \underline{44}. height : \underline{12}, 17, \underline{20}, 23, 25, 29. help handlers : \underline{33}, 34. help win: \underline{32}. hor : 49, 51. i: \underline{17}, \underline{21}, \underline{41}, \underline{49}, \underline{51}, \underline{53}, \underline{59}, \underline{60}, \underline{61}, \underline{62}. icon handlers : \underline{33}, 34. icon name: \underline{25}. icon pixmap: \underline{13}, \underline{14}, 24, 25. info: \underline{13}, \underline{14}, 22, 23, 49, 51. init main data: 22. inner : \underline{37}. inner diag win: \underline{32}, 37. inner handlers : \underline{33}, 34. inner window : 11. inv : \underline{60}, \underline{62}. inverse pict : 60, 62. isdigit : 28, 29. j: \underline{49}, \underline{51}, \underline{53}, \underline{59}, \underline{60}, \underline{61}, \underline{62}. join style: 30.

§63  PICTURES  INDEX 17

JoinBevel : 30. key : \underline{36}. KeyPressHandler: \underline{35}, 36. leave: \underline{36}. line width: 30. load fonts : 22, \underline{31}. local: \underline{5}. logical coordinates : \underline{50}, \underline{51}, 52, 53, 59, 60, 61, 62. lookup: \underline{40}, \underline{41}. m entry : 37. m list : 37. main: \underline{15}, 23, \underline{37}. main handlers : \underline{33}, 34, 35. main win: 23, \underline{30}, \underline{32}, 37. main window : 11. : \underline{20}, 25. : \underline{20}. : 14, 17, \underline{20}. : 14, \underline{20}. make invisible window : 42. make simple window : 42, \underline{43}, \underline{44}. make thin window : 42. make window : 23, 42. map window : 22, \underline{45}, \underline{46}. max bounds : 31. max height : 25. max width: 25. menu: \underline{37}. menu bar handlers : \underline{33}, 34. menu bar win: \underline{32}. menu entry : \underline{37}. menu entry handlers : \underline{33}, 34. menu entry win: \underline{32}, 37. menu list handlers : \underline{33}, 34. menu list win: \underline{32}. menu title handlers : \underline{33}, 34. menu title win: \underline{32}, 37. min height : 25. min width: 25. MotionHandler: \underline{35}, 36. move: \underline{36}. multi glissement : 61, 62. multiglissement domain window : \underline{58}, \underline{61}. multiglissement image window : \underline{58}, \underline{62}. names : \underline{21}. nr : \underline{37}. offset : 49, 51. outer diag win: \underline{32}, 37. outer handlers : \underline{33}, 34. outer pict win: \underline{32}, 37. outer window : 11. p: \underline{28}, \underline{29}, \underline{44}, \underline{46}.

p diagram window: \underline{11}, 37, 52, 53, 55, 56.
p inner window: \underline{11}, 37, 48, 49, 50, 51.
p main window: \underline{11}, 13, 14, 37.
p outer window: \underline{11}.
p picture window: \underline{11}, 37, 55, 57, 58, 59,

60, 61, 62. parent : \underline{44}. pict : \underline{37}. pict dom win: \underline{32}, 37. pict icon win: \underline{32}, 37. pict im win: \underline{32}, 37. pict p: 60, 62. picts bits : \underline{4}, 24. picts height : \underline{4}, 24. picts width: \underline{4}, 24. picture window : 11. pixel : 21. Pixmap: 13, 14, 24. PMaxSize: 25. PMinSize: 25. PPosition: 25. press : \underline{36}. print complete picture: 59, 60, 61, 62. PSize: 25. pw : \underline{57}, \underline{59}, \underline{60}, \underline{61}, \underline{62}. release: \underline{36}. root window : \underline{13}, \underline{14}, 15, 23. RootWindow : 15. s: \underline{28}, \underline{29}. scale: \underline{49}, \underline{51}. scale entry handlers : \underline{33}, 34. scale entry win: \underline{32}. scale handlers : \underline{33}, 34. scale win: \underline{32}. screen: 10, \underline{13}, \underline{14}, 15, 20, 21. scroll : \underline{37}. scroll down win: \underline{32}. scroll left win: \underline{32}. scroll right win: \underline{32}. scroll up win: \underline{32}. scrollarrow handlers : \underline{33}, 34. scrollbar : 37. scrollbar handlers : \underline{33}, 34. scrollbar win: \underline{32}, 37. set : \underline{16}, 17, 18, 20, 21, 23, \underline{28}, \underline{29}. set geometry : 18, \underline{28}. set height : 18, \underline{29}. settings: \underline{12}, 16, 28, 29. SimpleHandler: \underline{35}, 36. stderr : 18, 21, 27. strcmp: 18. strcpy : 18. strlen: 18. t: \underline{44}. tmp: \underline{44}. type: \underline{37}, 44, 46. uint: 43, 44. usage: 17, 18, \underline{27}, 28, 29. valuemask : \underline{30}. values : \underline{30}. vert : 49, 51. W: \underline{44}. w: \underline{37}, \underline{41}, \underline{44}, \underline{49}, \underline{50}, \underline{51}. : 10, 21. WhitePixel : 10. width: \underline{20}, 25. win: \underline{46}, 59, 60, 61, 62. win enter : 15, \underline{40}, \underline{41}, 44. win hash: \underline{38}, 41. win p: \underline{11}, 13, 14, 30, 35, 40, 41, 43, 44, 45, 46. win tab: \underline{38}, \underline{39}, 41. win tab size: \underline{38}, 39, 41. win w : 11. windex: \underline{35}, 39, 41. Window: 11, 37, 40, 41, 44, 46. window coordinates : \underline{48}, \underline{49}. window count : \underline{39}, 41. window height : \underline{13}, \underline{14}, 20, 25. window name: \underline{25}. window table entry : 11, \underline{37}, 38, 39. window type: 32, 37, 43, 44. window width: \underline{13}, \underline{14}, 20, 23, 25. x: \underline{44}, \underline{49}, \underline{51}, \underline{53}, \underline{59}, \underline{60}, \underline{61}, \underline{62}. XAllocColor : 21. XButtonEvent: 35. XC cross : 26. XClearWindow : 59, 60, 61, 62. XColor: 21. XConfigureEvent: 35. XCreateBitmapFromData: 24. XCreateFontCursor : 26. XCreateGC : 30. XCreateSimpleWindow : 23, 42, 44. XDefineCursor : 26. XDestroyWindow : 44. XFontStruct: 13, 14. XGCValues: 30. XKeyEvent: 35. XLoadQueryFont : 31. XMapWindow : 42, 45, 46. XMotionEvent: 35. XOpenDisplay : 19. XParseColor : 21. XParseColour : 21.

XSelectInput : 42, 45, 46. XSetBackground : 30. XSetFont : 30. XSetForeground : 30. XSetStandardProperties : 25. XSizeHints: 25. y: \underline{44}, \underline{49}, \underline{51}, \underline{53}, \underline{59}, \underline{60}, \underline{61}, \underline{62}.

PICTURES NAMES OF THE MODULES 19

⟨ Configure the screen 20 ⟩ Used in section 15. ⟨ Connect to the X-server 19 ⟩ Used in section 15. ⟨ Create and map the main window 22 ⟩ Used in section 15. ⟨ Create the main window 23 ⟩ Used in section 22. ⟨ Define cursor for the main window 26 ⟩ Used in section 22.

⟨ Define icon pixmap 24 ⟩ Used in section 22.

⟨ External variable declarations 13, 33, 38 ⟩ Used in section 6. ⟨ Get the requested colours 21 ⟩ Used in section 15. ⟨ Global constant and macro definitions 10, 32, 42 ⟩ Used in section 6.

⟨ Global function declarations 40, 43, 45, 48, 50, 52, 55, 58 ⟩ Used in section 6. ⟨ Global typedefs 11, 35, 36, 37 ⟩ Used in section 6.

⟨ Global variable definitions 14, 34, 39 ⟩ Used in section 5. ⟨ Inter module include files 7 ⟩ Used in section 6.

⟨ Local function definitions 27, 28, 29, 30, 31 ⟩ Used in section 5. ⟨ Local typedefs 12 ⟩ Used in section 5.

⟨ Local variables of main 16 ⟩ Used in section 15. ⟨ Parse the command line 17 ⟩ Used in section 15. ⟨ Set properties for window manager 25 ⟩ Used in section 22. ⟨ Set the option in argv [i] and argv [i + 1] 18 ⟩ Used in section 17.

⟨ X Header files 8, 9 ⟩ Used in section 6.

⟨ 6 ⟩

PICTURES

Section Page

Introduction and main data structures . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1 1 Obligatory manoeuvres . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15 4 The window table . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32 9 Coordinate transformation functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47 13 Miscellaneous functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54 14 Index . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63 16