(navigation image)
Home American Libraries | Canadian Libraries | Universal Library | Community Texts | Project Gutenberg | Children's Library | Biodiversity Heritage Library | Additional Collections
Search: Advanced Search
Anonymous User (login or join us)
Upload
See other formats

Full text of "X toolkit intrinsics programming manual : for X11, release 4"

Volume Four 

X Toolkit Intrinsics 
Programming Manual 

Second Edition 
for X11, Release 4 

by. Adrian Nye and Tim O'Reilly 

O'Reilly & Associates, Inc. 



2.3.3 The Application-defaults File ....................................................................................... 38 
2.3.4 To Hardcode or Not to Hardcode ................................................................................. 40 
2.4 Connecting Widgets to Application Code .......................................................................... 41 
2.4.1 Callbacks ........................................................................................................................ 42 
2.4.2 Actions ........................................................................................................................... 45 
2.4.2.1 The Actions Table ..................................................................................................... 48 
2.4.2.2 Format of an Action Procedure ............................................................................... 48 
2.4.2.3 The Translation Table ............................................................................................... 49 
2.4.2.4 Hardcoding Translations .......................................................................................... 51 
2.5 More About Resources ......................................................................................................... 52 
2.5.1 Setting and Getting Resources from the Application ................................................. 52 
2.5.1.1 Setting Resources with the Varargs Interfaces ....................................................... 53 
2.5.1.2 Setting Resources with the ArgList Interfaces ....................................................... 54 
2.5.1.3 Getting a Resource Value ........................................................................................ 56 
2.5.2 Core Resources .............................................................................................................. 57 
2.5.3 Other Inherited Resources ............................................................................................ 59 

3 More Techniques for Using Widgets .................................................................... 65 

3.1 Using Composite Widgets ................................................................................................... 65 
3.1.1 Setting Resources for an Instance Hierarchy .............................................................. 68 
3.1.2 Geometry Management in Practice .............................................................................. 69 
3.2 Using Conslraint Widgets .................................................................................................... 72 
3.3 Using Pop Ups ...................................................................................................................... 75 
3.4 More About Callbacks ......................................................................................................... 81 
3.4.1 Passing Data to Callback Functions ............................................................................. 81 
3.4.2 Callback Lists ................................................................................................................ 84 
3.5 Application Resources ......................................................................................................... 85 
3.5.1 The Application Data Structure .................................................................................... 86 
3.5.2 The Resource List .......................................................................................................... 86 
3.5.3 Getting the Resources ................................................................................................... 90 
3.6 Command-line Options ........................................................................................................ 91 
3.6.1 Standard Command-line Options ................................................................................. 91 
3.6.2 Defining Your Own Command-line Options ............................................................... 93 
3.7 Preventing User Customization of Widget Resources ....................................................... 97 
3.7.1 Using the Varargs Interfaces ......................................................................................... 97 
3.7.2 Using the Argument List Interfaces ............................................................................. 99 
3.7.2.1 Another Way to Set Arguments ............................................................................. 100 
3.7.2.2 Merging Argument Lists ........................................................................................ 102 
3.8 More About Application Contexts .................................................................................... 102 

4 An Example Application .......................................................................................... 105 

4.1 xbitmapl: Bitmap Editor Using a BitmapEdit Widget ................................................... 106 
4.1.1 Widget Public Functions ............................................................................................. 109 
4.1.2 Application-defaults File ............................................................................................ 109 



4.2 xbitmap2: Adding Scrollbars to Handle Large Bitmaps ................................................ 109 
4.2.1 Overriding Translations .............................................................................................. 114 
4.2.2 Action Arguments in the Translation Table ............................................................... 114 
4.2.3 The resize_thumbs Action .......................................................................................... 115 
4.2.4 Scrollbar Callbacks ..................................................................................................... 116 
4.3 xbitmap3: Adding Graphics to Display the Bitmap ........................................................ 118 
4.3.1 Graphics from the Application ................................................................................... 121 
4.3.2 Writing a Bitmap File .................................................................................................. 124 
4.4 xbitmap4: Bitmap Editor Without a BitmapEdit Widget ............................................... 125 

5 Inside a Widget ............................................................................................................. 137 

5.1 Widget Source File Organization ...................................................................................... 138 
5.2 The Private Header File--BitmapEdiP.h ......................................................................... 138 
5.2.1 Parts and Records ........................................................................................................ 139 
5.2.2 Class Part and Class Record ....................................................................................... 140 
5.2.3 Instance Part and Instance Record ............................................................................. 141 
5.3 The Widget Implementation File--BitmapEdit.c ........................................................... 143 
5.3.1 Obligatory Include Files ............................................................................................. 145 
5.3.2 Defining the Resource List ......................................................................................... 145 
5.3.3 The Translation Table and Actions Table .................................................................. 148 
5.3.4 Declaring Methods ...................................................................................................... 150 
5.3.5 Initializing the Class Record ...................................................................................... 151 
5.3.5.1 The Core Class Part ................................................................................................ 151 
5.3.5.2 Initializing the Core Methods ................................................................................ 153 
5.3.6 Description of Core Methods ..................................................................................... 155 
5.3.7 Packaging the Class Record for Application Use ..................................................... 157 
5.3.8 A Sample Method ........................................................................................................ 157 
5.4 The Public Header File--BitmapEdit.h ........................................................................... 160 
5.5 The Process of Widget Writing ......................................................................................... 163 
5.6 Summary of Conventions ................................................................................................... 164 

6 Basic Widget Methods ............................................................................................... 169 

6.1 The X Graphics Model Inside Widgets ............................................................................. 170 
6.2 The initialize Method ......................................................................................................... 170 
6.2.1 Creating GCs ............................................................................................................... 172 
6.3 The expose Method ............................................................................................................ 175 
6.4 The set_values Method ...................................................................................................... 178 
6.5 The resize Method .............................................................................................................. 181 
6.6 The query_geometry Method ............................................................................................ 184 
6.7 The destroy Method ............................................................................................................ 187 
6.8 Actions in the Widget Framework .................................................................................... 188 



7 Events, Translations, and Accelerators .............................................................. 193 

7.1 Translation Table Syntax .................................................................................................... 194 
7.1.1 The Directive ............................................................................................................... 195 
7.1.2 Selecting the Events to Translate ............................................................................... 195 
7.1.3 Details in Keyboard Events ........................................................................................ 198 
7.1.4 Details in Other Event Types ...................................................................................... 199 
7.1.5 Modifiers ...................................................................................................................... 201 
7.1.5.1 Physical Keys Used as Modifiers .......................................................................... 202 
7.1.5.2 Default Interpretation of the Modifier List ........................................................... 204 
7.1.5.3 Prohibiting a Modifier ............................................................................................ 204 
7.1.5.4 Requiring an Exact Match ..................................................................................... 205 
7.1.5.5 Paying Attention to the Case of Keysyms ............................................................ 205 
7.1.6 Event Sequences .......................................................................................................... 206 
7.1.6.1 Special Considerations Involving Motion Events ............................................... 207 
7.1.6.2 Modifiers and Event Sequences ............................................................................ 207 
7.1.6.3 Using Modifiers to Specify Button Event Sequences .......................................... 208 
7.1.6.4 Key Event Sequences ............................................................................................. 208 
7.1.7 Interactions Between Translations ............................................................................. 208 
7.1.7.1 Translations in Multiple Resource Files ............................................................... 209 
7.1.7.2 Order of Translations .............................................................................................. 209 
7.1.7.3 Event Sequences Sharing Initial Events ............................................................... 210 
7.1.7.4 Event Sequences Sharing Noninitial Events ........................................................ 210 
7.2 Accelerators ........................................................................................................................ 211 
7.2.1 Event Propagation ....................................................................................................... 213 
7.2.2 Installing Accelerators in Multiple Widgets ............................................................. 215 
7.2.3 Defining the Accelerator Table in the Code .............................................................. 216 
7.2.4 The display_accelerators Method .............................................................................. 216 

8 More Input Techniques ............................................................................................. 221 

8.1 Event Handlers .................................................................................................................... 222 
8.1.1 Adding Event Handlers ............................................................................................... 224 
8.1.2 Adding Nonmaskable Event Handlers ....................................................................... 225 
8.1.3 Removing Event Handlers .......................................................................................... 226 
8.1.4 Adding Raw Event Handlers ...................................................................................... 227 
8.2 Writing Routines That Use Specific Event Data .............................................................. 227 
8.2.1 Event Types and Structure Names .............................................................................. 229 
8.3 File, Pipe, and Socket Input ............................................................................................... 231 
8.3.1 Getting File Input ........................................................................................................ 231 
8.3.2 Getting Pipe Input ....................................................................................................... 233 
8.4 Timeouts .............................................................................................................................. 234 
8.4.1 Visibility Interest ......................................................................................................... 237 
8.5 Work Procedures ................................................................................................................. 239 
8.6 Low-level Management of the Event Queue .................................................................... 241 
8.6.1 XtPending and XtPeekEvent ...................................................................................... 241 

viii 



8.6.2 Event Filters ................................................................................................................. 242 
8.6.3 Input Sensitivity .......................................................................................................... 243 

9 Resource Management and Type Conversion ................................................ 247 

9.1 Review of Resource Fundamentals ................................................................................... 248 
9.2 How the Resource Database Works .................................................................................. 251 
9.2.1 Form of Resource Specifications ................................................................................ 252 
9.2.2 Merging of Resource Files .......................................................................................... 253 
9.2.3 The Language String ................................................................................................... 255 
9.2.4 Fallback Resources ...................................................................................................... 257 
9.2.5 Resource Matching Algorithm ................................................................................... 258 
9.2.6 Resource Precedence Rules ........................................................................................ 260 
9.3 Type Conversion ................................................................................................................. 263 
9.3.1 Conversions from XtRString ...................................................................................... 263 
9.3.2 Other Built-in Type Conversions ............................................................................... 266 
9.3.3 Special Resource Defaults That Do Not Use Conversion ........................................ 267 
9.3.4 Registering Type Converters ...................................................................................... 269 
9.3.4.1 Passing Arguments to a Type Converter ............................................................... 272 
9.3.5 Explicitly Invoking a Converter ................................................................................. 274 
9.3.6 Writing a Type Converter ........................................................................................... 275 
9.3.6.1 Defining the Default Value .................................................................................... 277 
9.4 Subparts and Subresources ................................................................................................ 278 
9.4.1 The Hook Methods ...................................................................................................... 279 
9.4.2 Managing Subresources .............................................................................................. 279 

10 Interclient Communications ................................................................................ 283 

10.1 Window Manager Interactions ........................................................................................ 284 
10.1.1 Shell Subclasses ........................................................................................................ 284 
10.1.2 Setting Shell Resources ............................................................................................ 285 
10.1.3 Screen Space .............................................................................................................. 287 
10.1.4 Input Model ............................................................................................................... 288 
10.1.5 Colormals .................................................................................................................. 290 
10.1.6 Icons ........................................................................................................................... 292 
10.1.7 Window Manager Decorations ................................................................................. 293 
10.2 Selections: Widget-To-Widget Communication ........................................................... 294 
10.2.1 How Atomic Selection Works .................................................................................. 295 
10.2.2 Highlighting the Selected Data (Owner) ................................................................. 298 
10.2.3 Making the Selection with XtOwnSelection (Owner) ........................................... 303 
10.2.4 Requesting the Selection (Requestor) ..................................................................... 304 
10.2.4.1 Possible Target Type Atoms ................................................................................ 305 
10.2.4.2 The Paste Action from BitmapEdit ..................................................................... 307 
10.2.5 Converting the Selection (Owner) ........................................................................... 307 
10.2.6 Finally Pasting the Selection (Requestor) ............................................................... 310 
10.2.7 If the Selection is Lost (Owner) ............................................................................... 312 



10.2.8 When the Selection Transfer is Complete (Owner) ................................................ 312 
10.2.9 ICCCM Compliance ................................................................................................... 312 
10.2.9.1 Xmu Atom Caching ............................................................................................. 314 
10.2.9.2 Converting the Standard Selections .................................................................... 315 
10.2.9.3 The Clipboard Selection ...................................................................................... 316 
10.2.10 How Incremental Selection Works ........................................................................ 317 
10.2.11 Miscellaneous Selection Routines ......................................................................... 318 

11 Geometry Management ......................................................................................... 321 

11.1 How Composite Management Works ............................................................................. 322 
11.1.1 Initial Geometry Negotiation ................................................................................... 324 
11.1.2 Basic Core Methods in Composite Widgets ............................................................ 328 
11.1.3 Laying Out Child Widgets ........................................................................................ 330 
11.1.4 The change_managed Method ................................................................................. 332 
11.1.5 XtQueryGeometry and the query_geometry Method ............................................. 332 
11.1.6 XtMakeGeometryRequest and the geometry_manager Method ........................... 333 
11.1.7 The insert_child and delete_child Methods ............................................................ 335 
11.2 How Constraint Management Works .............................................................................. 336 
11.3 Writing a Consa'aint Widget ............................................................................................ 336 
11.3.1 The Core Resource List ............................................................................................ 336 
11.3.2 The Constraint Resource List ................................................................................... 337 
11.3.3 Class Structure Initialization .................................................................................... 339 
11.3.4 The Constraint initialize Method ............................................................................. 341 
11.3.5 The class_part_init Method ...................................................................................... 342 
11.3.6 The geometry_manager Method .............................................................................. 343 
11.3.7 The resize Method ..................................................................................................... 347 
11.3.8 The Core and Conslraint set_values Methods ......................................................... 349 
11.3.9 The change_managed Method ................................................................................. 349 
11.3.10 The query_geometry Method ................................................................................. 350 
11.3.11 Delaying Geometry Recalculation ......................................................................... 351 
11.4 Compound Widgets .......................................................................................................... 351 
11.5 Stacking Order .................................................................................................................. 352 

12 Menus, Gadgets, and Cascaded Pop Ups ........................................................ 357 

12.1 Menu Styles and Implementation .................................................................................... 359 
12.1.1 How Menus are Popped Up ...................................................................................... 360 
12.1.2 Menu Panes ................................................................................................................ 361 
12.2 Several Ways to Create and Use Menus ......................................................................... 363 
12.2.1 A Spring-Loaded Menu: Pointer Grabbing ............................................................ 363 
12.2.2 A Drop-Down Menu ................................................................................................. 371 
12.2.3 Cascaded Menus ........................................................................................................ 374 
12.2.4 Using the R4 SimpleMenu Widget .......................................................................... 379 
12.2.5 Delayed Popup Creation ........................................................................................... 383 
12.3 About Dialog Boxes ......................................................................................................... 384 



12.4 Gadgets .............................................................................................................................. 385 
12.4.1 Inside a Gadget .......................................................................................................... 388 
12.4.2 Private Header File .................................................................................................... 389 
12.4.3 The Gadget Source File ............................................................................................ 390 
12.4.4 The Public Header File ............................................................................................. 391 
12.4.5 The Gadget Parent ..................................................................................................... 391 

13 Miscellaneous Toolkit Programming Techniques ....................................... 399 

13.1 Errors and Warnings ......................................................................................................... 399 
13.2 Objects ............................................................................................................................... 402 
13.3 Macros For Getting Information ..................................................................................... 403 
13.4 The Keyboard Focus and accept_focus Method ............................................................ 404 
13.5 Keyboard Interpretation ................................................................................................... 406 
13.6 Memory Allocation .......................................................................................................... 408 
13.7 Action Hooks and Calling Actions Directly .................................................................. 408 
13.8 Xt Grabbing Functions ..................................................................................................... 409 
13.9 File Finding and Internationalization ............................................................................. 409 
13.10 Application Contexts ..................................................................................................... 410 
13.10.1 Multiple Application Contexts ............................................................................... 411 
13.10.2 Rewriting XtAppMainLoop for Multiple Application Contexts ......................... 412 
13.10.3 Functions Used with Multiple Application Contexts ........................................... 412 
13.11 Multiple Top-level Shells .............................................................................................. 413 
13.12 Connecting to Multiple Servers .................................................................................... 413 
13.13 Class Extension Structures ............................................................................................ 414 

A OPEN LOOK and Motif ........................................................................................... 419 

A. 1 The AT&T OPEN I_X3OK Widgets ..................................................................................... 423 
A.1.1 Application Controls .................................................................................................. 424 
A.I.I.1 Command Buttons ................................................................................................. 424 
A. 1.1.2 Exclusive and Nonexclusive Settings .................................................................. 426 
A.1.1.3 Analog.Controls ..................................................................................................... 428 
A.1.2 Composite Widgets .................................................................................................... 428 
A. 1.2.1 Menus and Control Areas ..................................................................................... 428 
A. 1.2.2 General Purpose Composite Widgets .................................................................. 429 
A. 1.2.3 Scrollbars and Scrollable Windows ..................................................................... 429 
A. 1.3 Pop Ups ....................................................................................................................... 431 
A. 1.4 Text Widgets ............................................................................................................... 433 
A. 1.5 Drawing Areas ............................................................................................................ 433 
A.2 The OSF/Motif Widgets .................................................................................................... 433 
A.2.1 Application Controls .................................................................................................. 436 
A.2.1.1 Command Buttons ................................................................................................. 436 
A.2.1.2 Analog Controls ..................................................................................................... 436 
A.2.2 Composite Widgets .................................................................................................... 437 
A.2.2.1 Menus and Control Areas ..................................................................................... 437 

xi 



A.2.2.2 General Purpose Composite Widgets .................................................................. 440 
A.2.2.3 Scrollable Windows .............................................................................................. 441 
A.2.3 Pop Ups ....................................................................................................................... 442 
A.2.4 Text Widgets ............................................................................................................... 443 
A.2.5 Drawing Areas ............................................................................................................ 443 

B Specifying Fonts and Colors .................................................................................. 447 

B.1 Color Specification ............................................................................................................ 447 
B.I.1 Color Names ................................................................................................................ 447 
B. 1.2 Hexadecimal Color Specification .............................................................................. 448 
B. 1.2.1 The RGB Color Model .......................................................................................... 449 
B.1.2.2 How Many Colors are Available? ........................................................................ 450 
B.2 Font Specification .............................................................................................................. 452 
B.2.1 Font Naming Conventions ......................................................................................... 453 
B.2.2 Font Name Wildcarding ............................................................................................. 454 
B.2.3 Font Name Aliasing .................................................................................................... 456 
B.2.4 Making the Server Aware of Aliases ........................................................................ 457 
B.2.5 The fonts.dir Files ....................................................................................................... 457 
B.3 Window Geometry ............................................................................................................. 458 

C Naming Conventions ................................................................................................. 463 

D Release Notes ................................................................................................................ 467 

D. 1 Summary of New Functions and Procedure Types ......................................................... 467 
D.2 Application Writing ........................................................................................................... 470 
D.2.1 New Function for Initializing an Application .......................................................... 470 
D.2.2 Varargs Interfaces ....................................................................................................... 470 
D.2.2.1 Special Types for Varargs List Members ............................................................. 471 
D.2.3 Loading the Resource Database ................................................................................ 471 
D.2.3.1 The Language String ............................................................................................. 471 
D.2.3.2 New Built-In Application Resources ................................................................... 472 
D.2.3.3 Fallback Resources ................................................................................................ 472 
D.2.4 Parsing the Command Line ........................................................................................ 472 
D.3 Changes Affecting Both Application and Widget Writing ............................................ 473 
D.3.1 Actions ........................................................................................................................ 473 
D.3.1.1 Directly Invoking Actions .................................................................................... 473 
D.3.1.2 Action Hook Registration ..................................................................................... 473 
D.3.1.3 Obtaining Event Information in an Action Procedure ........................................ 473 
D.3.1.4 Registering Button and Key Grabs For Actions ................................................. 474 
D.3.1.5 Action Functions and Unrealized Widgets .......................................................... 474 
D.3.2 Reserved Names for Resources and Actions ............................................................ 474 
D.3.3 Resource String Identifier Convention ..................................................................... 474 



D.3.4 Resource File Format ................................................................................................. 474 
D.3.5 Modifier Names .......................................................................................................... 475 
D.3.6 Determining Specification Revision Level ............................................................... 475 
D.3.7 Implementation-specific Datatype Definitions ......................................................... 475 
D.3.8 Event Handlers ............................................................................................................ 476 
D.3.9 Error and Warning Handlers ...................................................................................... 476 
D.4 Changes Affecting Widget Writing .................................................................................. 476 
D.4.1 New Name for Core Class ......................................................................................... 476 
D.4.2 File Content Changes ................................................................................................. 477 
D.4.2.1 Changes to Private .h Files ................................................................................... 477 
D.4.2.2 Changes to .c Files ................................................................................................. 477 
D.4.3 Class Extension Structures ......................................................................................... 477 
D.4.3.1 Composite Class Extension Structure .................................................................. 478 
D.4.3.2 Constraint Class Extension Structure .................................................................. 479 
D.4.3.3 New Constraint get_values_hook method ........................................................... 479 
D.4.3.4 Shell Class Extension Structure ........................................................................... 479 
D.4.4 New XtNvisual Resource ........................................................................................... 480 
D.4.5 Methods ....................................................................................................................... 480 
D.4.6 Mapping Order of Realized Child Widgets .............................................................. 481 
D.4.7 Callback Lists ............................................................................................................. 481 
D.4.7.1 XtNunrealizeCallback ........................................................................................... 481 
D.4.7.2 Internal Format of Callback Lists ........................................................................ 481 
D.4.7.3 New Routine to Call Callback List ...................................................................... 482 
D.4.8 Resource Lists ............................................................................................................. 482 
D.4.8.1 Base Offsets in Resource List ............................................................................... 482 
D.4.8.2 XtProcedureArg ..................................................................................................... 482 
D.4.8.3 Default Resource Values ....................................................................................... 482 
D.4.8.4 Getting a Constraint Resource List ...................................................................... 482 
D.4.9 Converters ................................................................................................................... 483 
D.4.9.1 New Xt Resource Representations ....................................................................... 483 
D.4.9.2 New Xt Resource Converters ............................................................................... 483 
D.4.9.3 New Fn for Issuing Conversion Warnings ........................................................... 484 
D.4.9.4 New Resource Converters Interface .................................................................... 484 
D.4.10 Keyboard Handling .................................................................................................. 486 
D.4.10.1 KeyC.ode-to-KeySym Conversions .................................................................... 486 
D.4.10.2 KeySym-o-KeyCode Conversions .................................................................... 486 
D.4.11 Selections .................................................................................................................. 486 
D.4.12 Objects ....................................................................................................................... 486 
D.4.12.1 The Gadget Parent ............................................................................................... 487 
D.4.12.2 Xt Functions that take any Object ...................................................................... 488 
D.4.12.3 Xt Functions that take any RectObj ................................................................... 489 
D.4.12.4 Xt Functions that take any Core ......................................................................... 489 
D.4.12.5 Xt Functions that take any Composite ............................................................... 490 
D.4.12.6 Xt Functions that take any Shell or a Subclass ................................................. 490 
D.4.12.7 Macros for Getting Object Information ............................................................. 490 
D.4.13 Miscellaneous ........................................................................................................... 491 
D.4.13.1 XtNameToWidget ............................................................................................... 491 
D.4.13.2 New Exposure Compression Controls ............................................................... 491 

xiii 



D.4.13.3 Requesting Key and Button Grabs ..................................................................... 492 
D.4.13.4 New Macros for Widget Superclass Determination ......................................... 493 
D.4.13.5 Macros and Procedure Equivalents .................................................................... 493 
D.4.13.6 Finding File Names ............................................................................................. 493 
D.4.13.7 Improved Multi-Display Support in Xmu ......................................................... 493 

E The xbitmap Application ........................................................................................ 497 

E. 1 The BitmapEdit Widget ..................................................................................................... 497 
E.2 The BitmapEdiP.h Private Header File ............................................................................ 510 
E.3 The BitmapEdit.h Public Header File ............................................................................... 511 
E.4 xbitmap8 ............................................................................................................................. 513 

F Sources of Additional Information ..................................................................... 521 

F.1 Getting the X Software ...................................................................................................... 521 
F. 1.1 Bug Fixes ..................................................................................................................... 522 
F. 1.1.1 Notes ....................................................................................................................... 524 
F. 1.1.2 Fairness ................................................................................................................... 524 
F.2 Nemews ............................................................................................................................... 525 
F.3 Training and Consulting ..................................................................................................... 525 
F.3.1 Phone Support ............................................................................................................. 526 
F.4 The X Consortium .............................................................................................................. 526 
F.5 Finding Out for Yourself .................................................................................................... 527 

Glossary ................................................................................................................................. 531 

Master Index ....................................................................................................................... 553 

xiv 



11-2 
11-3 
11-4 
11-5 
12-1 
12-2 
12-3 
12-4 
12-5 
12-6 
12-7 
13-1 
A-1 
A-2 
A-3 
A-4 
A-5 
A-6 
A-7 
A-8- 
A-9 
A-10 
A-11 
A-12 
A-13 
A-14 
A-15 
A-16 
A-17 
A-18 
A-19 
A-20 
B-1 
B-2 

Initial geometry negotiation, assuming sufficient shell space ..................................... 325 
Initial geometry negotiation, if resizing is necessary ................................................... 326 
A ScrollBox widget at two different sizes .................................................................... 326 
Geometry negotiation by the set_values_almost method ............................................ 334 
Command widgets in a button box, and the same commands as a menu .................... 358 
Menus from the OPEN LOOK and Motif widget sets .................................................... 362 
xmenul: application with spring-loaded pop-up menu ............................................... 366 
xmenu2: a drop-down menu .......................................................................................... 371 
xmenu5: cascaded spring-loaded menus ...................................................................... 375 
xmenu7: a menu using the Athena SimpleMenu widget ............................................ 380 
Class hierarchy derivation of Core ................................................................................ 387 
Using XtCallAcceptFocus to set the keyboard focus to a child .................................. 406 
An OPEN LOOK application ............................................................................................ 423 
Class inheritance hierarchy of the AT&T OPEN LOOK widgets .................................. 425 
An OPEN LOOK ControlArea with OblongButton and ButtonStack widgets ............. 425 
OPEN LOOK RectButtons controlled by Exclusives and Nonexclusives widgets ....... 427 
An OPEN LOOK CheckBox widget ................................................................................. 428 
An OPEN LOOK Slider widget ........................................................................................ 428 
An OPEN LOOK Scrollbar ................................................................................................ 429 
An OPEN LOOK ScrollingList widget ............................................................................. 430 
An OPEN LOOK Notice .................................................................................................... 431 
An OPEN LOOK PopupWindow .................................................................................... 432 
An OPEN LOOK Help window ...................................................................................... 432 
Look and feel of a Motif application ............................................................................ 434 
Class inheritance hierarchy of the Motif widget set .................................................... 435 
Motif DrawnButton and PushButton widgets .............................................................. 436 
A Motif RowColumn widget configured as a Menu Bar ............................................ 438 
A Motif RowColumn widget configured with four Radio Boxes ............................... 438 
A Motif RowColumn widget configured as a drop-down menu ................................. 439 
A Motif Form widget and children ............................................................................... 440 
A Motif ScrollBar .......................................................................................................... 441 
A Motif SelectionBox .................................................................................................... 442 
Multiple planes used to index a colormap ...................................................................... 451 
A font name ....................................................................................................................... 453 



Examples 

Page 
2-2 XHello: the application-defaults file ................................................................................ 39 
2-3 xgoodbye.c: complete code ............................................................................................... 43 
2-4 XGoodbye: the application-defaults file .......................................................................... 44 
2-5 xfarewell.c: complete code ................................................................................................ 46 
2-6 An XtActionProc with widget and event arguments ........................................................ 48 
2-7 XFarewell: the application-defaults file ........................................................................... 50 
2-8 Code Fragment: specifying translations in the program ................................................. 52 

2-9 Using XtVaSetValues to set a widget resource ................................................................. 54 
2-10 Using XtSetValues to set a widget resource ................................................................... 54 
2-11 Code fragment to set multiple resources of a widget ..................................................... 55 
2-12 Code fragment to get a widget resource using XtVaGetValues .................................... 56 
2-13 Code fragment to get a widget resource using XtGetValues ......................................... 57 
2-14 Alternate resource settings for xfarewell ........................................................................ 60 
3-1 xbox 1.c: complete code ..................................................................................................... 66 
3-2 XBoxl: application-defaults file ....................................................................................... 68 
3-3 XBox2: application-defaults file ....................................................................................... 74 
3-4 xbox3: application-defaults file ........................................................................................ 75 
3-5 Creating a pop-up dialog box ............................................................................................. 76 
3-6 Passing a single value to a callback function .................................................................... 82 
3-7 Passing a pointer to a structure to a callback function ..................................................... 82 
3-8 ANSI non-conformant callback function definition ......................................................... 83 
3-9 Initializing a callback list ................................................................................................... 85 
3-10 xbitmap: getting application resources ........................................................................... 86 
3-11 The resource list for xbitmap ........................................................................................... 87 
3-12 Calling XtGetApplicationResources and checking values ............................................ 90 
3-13 xbitmap: specifying command-line options ................................................................... 93 
3-14 The R4 varargs interface to creating a widget ................................................................ 97 
3-15 An argument list ................................................................................................................ 99 
3-16 Using an argument list in widget creation ....................................................................... 99 
3-17 Setting the argument list with XtSetArg ....................................................................... 1130 
3-18 Incorrectly sttting the argument list with XtSetArg .................................................... 101 
4-1 xbitmapl: complete code ................................................................................................. 107 
4-2 XBitmapl: application-defaults file ............................................................................... 109 
4-3 xbitmap2: adding scrollbars ............................................................................................ 112 
4-4 xbitmap2: resize_thumbsroutine .................................................................................... 115 
4-5 xbitmap2: scrolling callback functions .......................................................................... 116 
4-6 xbitmap3: implementing small pixmaps by drawing into Core widgets ..................... 120 
4-7 xbitmap3: the cell_toggled routine ................................................................................. 122 
4-8 xbitmap3: the Redraw_small_picture routine ................................................................ 123 
4-9 xbitmap3: writing a bitmap file ....................................................................................... 124 
4-10 xbitmap4: implementing the bitmap editor from the application ............................... 126 
5-1 BitmapEdiP.h: the class part and class record ............................................................... 140 
5-2 BitmapEdiP.h: the instance part and instance record .................................................... 141 



5-3 BitmapEdiP.h: declaring the external class record ........................................................ 143 
5-4 BitmapEdit.c: include files .............................................................................................. 145 
5-5 BitmapEdit's resource list ................................................................................................ 145 
5-6 Setting the resource list into the class structure .............................................................. 148 
5-7 The default translation table and the actions table ......................................................... 149 
5-8 Translations in the Core class record ............................................................................... 149 
5-9 BitmapEdit.c: function type declarations ....................................................................... 150 
5-10 BitmapEdit.c: initialization of Core class record ........................................................ 151 
5-11 BitmapEdit.c: declaring the class record pointer ......................................................... 157 
5-12 BitmapEdit.c: inheriting a self-contained method ....................................................... 158 
5-13 Inheriting by invoking the superclass method from a widget method ........................ 159 
5-14 BitmapEdit.h: incidental declarations .......................................................................... 161 
6-1 The initialize method ........................................................................................................ 171 
6-2 Creating GCs from the initialize method ........................................................................ 173 
6-3 The expose method ........................................................................................................... 175 
6-4 The set_values method ..................................................................................................... 178 
6-5 BitmapEdit: the resize method ........................................................................................ 182 
6-6 The XtWidgetGeometry structure ................................................................................... 184 
6-7 BitmapEdit: the query_geometry method ...................................................................... 186 
6-8 The destroy method ........................................................................................................... 187 
6-9 BitmapEdit: action routines ............................................................................................. 188 
7-1 Installing accelerators in an application .......................................................................... 212 
7-2 Specifying the XtNaccelerators resource from the application-defaults file ............... 212 
7-3 Conflicting translations and accelerators ........................................................................ 214 
7-4 Installing accelerators from both command widgets ...................................................... 215 
7-5 Accelerators resource settings for two widgets .............................................................. 215 
8-1 Registering an event handler, and the handler function itself ....................................... 224 
8-2 Adding a nonmaskable event handler .............................................................................. 226 
8-3 Casting the event structure by declaring action routine arguments .............................. 228 
8-4 Handling multiple event types in an action routine ........................................................ 228 
8-5 Getting file input with XtAppAddlnput .......................................................................... 232 
8-6 Reading stdin from an Xt application .............................................................................. 234 
8-7 xtetris: registering a timeout and the timeout function ................................................. 235 
8-8 xtetris: calling XtRemoveTimeOut ................................................................................ 237 
8-9 Registering an Xt Work Procedure .................................................................................. 239 
8-10 A work procedure to create a pop-up widget ................................................................ 240 
8-11 Skeleton of a custom main loop ..................................................................................... 241 
9-1 Two resources defined by the Athena Label widget ....................................................... 248 
9-2 An app-defaults file for the Spanish language ................................................................ 257 
9-3 Setting fallback resources in XtApplnitialize ................................................................. 257 
9-4 A sample merged resource database ................................................................................ 258 
9-5 Sample resource database with eliminated entries and components ............................. 260 
9-6 Resource database after final elimination of entries and components .......................... 260 
9-7 Resource database finalists in original form ................................................................... 261 
9-8 A resource definition converting an int to a pixmap ...................................................... 267 
9-9 A resource definition using XtRImmediate ..................................................................... 267 
9-10 A resource definition using XtRCallProc ...................................................................... 268 
9-11 An example of an XtResourceDefaultProc ................................................................... 268 

ooo 
XVIII 



9-12 
9-13 
9-14 
9-15 
9-16 
9-17 
10-1 
10-2 
10-3 
10-4 
10-5 
10-6 
10-7 
10-8 
10-9 
10-10 
11-1 
11-2 
11-3 
11-4 
11-5 
11-6 
11-7 
11-8 
11-9 
11-10 
11-11 
11-12 
11-13 
11-14 
11-15 
11-16 
11-17 
12-1 
12-2 
12-3 
12-4 
12-5 
12-6 
12-7 
12-8 

Registering a type converter .......................................................................................... 270 
Adding a converter with arguments ............................................................................... 272 
Manually invoking a type converter .............................................................................. 274 
An R4 XtRSIring to XtREdgeType type converter ...................................................... 276 
Testing for a special-case default value ........................................................................ 278 
Simplified get_values_hook method of the AsciiSrc subpart of the Text widget ...... 279 
Setting the XtNinput resource of a Shell widget .......................................................... 290 
Creating an icon pixmap, and setting XtNiconPixmap ................................................ 292 
BitmapEdit: actions that highlight selection ................................................................ 299 
BitmapEdit: getting the atom for a widget-specific target type ................................. 306 
BitmapEdit: action to paste a selection ........................................................................ 307 
BitmapEdit: converting the selection value ................................................................. 308 
BitmapEdit: pasting selection in requestor_callback function ................................... 310 
BitmapEdit: the lose_ownership_proc ......................................................................... 312 
BitmapEdit: initializing Xmu's atom caching mechanism in the initialize method. 314 
BitmapEdit: converting standard targets in the convert_proc .................................. 315 
ScrollBox: the set_values method ................................................................................ 328 
ScrollBox: the resize method ........................................................................................ 329 
ScrollBox: the query_geometry method ...................................................................... 329 
ScrollBox: private routine to lay out child widgets .................................................... 330 
Form: the Core resource list .......................................................................................... 336 
Form: constraint resource list ........................................................................................ 337 
Form: constraint data structure ..................................................................................... 338 
Form: class structure initialization ............................................................................... 339 
Form: the Constraint initialize method ........................................................................ 341 
Form: the class_part_init method ............................................................................... 342 
Form: the geometry_manager method ....................................................................... 343 
Form: private functions: RefigureLocations and the layout method ...................... 344 
Form: the LayoutChild private function .................................................................... 346 
Form: the resize method .............................................................................................. 347 
Form: the change_managed method ........................................................................... 350 
Form: the query_geometry method ............................................................................ 350 
Form: the public function for delaying calls to change_managed ........................... 351 
xmenul: complete code ................................................................................................. 366 
XMenu 1: the application-defaults file .......................................................................... 369 
xmenu2: code to-place drop-down menu ..................................................................... 372 
XMenu2: translation portion of the application-defaults file ..................................... 374 
xmenu5: actions that place, pop up, and pop down main menus and submenus ....... 376 
XMenu5: translation portion of application-defaults file ........................................... 378 
xmenu7: using the SimpleMenu widget and its children ............................................ 380 
XMenu7: application-defaults file ................................................................................ 382 

12-9 Sme gadget: class part and complete class structure declaration ............................... 389 
12-10 Sme gadget: instance part and complete instance structure declaration ................. 390 
12-11 SimpleMenu: expose method calling gadget children's expose methods ............... 392 
12-12 SimpleMenu: resize method ........................................................................................ 393 
12-13 SimpleMenu: the Notify action routine ..................................................................... 394 
12-14 SimpleMenu.c: Setting accepts__objects in the Composite extension structure ....... 394 
13-1 How to invoke XtAppErrorMsg (from AsciiSrc.c) ...................................................... 401 



13-2 Common fields in a class extension record ................................................................... 414 
B-1 Sample fonts.alias file ...................................................................................................... 456 
B-2 fonts.dir file in/usr/lib/X11/fonts/100dpi ....................................................................... 458 
E-1 BitmapEdit: complete widget code ................................................................................. 497 
E-2 BitmapEdiP.h: complete private header file .................................................................. 510 
E-3 BitmapEdit.h: complete public header file .................................................................... 511 
E-4 xbitmap8: complete application code ............................................................................ 513 



Tables 

2-1 
2-2 
2-3 
3-1 
3-2 
3-3 
5-1 
5-2 
5-3 
6-1 
6-2 
7-1 
7-2 
7-3 
7-4 
7-5 
7-6 
8-1 
8-2 
8-3 
9-1 
9-2 
9-3 
9-4 

Page 
Functions that Set Resources: arglist and varargs Counterparts ..................................... 53 
Core Resources .................................................................................................................... 57 
Label Resources .................................................................................................................. 60 
Resource Type Strings ........................................................................................................ 89 
Standard Command-line Parameters ................................................................................. 92 
XrmOptionKind: Command-line Option Style Constants .............................................. 95 
Resource List Constant Conventions ............................................................................... 147 
Inheritance Style of Various Methods ............................................................................. 155 
Summary of Xt Structure Name Conventions ................................................................ 164 
XtWidgetGeometry request_mode Symbols ................................................................... 184 
XtWidgetGeometry stack_mode Symbols ...................................................................... 185 
Event Type Abbreviations in Translation Tables ............................................................ 196 
Notify Mode Values for Enter, Leave, and Focus Events .............................................. 200 
Atom Details for Various Events ..................................................................................... 200 
Event Structure Fields Used as Translation Table Hints ................................................ 201 
Modifiers Used in Translation Tables .............................................................................. 202 
Modifier Symbols .............................................................................................................. 204 
Event Masks and Event Types .......................................................................................... 223 
Event Types and Event Structures ................................................................................... 230 
Other Input Source Masks ................................................................................................ 231 
Resource Type Strings ...................................................................................................... 250 
Built-in Type Converters from XtRString ....................................................................... 265 
Other Built-in Converters ................................................................................................. 266 
Xmu Converters ................................................................................................................ 269 

10-1 Shell Resources ............................................................................................................... 285 
10-2 Target Types Suggested in ICCCM ................................................................................. 313 
13-1 Xt Error and Warning Message Utilities ....................................................................... 401 
13-2 Xt Routines That Use Default and Explicit Application Contexts ............................. 410 
A-1 Comparison of Athena, OPEN LOOK, and Motif Widgets ............................................ 420 
B-1 Geometry Spe.c. ification: x and y Offsets ....................................................................... 459 
D-1 ArgList Functions and varargs Counterparts ................................................................. 470 
D-2 New Naming for Core Class Symbols and Variables .................................................... 476 
D-3 New Representation Types .............................................................................................. 483 
D-4 Flags for compress_exposure field of Core Class Structure ......................................... 492 
D-5 Optional OR Flags for compress_exposure Field of Core Class Structure .................. 491 

xxi 



Preface 

By convention, a preface introduces the book itself, while the introduction 
starts in on the subject matter. You should read through the preface to get 
an idea of how the book is organized, the conventions it follows, and so on. 

In This Chapter: 

Summary of Contents ........................................................................ xxv 
Assumptions ...................................................................................... xxvi 
Related Documents .......................................................................... xxvii 
How to Use This Manual ................................................................... xxvii 
Font Conventions Used in This Manual .............................................. xxx 
Requests for Comments .................................................................... xxxi 
Bulk Sales Information ....................................................................... xxxi 
Obtaining the X Window System Software ......................................... xxxi 
Example Programs ............................................................................ xxxi 
Acknowledgments ............................................................................. xxxii 



Preface 

The Xt Intrinsics library consists of routines for building and using widgets. A widget is a 
pre-built user-interface component. Applications are written using the Xt Intrinsics library, 
together with a widget set library, to simplify the development of X Window System applica- 
tions. This combination of Xt and any widget set is collectively called the X Toolkit. This 
book describes how to build applications using the Xt Intrinsics and any widget set. It pro- 
vides a complete tutorial with programming examples, on how to program with existing widg- 
ets and how to write your own. 
There are several widget sets provided by system vendors to implement their particular user- 
interface styles. The two most widely used are OSF's Motif, and AT&T's OPEN LOOK 
widget set. The X distribution from MIT (where X itself is developed) comes with the Xaw 
widget set, which provides a small number of widgets that can be used to write simple appli- 
cation programs. Xaw was developed by MIT's Project Athena, and the acronym Xaw stands 
for "Athena Widgets." Xaw was designed as a simple demonstration and test of the Intrin- 
sics--not as a complete set of widgets for writing commercial applications. 
This book uses the Athena widgets to demonstrate how to use existing widgets, but what it 
says is equally applicable to and provides a good introduction to programming with any other 
widget set based on Xt. It is based on Release 4 of the Intrinsics and the Athena widgets. 
Xt is written using Xlib, the lowest level C-language interface to the X Window System. 
Both the Xt Intrinsics and Xlib are required by the X standard (established by the X Consor- 
tium) on any system that allows programming of X applications in C. 

Summary of Contents 

The discussion of the X Toolkit is divided into two volumes, Volumes Four and Five of the X 
Window System Series available from O'Reilly & Associates, Inc. 
This is Volume Four, X Toolkit lntrinsics Programming Manual. It provides an explanation 
of the X Toolkit, including tutorial material and numerous programming examples. Arranged 
by task or topic, each chapter brings together a group of Xt functions, describes the concep- 
tual foundation on which they are based, and illustrates how they are most often used in writ- 
ing applications. This volume is structured to be useful as a tutorial and also as a task- 
oriented reference. 

Preface xxv 



Volume Five, the X Toolkit lntrinsics Reference Manual, includes reference pages for each of 
the Xt functions, as well as for the widget classes defined by Xt, organized alphabetically for 
ease of reference; a permuted index; and numerous appendices and quick reference aids. 
The two volumes are designed to be used together. To get the most out of the examples in 
Volume Four, you will need the exact calling sequences of each function from Volume Five. 
To understand fully how to use each of the functions described in Volume Five, all but the 
most experienced Toolkit "hacker" will need the explanation and examples in Volume Four. 
Both volumes include material from the original Toolkit documentation provided by MIT, 
though in Volume Four this material is mostly limited to the appendices. We have done our 
best to incorporate all the useful information from the MIT documentation, to reorganize and 
present it in a more useful form, and to supplement it with conceptual material, tutorials, ref- 
erence aids, and examples. In other words, this manual is not only a replacement but is a 
superset of the MIT documentation. 
Those of you familiar with the MIT documentation will recognize that each reference page in 
Volume Five includes the detailed description of the routine found in X Toolkit lntrinsics--C 
Language Interface, plus in many cases additional text that clarifies ambiguities and 
describes the context in which the routine would be used. We have also added cross- 
references to related reference pages and to where additional information can be found in 
Volume Four. 

Assumptions 

This book makes no assumptions about the reader's knowledge of object-oriented program- 
ming or the X Window System. Readers should be proficient in the C programming lan- 
guage, although examples are provided for infrequently used features of the language that are 
necessary or useful when programming with the X Toolkit. In addition, general familiarity 
with the principles of raster graphics will be helpful. 

However, even though the Toolkit is intended to hide the low-level X interface provided by 
Xlib, there are times in writing applications or widgets when Xlib functions will be necessary 
because no Xt feature exists to do the same thing. This book describes the most common 
occasions for using Xlib, but does not provide a reference to the particular functions 
involved. Additional documentation on Xlib, such as that provided by Volume One, Xlib 
Programming Manual, and Volume Two, Xlib Reference Manual, will be indispensable. 

xxvi X Toolkit Intrinsics Programming Manual 



Related Documents 

Seven other books on the X Window System are available from O'Reilly & Associates, Inc.: 
Volume Zero X Protocol Reference Manual 
Volume One Xlib Programming Manual 
Volume Two Xlib Reference Manual 
Volume Three X Window System User's Guide 
Volume Five X Toolkit Intrinsics Reference Manual 
Volume Seven XView Programming Manual 
Quick Reference The X Window System in a Nutshell 

The following documents are included on the X11 source tape: 
X Toolkit IntrinsicsBC Language Interface, by Joel McCormack, Paul Asente, 
and Ralph Swick 
X Toolkit Athena Widgets--C Language Interface, by Ralph Swick and 
Terry Weissman 
XlibBC Language X Interface, by Jim Gettys, Ron Newman, and Robert Scheifler 
The following Nutshell Handbooks published by O'Reilly and Associates, Inc. are useful 
when programming in C: 

Checking C Programs with lint, by Ian Darwin 
Managing Projects with make, by Steve Talbott 
Using C on the UNIX System, by Dave Curry 

The following is the classic introduction to C programming: 
The C Programming Language, by B. W. Kemighan and D. M. Ritchie 
How to Use This Manual 

Volume Four explains both application programming with widgets and widget programming 
(the design and coding of new widgets). 

The first four chapters treat widgets largely as "black boxes," which is appropriate consider- 
ing the object-oriented philosophy of the Toolkit. These chapters also provide an overview 
of many elements of the X Toolkit, and so are appropriate for all readers. 

Chapter 1 

Introduction to the X Window System, provides a discussion of the context in 
which X programs operate. Programmers who are comfortable programming 
with Xlib can skip Chapter 1. 

Chapter 2 

Introduction to the X Toolkit, describes the conceptual foundations underlying 
Toolkit programming, and shows how to write simple programs that use 
widgets from existing widget sets. It introduces such fundamental Toolkit 

Preface xxvii 



programming concepts as resources, the Translation Manager, callbacks, and 
actions. 
Chapter 3 More Techniques for Using Widgets, describes how to use some of the more 
complex widgets found in applications, including composite widgets, con- 
straint widgets, and pop ups. It also describes how to define application 
resources and command-line options, and how to hardcode the value of widget 
resources when you create a widget. Finally, it describes how to create multi- 
ple top-level windows, and how to use application contexts to create applica- 
tions that are more portable. 
Chapter 4 An Example Application, describes a complete application, in several itera- 
tions. First, it shows a simple version of the program, a bitmap editor, as it 
would be written assuming the existence of a BitmapEdit widget (which is 
actually developed in Chapter 5). Then, two refined versions are developed, 
each demonstrating additional Toolkit programming techniques. Finally, the 
same application is shown as it would be written if the bitmap editor were 
implemented in an application window rather than with the BitmapEdit 
widget, as it would be wriuen if no BitmapEdit widget existed. 
The next two chapters describe widget internals, and the process of creating new widgets. 
While this information is not essential for all application programmers, many applications 
require a custom widget to implement their special graphics capabilities. 
Chapter 5 Inside a Widget, describes the code inside a widget. Much of this code is 
common to all widgets. You can think of it as a framework that Xt uses to 
implement a widget's features. After reading this chapter, you should under- 
stand the procedure for creating your own widget around this framework. 
Chapter 6 Basic Widget Methods, describes a widget's initial.ze, expose, 
set_values, destroy, resize and query_eometry methods. (A 
widget's methods are internal routines called automatically by Xt to give the 
widget a degree of independence from the application.) The chapter explains 
when Xt calls each method, and describes in detail what should be in each of 
these methods. Among other things, these methods prepare for and do the 
drawing of graphics that appear in a widget. This chapter describes what the 
Toolkit adds to the graphics model provided by Xlib but does not describe in 
detail how to draw using Xlib; this topic is described in Chapters 5, 6, and 7 of 
Volume One, Xlib Programming Manual. 
Later chapters treat various topics of interest to either application or widget programmers, or 
both. Some of these topics have been introduced in the earlier chapters and are explored 
more completely in the later ones. 
Chapter 7 Events, Translations, and Accelerators, describes the complete syntax of 
translation tables, which allow the user to configure the mapping of event 
sequences into widget actions. It also describes accelerators, a mechanism for 
mapping events in one widget to actions in another. 
Chapter 8 More Input Techniques, describes how to handle events with event handlers 
and how to use information from the event structure inside an event handler or 
action routine. It also describes how to get file, pipe, or socket input, how to 

xxviii X Too&# Intrinsics Programming Manual 



Requests for Comments 

To help us provide you with the best documentation possible, please write to tell us about any 
flaws you find in this manual or how you think it could be improved. 
Our U.S. mail address, e-mail address, and phone numbers are as follows: 
O'Reilly & Associates, Inc. 
632 Petaluma Avenue 
Sebastopol, CA 95472 
800-338-6887 
international + 1 707-829-0515 

UUCP: uunet!ora!adrian Internet: adrian@ora.com 

Bulk Sales Information 

This manual is being resold by many workstation manufacturers as their official X Window 
System documentation. For information on volume discounts for bulk purchase, call 
O'Reilly and Associates, Inc., at 800-338-6887 or send e-mail to linda@ora.com 
(uunet!ora!linda). 
For companies requiring extensive customization of the book, source licensing terms are also 
available. 

Obtaining the X Window System Software 

The X Window system is copyrighted but freely distributed. The only restriction this places 
on its use is that the copyright notice identifying the author and the terms of use must accom- 
pany all copies of the software or documentation. Thanks to this policy, the software is avail- 
able for nominal cost from a variety of sources. See Appendix F, Sources of Additional 
Information, for a listing of these sources. 

Example Programs 

An early version of the example programs in this book is on the X11 Release 4 distribution in 
the contributed section. There are many ways of getting this distribution; most are described 
in Appendix F, Sources of Additional Information. 
The current example programs are available free from UUNET (that is, free except for 
UUNET's usual connect-time charges). If you have access to UUNET, you can retrieve the 
source code using uucp or ftp. For uucp, find a machine with direct access to UUNET, and 
type the following command: 
uucp uunet\ : -/nutshell/xt/xtprogs2. tar. Z yourhos-/yourname/ 

Preface xxxi 



The backslashes can be omitted if you use the Bourne shell (sh) instead of csh. The file 
should appear some time later (up to a day or more) in the directory /usr/spool/uucppub- 
lic/yourname. 
You don't need to subscribe to UUNET to be able to use their archives via UUCP. By calling 
1-900-468-7727 and using the login "uucp" with no password, anyone may uucp any of 
UUNET's on line source collection. (You may wish to start by copying 
uunet!/usr/spool/ftp/ls-lR.Z, which is a compressed index of every file in the archives.) As of 
this writing, the cost is 40 cents per minute. The charges will appear on your next telephone 
bill. 
You don't need to subscribe to UUNET to be able to access its archives byftp either. How- 
ever, you need to use a machine connected to the internet. To useftp,ftp to uunet.uu.net and 
use anonymous as your user name and guest as your password. Then type the following: 
cd nutshell/xt 
b i na ry (you must specify binary transfer for compressed.files) 
get xtprogs2 .tar. Z 
bye 
The file is a compressed tar archive. To restore files once retrieving the archive, type: 
uncompress xtprogs2 .tar 
tar xf xtprogs2.tar 

The examples will be installed in subdirectories under the current directory, one for each 
chapter in the book. Imakefiles are included. (Imakefiles are used with imake, a program 
supplied with the X11 distribution that generates proper Makefiles on a wide variety of sys- 
tems.) 

All the application-defaults files are in the main examples directory. The application- 
defaults files are not automatically installed in the system application-defaults directory 
(usually/usrllib/Xll/app-defaults on UNIX systems). (See Chapter 9, Resource Management 
and Type Conversion, for details.) If you have permission to write to that directory, you can 
copy them there yourself. Otherwise, you can set the XAPPLRESDIR environment variable to 
the complete path of the directory where you installed the examples. The value of XAP- 
PLRESDIR must end with a / (slash). (Most of the examples will not function properly with- 
out the application-defaults files.) 

Acknowledgments 

As mentioned above, this manual includes some material from the Xt Toolkit Intrinsics--C 
Language Interface, by Joel McCormack, Paul Asente, and Ralph Swick. This is the docu- 
ment that defines the X Consortium standard for Xt, known as the Xt specification. Overt 
borrowings from the Xt specification are rare in this volume. However, the Xt specification 
document, as well as the sample code of Xt and the Athena widget set distributed with 
releases of X, provides the intellectual basis for most of what appears here. 
We'd like to thank Sony Microsystems for the loan of a Sony NEWS workstation running 
their implementation of the X Window System. The speed and power of the Sony work- 
station, and the support of Sony's staff, were a great help in developing these books. 

xxxfi X Too&# Intrinsics Programming Manual 



Additional development was done on a Sun-3 workstation running MIT's sample server, a 
Visual 640 X Display Station, and an NCD16 Network Display Station. 
We would also like to thank the reviewers of the Alpha draft of this book, even though we 
almost had to start over because of their comments. They were David Lewis of Integrated 
Computer Solutions (ICS), Wendy Eisner of Sunquest Information Systems, Dan Heller of 
Island Graphics, Inc. (now working with O'Reilly and Associates), Miles O'Neal of Systems 
and Software Solutions, Inc., and Chris Peterson of MIT Project Athena (now of the X Con- 
sortium). Ian Darwin of SoftQuad and Bradley Ross of Cambridge Computer Associates 
reviewed the Beta draft. Extra thanks are due to Ralph Swick, Chris Peterson, and Robert 
Scheifler, who answered many questions during the development of this book. 
Of course, we alone take responsibility for any errors or omissions that remain. 
Special thanks go to Mark Langley, who wrote an early draft of this book. He helped to edu- 
cate us about the Toolkit, and his efforts to make the book a success did not go unnoticed. 
Of course, the authors would like to thank the entire staff of O'Reilly and Associates, Inc., 
and Cambridge Computer Associates, Inc., especially Ellie Cutler, Kathryn Ellis, Virginia 
Estabrook, Edie Freedman, Daniel Gilly, Kismet McDonough, Lenny Muellner, Linda Mui, 
Susan Sarkes Dalton, Ruth Terry, Sue Willing, and Donna Woonteiler, for their help and sup- 
port in the development of this book. Dan Heller helped us learn how the Toolkit is really 
used in typical applications, and helped design the examples and the order of presentation. 
The illustrations (except where borrowed from other books in the series) were done by 
Andrea Pluhar and Chris Reilley. Tim O'Reilly developed the master index, and Dale 
Dougherty revised the indexing program to permit multi-volume indexing. 
Perhaps most of all, we would like to thank our readers and customers for their patience, 
which we tested by promising that this book would be finished next month---every month for 
the last eight months. These days, with word processors, it is easy to generate a book-length 
manuscript, but no easier than it ever was to carve that text into something worth reading. 
We have had that book-length manuscript for a year, but have not been satisfied until now 
that it presented the material in a clear, friendly, and authoritative manner. We hope that the 
extra time we have spent boiling down the facts about this very new and continuously 
advancing subject will prove worthwhile to you, the reader. 

---Adrian Nye and Tim O'Reilly 

Preface xxxiii 



1 

Introduction to the X Window System 

This chapter introduces many of the most important concepts on which the X 
Window System is based, and describes the environment in which the X 
Toolkit operates. This chapter assumes that you are new to programming 
the X Window System. If you already have some experience programming 
the X Window System, you may wish to skim this Chapter for a brief review 
or even begin with Chapter 2. 

In This Chapter: 

The Server and Client ............................................................................ 6 
The Software Hierarchy ......................................................................... 8 
Event-driven Programming .................................................................. 10 
The Window Manager .......................................................................... 11 
Extensions to X ................................................................................... 12 



1 
Introduction to the X Window System 

The X Window System (or simply X)* is a hardware-independent and operating-system- 
independent windowing system. It was developed jointly by MIT and Digital Equipment 
Corporation, and has been adopted by the computer industry as a standard for graphics appli- 
cations. 
X controls a "bit-mapped" display in which every pixel (dot on the screen) is individually 
controllable. This allows applications to draw pictures as well as text. Until recently, indi- 
vidual control of screen pixels was widely available only on personal computers (PCs) and 
high-priced technical workstations. Most general-purpose machines were limited to output 
on text-only terminals. X brings a consistent world of graphic output to both PCs and more 
powerful machines. Figure 1-1 compares an X application to an application running on a tra- 
ditional text terminal. 
Like other windowing systems, X divides the screen into multiple input and output areas 
called windows. Using a terminal emulator, windows can act as "virtual terminals," running 
ordinary text-based applications. However, as shown in Figure 1-1, windows can also run 
applications designed to take advantage of the graphic power of the bitmapped display. 
X takes user input from a pointer. The pointer is usually a mouse but could just as well be a 
track-ball or a tablet. The pointer allows the user to control a program without using the key- 
board, by pointing at objects drawn on the screen such as menus and command buttons. This 
method of using programs is often easier to learn than traditional keyboard control, because it 
is more intuitive. Figure 1-2 shows an application with a typical three-button pointer being 
used to select a menu item. 
Of course, X also handles keyboard input. The pointer directs keyboard input from window 
to window. Only one window at a time can receive keyboard input. 
In X, as in many other window systems, each application need not (and usually does not) 
consist of only a single window. Any pan of an application can have its own separate 
subwindow, which simplifies the management of input and output within the application 
code. Such child windows are visible only within the confines of their parent window. 

*The name "X Windows" is frowned upon by the developers of X. 

Introduction to the X Window System 3 



text 
terminal 

X window 
system 

Figure 1-1. An X application, and an application on a traditional text terminal 

Figure 1-2. A three-button mouse directing the pointer to select a menu item 

4 X Toolkit Intrinsics Programming Manual 



client to the server and from the server to the client takes place using the X Protocol. The 
communication path between a client and the server is called a connection. 

It is common for a user to have programs running on several different hosts in the network, 
all invoked from and displaying their windows on a single screen (see Figure 1-4). Clients 
running remotely can be started from the remote machine or from the local machine using the 
network utilities rlogin or rsh. 

Personal Computer 

Supercomputer 

Mini m t r 

Display Server 

Figure 1-4. Applications can run on any system across the network 

This use of the network is known as distributed processing. The most important application 
of this concept is to provide graphic output for powerful systems that don't have their own 
built-in graphics facilities. However, disu'ibuted processing can also help solve the problem 
of unbalanced system loads. When one host machine is overloaded, the users running clients 
on that machine can arrange for some of their clients to run on other hosts. Eventually, there 
may be automatic load-balancing applications, but currently, such remote execution is done 
manually. It is not unusual to see users in the X environment having several xload load mon- 
itor applications running on various systems throughout the network but displaying on their 
screen, so that they can see the balance of loads throughout the network. 

Introduction to the X Window System 7 



Before leaving the subject of servers and clients, we should mention PC servers and X termi- 
nals. Software is available that allows various types of PCs to operate as X servers.* X ter- 
minals are special-purpose devices designed to run just an X server, and to connect to remote 
systems over a local area network. PC servers and X terminals are the least expensive way to 
provide an X screen for a user. Since most PCs use single-tasking operating systems, they 
can't run any clients at the same time as the server. Therefore, they too require a network 
adapter to connect to another system where clients are run. 
X terminals and PC servers both demonstrate the strength of X's client-server model. Even 
though PCs and X terminals aren't able to do multitasking on their own, they give the user 
the effect of multitasking workstations, because they can interact simultaneously with several 
clients running on remote multitasking systems. 

1.2 

The Software Hierarchy 

This book is about writing client applications for the X Window System, in C, using the Xt 
Intrinsics library and a set of widgets. This is only one of the many ways to write X applica- 
tions, because X is not restricted to a single language or operating system. The only require- 
ment of an X application is that it generate and receive X protocol messages according to the 
X Consortium Protocol specification.f However, using the Xt Intrinsics and a widget set is, 
and is expected to continue to be, the most common way of writing applications for several 
reasons: it is quite powerful; it results in applications that cooperate well with other X appli- 
cations; it supports several popular user-interface conventions; and the C language is widely 
available. 
Figure 1-5 shows the layering of software in an application that uses the Xt Intrinsics and a 
widget set. Notice that the Intrinsics are based upon Xlib, the lowest-level C-language inter- 
face to X. Xlib provides full access to the capabilities of the X protocol, but does little to 
make programming easier. It handles the interface between an application and the network, 
and includes some optimizations that encourage efficient network usage. 
Xt is built upon Xlib. The purpose of Xt is to provide an object-oriented layer that supports 
the user-interface abstraction called a widget. A widget is a reusable, configurable piece of 
code that operates independently of the application except through prearranged interactions. 
A widget set is a collection of widgets that provide commonly used user-interface compo- 
nents tied together with a consistent appearance and user interface (also called look and feel). 
There are several different widget sets from various vendors that are designed to work with 
Xt. The use of widgets separates application code from user-interface code and provides 
ready-to-use user-interface components such as buuons and scrollbars. Xt, widgets, and 
widget sets are described in much more detail in Chapter 2, Introduction to the X Toolkit. 
*Companies such as Graphics Software Systems, Interactive Systems, and Locus Computing offer server implemen- 
tations for IBM-compatible PCs. White Pine Software offers an X server that runs under Multifinder on the Macin- 
tosh. An Amiga server is available from GfxBase/Boing. X terminals are available from Visual Technology, NCR, 
Network Computing Devices (NCD), Tektronix, Graphon Corp, and others. The number of X products on the market 
is growing rapidly. 
'Volume Zero, X Protocol Reference Manual, provides a conceptual discussion of the X protocol and its detailed 
specification. 

8 X Toolkit Intrinsics Programming Manual 



Application 

Widget Set 

Xt Intrinsics 
Xlib 

I .:. 

!1 
X Protocol 
X Server 

Device Drivers 

1 

Figure 1-5. The software architecture of Xt Intrinsics-based applications 

In this book, we'll refer to the combination of the Xt Intrinsics and one widget set as the X 
Toolkit or just the Toolkit. When referring to the Xt Intrinsics layer alone, we'll use Xt, or the 
Intrinsics. 
Applications often need to call Xlib directly to accomplish certain tasks such as drawing. Xt 
does not provide its own graphics calls, nor does it provide access to every X protocol fea- 
ture. This book will describe the features of Xlib that you may need from a Xt application, 
but it will not repeat the detailed description of Xlib programming found in Volume 
One, Xlib Programming Manual. You will find Volume One and Volume Two (Xlib Refer- 
ence Manual) invaluable when you need to make Xlib calls. 
Xlib, Xt, and several widget sets are available on MIT's public software distribution. The 
Motif and OPEN LOOK widget sets are not on the Release 3 or Release 4 distributions from 
MIT, but they are available for minimal cost from the vendors themselves (OSF and AT&T or 
Sun respectively.) The darkly shaded areas of Figure 1-5 indicate interfaces that are exclu- 
sive standards of the X Consortium. That Xlib is an exclusive standard means that computer 
manufacturers wishing to comply with the X Consortium standard must offer Xlib and cannot 
offer any other low-level X interface in C. The lightly shaded areas (such as the Xt Intrin- 
sics) are nonexclusive standards--vendors are required to provide Xt but are also allowed to 
provide other toolkit-level layers for the C language. For example, Sun and AT&T will offer 
Xt, but will also offer XView as an alternate C-language toolkit-level layer. XView was 
originally designed for porting existing SunView TM applications to X, but it can also be used 
for writing new applications. Volume Seven, XView Programming Guide, describes pro- 
gramming with XView. 

Introduction to the X Window System 9 



X software is unlike many other window systems in that it was designed to provide mech- 
anism without mandating any certain style of user interface. In the words of its designers, X 
provides "mechanism without policy." The Xlib and Xt layers are standard because they can 
support any kind of interface. It is the widget set that actually imposes user-interface con- 
ventions, and it is this layer for which no standard has (yet) been considered by the X Con- 
sordum. However, because there is a strong need in the market for one or two standard 
widget sets that provide consistent appearance and user-interface conventions, it is likely that 
one or two widget sets will emerge as de facto standards in the near future. 
It is important to note that the X Consortium standards for Xlib and Xt define the program- 
ming interface to each library (often referred to as the Application Programmer's Interface, 
or API), not the underlying code. That means that vendors are allowed to modify or rewrite 
the code to gain the best performance from their particular system, as long as they keep the 
programming interface the same. To you, the application writer and user of the Intrinsics, 
this means that you must always rely on documented behavior if you want your application to 
run on different systems. You must avoid accessing private structures, because they may be 
different in another vendor's release of the library, or they may be changed in a future release 
of X. 

1.3 

Event-driven Programming 

Programming a graphically-based window system is fundamentally different from standard 
procedural programming. In traditional character-based interfaces, once the application 
starts, it is always in control. It knows just what kind of input it will allow, and may define 
exclusive modes to limit that input. For example, the application might ask the user for input 
with a menu, and use the reply to go down a level to a new menu, where the actions that were 
possible at the previous level are no longer available. Or a text editor may operate in one 
mode in which keyboard input is interpreted as editor commands, and another in which it is 
interpreted as data to be stored in an editor buffer. In any case, only keyboard input is 
expected. 
In a window system, by contrast, multiple graphic applications may be running simulta- 
neously. In addition to the keyboard, the user can use the pointer to select data, click on but- 
tons or scrollbars, or change the keyboard focus from one application to another. Except in 
special cases (for example, where a "dialog box" will not relinquish control until the user 
provides some necessary information), applications are modeless--the user can suddenly 
switch from the keyboard to the mouse, or from one application area to another. Further- 
more, as the user moves and resizes windows on the screen, application windows may be 
obscured or redisplayed. The application must be prepared to respond to any one of many 
different events at any time. 
An X event is a data structure sent by the server that describes something that just happened 
that may be of interest to the application. There are two major categories of events: user 
input and window system side effects. For example, the user pressing a keyboard key or 
clicking a mouse button generates an event; a window being moved on the screen also 

10 X Toolkit Intrinsics Programming Manual 



generates events--possibly in other applications as well if the movement changes the visible 
portions of their windows. It is the server's job to distribute events to the various windows 
on the screen. 

Event-driven window programming reduces modes to a minimum, so that the user does not 
need to navigate a deep menu structure and can perform any action at any time. The user, not 
the application, is in control. The application simply performs some setup and then goes into 
a loop from which application functions may be invoked in any order as events arrive. 

1.4 The Window Manager 

Because multiple client applications can be running simultaneously, rules must exist for arbi- 
trating conflicting demands for input. For example, does keyboard input automatically go to 
whichever window the pointer is in, or must the user explicitly select a window? How does 
the user move or resize windows? 
Unlike most window systems, X itself makes no rules about this kind of thing. Instead, there 
is a special client called the window manager that manages the positions and sizes of the 
main windows of applications on a server's display. The window manager is just another cli- 
ent, but by convention it is given special responsibility to mediate competing demands for the 
physical resources of a display, including screen space, color resources, and the keyboard. 
The window manager allows the user to move windows around on the screen, resize them, 
and usually start new applications. The window manager also defines much of the visible 
behavior of the window system, such as whether windows are allowed to overlap or are tiled 
(side by side), and whether the keyboard keyboard focus simply follows the pointer from 
window to window, or whether the user must click a pointer button in a window to change 
the keyboard focus. 
Applications are required to give the window manager certain information to help it mediate 
competing demands for screen space or other resources. For example, an application speci- 
fies its preferred size and size increments. These are known as window manager hints 
because the window manager is not required to honor them. The Toolkit provides an easy 
way for applications to set window manager hints. 
The conventions for interaction with the window manager and with other clients have been 
standardized by the X Consortium as of July 1989 in a manual called the Inter-Client Com- 
munication Conventions Manual (ICCCM for short). The ICCCM defines basic policy inten- 
tionally omitted from X itself, such as the rules for transferring data between applications 
(selections), for transferring keyboard focus, for installing colormaps, and so on. 
As long as applications and window managers follow the conventions set out in the ICCCM, 
applications created with different toolkits will be able to coexist and work together on the 
same server. Toolkit applications should be immune to the effects of changes from earlier 
conventions because the conventions are implemented by code hidden in a standard widget 
called Shall. However, you should be aware that some older applications and window man- 
agers do not play by the current rules. 

Introduction to the X Window System 11 



1.5 Extensions to X 

X is also extensible. The code includes a defined mechanism for incorporating extensions, so 
that vendors aren't forced to modify the existing system in incompatible ways when adding 
features. An extension requires an additional piece of software on the server side and an 
additional library at the same level as Xlib on the client side. After an initial query to see 
whether the server portion of the extension software is installed, these extensions are used 
just as Xlib routines and perform at the same level. 
Among the extensions currently being developed are support for 2-D spline curves, for 3-D 
graphics, and for display PostScript TM. These extensions can be used in Toolkit applications 
just as Xlib can. 

12 X Toolkit Intrinsics Programming Manual 



2 

Introduction to the X Toolkit 

This chapter provides a conceptual introduction to the X Toolkit, followed by a 
practical tutorial that starts with the most fundamental toolkit program, a 
"hello world" type application consisting of only a single widget. This applica- 
tion is successively refined until the major elements of any X Toolkit program 
have been introduced. 

In This Chapter: 

Programming with Widgets .................................................................. 15 
Contents of a Widget Set ................................................................. 17 
Widget Classes and Instances ......................................................... 18 
Widget Configurability with Resources ............................................. 23 
Widget Independence ...................................................................... 25 
Widget-Application Interaction .......................................................... 27 
Xt and Object-oriented Programming (OOP) .................................... 30 
The Object ..................................................................................... 30 
Methods ........................................................................................ 31 
Messages ...................................................................................... 31 
Encapsulation ................................................................................ 31 
Structure of X Toolkit Applications ........................................................ 32 
A Simple X Toolkit Application .............................................................. 33 
The Code ........................................................................................ 33 
Compiling the Application ................................................................. 36 
The Application-defaults File ............................................................ 38 
To Hardcode or Not to Hardcode ..................................................... 40 
Connecting Widgets to Application Code .............................................. 41 
Callbacks ......................................................................................... 42 
Actions ............................................................................................ 45 
The Actions Table .......................................................................... 48 
Format of an Action Procedure ...................................................... 48 



The Translation Table ..................................................................... 49 
Hardcoding Translations ................................................................ 51 
More About Resources ........................................................................ 52 
Setting and Getting Resources from the Application ......................... 52 
Setting Resources with the Varargs Interfaces ............................... 53 
Setting Resources with the ArgList Interfaces ................................ 54 
Getting a Resource Value .............................................................. 56 
Core Resources ............................................................................... 57 
Other Inherited Resources ............................................................... 59 



Two commercial widget sets that are easily available and quite complete are OSF's Motif 
and AT&T's OPEN LOOK widgets. Both Motif and OPEN LOOK contain menus, scrollbars, 
command buttons, dialog boxes, and a wide variety of composite widgets. Both have an 
attractive appearance and consistent, well defined user-interface conventions. Each comes 
with a style guide that contains suggestions for designing applications to blend in well with 
other applications using that widget set. 

Appendix A, OPENLOOK and Motif, describes these widget sets. 

Widget Classes and Instances 

A widget set defines classes of widgets. Both the Athena and Motif widgets sets have a 
Label widget class which performs approximately the same job. However, these are two dif- 
ferent widget classes in Xt, even though they may seem to fit the standard English definition 
of a single class. (In practice, one would rarely want to use both of these widget classes in 
one application anyway.) 
Command is a class of widget, as are Box, Label, Scrollbar, and the other Athena widgets 
shown in our hypothetical application. Each time you create a widget, you create an instance 
of one of these predefined classes. For example, you might create several Command widgets, 
each with a unique name, containing a unique text label, and each invoking different applica- 
tion code when it is clicked on. All these widgets would be of class Command. They would 
have similar characteristics, but they would not necessarily look or act exactly the same since 
each could have been configured differently. 
A widget class has certain fixed features which are common to all instances of that class, and 
certain characteristics which can be changed from instance to instance. 
How you view a class depends on whether you are using existing widget classes or writing 
new ones. Eventually you will thoroughly understand both these views of a class, since you 
will be a competent widget user and widget writer. Both views are introduced here because 
we don't want to mislead you by telling you only half the story of what a class is. But for the 
first four chapters of this book, we will be concentrating on the widget user's point of view. 
For a user of existing widget classes (a widget set), a widget class is a black box that has cer- 
tain fixed features and certain configurable features, both of which are documented on the 
widget class's reference page. You need not know anything about how a class is imple- 
mented in Xt. You know that when you create an instance of that widget class, the instance 
will have the documented fixed features and you can set the configurable features. A user of 
existing widget classes is most interested in the configurable features, since setting these is a 
big part of programming an Xt application. Each configurable feature is called a resource. 
Resources are more fully introduced in the next section. 
If you are writing a widget class, or you have written one and see things from that perspec- 
five, a class seems slightly different. To you, a widget class is a set of three files in which the 
widget class is implemented. The widget class is no longer a black boxwit is an open box. 
Knowing what widget class code looks like, you know that its fixed features and its configur- 
able features are implemented in distinct sections of the code. You know that each resource 
is actually represented by a field in a structure. Even though you may not even have access 

18 X Toolkit Intrinsics Programming Manual 



to the source code for a widget class, your definition of a class is based on how that class is 
implemented. 
These two views of a class take on special relevance when looking at a characteristic of the 
Toolkit called class inheritance. Widget features and characteristics can be inherited from 
other, more basic classes of widgets. To a widget user, class inheritance is important only 
because it means that the resources (configurable features) of a widget class are defined not 
only by that class but also by the classes that class inherits features from, called its super- 
classes. When you look up a widget classes's features on its reference page, you will have to 
look up its superclass and look on that page also, and continue up the class inheritance hierar- 
chy to the most basic widget, in order to get a complete list of its capabilities. This sounds 
difficult, but in reality you get to know the features of the most basic classes by heart, and 
there are not very many classes. 
From the widget writer's point of view, inheritance means that a new class of widget has to 
define only its own unique features, and need not re-implement those common to all widgets, 
or already implemented by an existing superclass. All classes exist in a hierarchy, which 
defines from which other classes each class inherits features. (Note that the class hierarchy is 
completely different from the parent-child relationship of widget instances you create in an 
application. The class hierarchy of a particular widget set is fixed by the widget set writers, 
while the instance hierarchy is different in every application and is determined by the appli- 
cation writer.) 
Figure 2-2 shows the class inheritance hierarchy for the Athena Widgets. Classes defined by 
Xt (which are the same for all widget sets) are shaded gray.* 
The Core widget class, defined by the Intrinsics, is the root of the hierarchy, from which all 
other classes are descended. The Core class defines characteristics common to all widgets, 
such as size and position. 
The Athena Simple widget class inherits basic widget features from Core and adds a few 
minor features of its own (for example, the ability to change the cursor shape when it enters 
the window). The Label widget in turn adds the ability to print a string, and mechanisms for 
changing the font and placement of the string, widget)" Command then inherits features 
from Label (including those already inherited from Core and Simple) and adds more features 
(the ability to accept user input, and to highlight the button). Command is known as a sub- 
class of Label, and Label is the superclass of Command. In general, lower classes in the 
hierarchy have more features. 

*Note that the X Toolkit supports only single inheritance. That is, characteristics can be inherited directly from only 
one superclass (though that superclass may itself have inherited characteristics from prior superclasses. 

Introduction to the X TooAk# 19 



Most applications use a TopLevel shell for their main window; pop ups use either an 
OverrideShell or a TransientShell. (See Chapter 12, Menus, Gadgets, and Cascaded Pop 
Ups, for more information on Shell widget classes.) 
Constraint is a further refinement of Composite that allows the application or the user to sup- 
ply inslructions about how the size and position of each child should be managed. 
The Athena widgets are described in Volume Five, X Toolkit Intrinsics Reference Manual. 
New widgets can be subclassed by the widget programmer directly from Core, Composite, or 
Constraint, or can be subclassed from an existing widget in any widget set that has some of 
the desired behavior. For example, it is easy to imagine creating subclasses of Form to pro- 
vide other types of preconfigured dialog boxes or data entry screens. 
As long as appropriate widget classes are available, the application programmer needs to 
know little or nothing about widget internals. In fact, even if widget internals are known, it is 
unwise to depend on them. Widgets should be treated as black boxes with documented 
inputs and outputs. If only these documented interfaces are used, the widget internals can be 
modified without affecting the application, and the application can be modified without 
affecting the widget. 

.1.3 

Widget Configurability with Resources 

To serve their purpose as reusable user-interface components, widgets must be highly confi- 
gurable. For example, an application programmer must be able to define not only a separate 
label for each Command widget, but also the application function that is invoked when the 
button is clicked. The programmer will also want to let the user define additional attributes 
such as font and color. 

To support this degree of configurability, widget classes can declare variables as named 
resources of the widget. The application can pass the value of widget resources as arguments 
to the call to create a widget instance, or can set them after creation using the Intrinsics call 
Xt:Set:va]_uea. In addition, though, as an application starts up, a part of Xlib called the 
resource manager reads configuration settings placed in a series of ASCii files by the user 
and/or the application developer, and Xt automatically uses this information to configure the 
widgets in the application. The collection of resource name-value pairs contained in the vari- 
ous resource files and set directly by the application is collectively referred to as the resource 
database. 

Figure 2-6 shows several Label widgets configured with different resource settings, to show 
you how radically the appearance of even such a simple widget can be altered. Note that a 
widget's input characteristics can also be configured (although the Label class has no input 
characteristics to configure). 

The resource manager provides a very flexible mechanism for generalizing the behavior of 
widgets. The application developer can "hardcode" the value of resources that cannot be 
changed without crippling the widget or application, and can establish reasonable defaults 
for the rest, so that the user can configure all nonessential aspects of application appearance 
and behavior. 

Introduction to the X Toolkit 23 



Hello. World ! 

Figure 2-6. Several Label widgets configured using resources 

Note that the term resource is used somewhat ambiguously in X. First, in the original docu- 
mentation for Xlib and the X protocol, various data structures that are maintained by the 
server and identified to clients only by an integer ID are referred to as resources. These data 
structures include windows, bitmaps, fonts, and so forth. 
Second, the term is commonly used to refer both to a widget variable publicly declared as a 
widget resource, and to the name-value pairs in the resource database. In this book, we will 
use the term resource to refer to the actual variable and its current value in a widget instance, 
and the term resource setting to refer to a name-value pair in the database. The two are 
closely related, but may not be identical. For example, separate settings for the same 
resource may be requested in an application-defaults file and in an individual user-preference 
file.* Furthermore, the value of a resource may be set on the fly by a call to xt:set:vaZuea, 
but this value is never saved in the resource database. (This value can be retrieved from 
within a widget or application by a call to Xt:Get:Va].uea.) 

*There are several possible sources of resource settings. Which will actually take effect is determined by rules of 
precedence that are described (along with the various sources of resource settings) in Chapter 9. 

24 X Toolkit Intrinsics Programming Manual 



]] Server  
Network 
Drawing I i Expose and user 
requests t events 
Intrinsics 
........... 

Widgets operate independently of the application ... 

Figure 2-7. Widgets operate independently of the application 

26 X Toolkit Intrinsics Programming Manual 



Server 

Network 

Widget ] 
.,xts, ...... . ....... 
l Application Code l 

Xt 
Intrinsics 
routines 

...but the application can change various characteristics of 
the widget with XtSetValues 
Figure 2-8. XtSetValues lets the application set how a widget will operate itself 

Widget-Application Interaction 

In the other direction, wJdgeLs are designed to let the user control the application. Therefore, 
widgets have the ability to invoke certain sections of application codewelements of the 
application's own choosing. Again, though, widgets will operate fine without invoking any 
application code, but if they don't invoke any, they won't do anything for the user. 
One way that the application arranges for widgets to invoke application code is by register- 
ing application functions with Xt. Once the application is running, Xt will call these func- 
tions in response to some occurrence in the widget. For example, a Command widget usually 
invokes an application function when the user clicks on the widget. (Thus, the widget 
labeled "Quit" might invoke the code that exits the application.) Or the Scrollbar widget 
notifies the application when the user has moved the thumb, by calling a function that the 
application has registered with the widget for that purpose. Figure 2-9 and Figure 2-10 illus- 

Introduction to the X Toolkit 27 



trate how an application registers a function during the startup phase, and how Xt then calls 
the function during the event-loop phase in response to a particular occurrence in the widget. 

 Network 
........ 

idget ........ 
"':"1:': ': :::'" :-::!!-!-!:!-.. ::::::!:i;:!::::::::!i:!!:!::::::::;.<:N:!!:: .--:-- ::::::-:': 
-- .-.-:i register callback routines 
I I:.: (or. less often, action 
;:; routines) 

Application Code 

Xt 
intrinsics 
routines 

\ 
... and the application can provide and register callback or action 
functions with the widget ... 
_ 
Figure 2-9. Application registers a function with Xt during startup phase 

There are three separate mechanisms that can be used to link widgets and application func- 
tions: callbacks, actions, and event handlers. 
Generally speaking, a widget expecting to interact with an application will declare one or 
more callback lists as resources; the application adds functions to these callback lists, which 
will be invoked whenever the predefined callback conditions are met. Callback lists are 
resources, so that the application can set or change the function that will be invoked. 
Callbacks are not necessarily invoked in response to any event; a widget can call the speci- 
fied routines at any arbitrary point in its code, whenever it wants to provide a "hook" for 
application interaction. For example, all widgets provide a dest:z:oyCal.l.back resource 
to allow applications to interpose a routine to be executed when the widget is destroyed. 

28 X Toolkit Intrinsics Programming Manual 



2.1.6.2 Methods 

2.1.6.3 

2.1.6.4 

What is called a method in traditional tOP is either a method or an action in Xt. In Xt, 
methods are a set of functions that are fixed for a particular class, triggered in fixed ways in 
response to Xt function calls made by the application (with one special case, the expose 
method, triggered directly by the Expose event). A widget's methods supply its most basic 
functions, such as the code needed to create a widget or to change its resources. Actions, on 
the other hand, are called in response to the events specified in a translation table, and are 
thus user configurable. Actions supply most of the features of widgets, and these features can 
be added to or replaced by the application, as demonstrated in Sections 2.4.2, 4.3, and 4.4. 

Messages 

In pure tOP, input to objects and communication between them are called messages. In Xt, 
however, the forms of communication are function calls, events, actions, and callbacks. As 
you have seen, applications can communicate with widgets using function calls, such as to 
set or get widget resources using XtSetValues and XtGetValues. Widgets also 
respond directly to events from the user. Widgets contact the application when certain things 
occur using callbacks or actions. Widgets pass data back and forth using special kinds of 
events. All these types of communication can be thought of as forms of messages. 

Encapsulation 

Objects are intended to be black boxes with documented inputs and outputs. In other words, a 
program that uses an object must not depend on the internal implementation of the object, but 
instead only on the known inputs and outputs. This is called code encapsulation. The advan- 
tages of code encapsulation are that programmers can use the object without needing to 
understand its internal implementation (hiding details), and that the internal implementation 
of the object can be changed at any time because no other code depends on it. This can be 
stated in another way: it minimizes interdependencies. In large software projects, this one 
feature makes tOP worthwhile. 
This encapsulation is very effective in Xt. You should be able to get a long way toward com- 
pleting an application without even needing to know what the code inside a widget looks 
like, let alone the details that implement a particular widget. For that reason, in this book we 
don't show you what is inside a widget until Chapter 5, Inside a Widget. Even when you do 
know how widgets are implemented, it is a good idea to "forget" while writing application 
code, so that you are not tempted to depend on implementation details. 
Each widget class has a public include file and a private include file. The application 
includes just the public include file, while the actual widget code includes the private (which 
happens also to include the public). The names of both include files are based on the class 
name of the widget, but the private include file adds the letter P to the end. For example, the 
Label widget's public include file is Label.h, while its private include file is LabelP.h. Appli- 
cation code should include only the public include file, to maintain the desired encapsulation, 
It is tempting for beginning Xt programmers to include the private include file, because it 
allows you to take shortcuts, but you should resist the temptation.* 

*In a language designed for tOP, such as C++, these shortcuts are generally prevented by the compiler or by the lan- 
guage itself. 

Introduction to the X Toolkit 31 



2.3 A Simple X Toolkit Application 

Some application code that uses the X Toolkit will go a long way to illustrate the basic con- 
cepts introduced above. 

Figure 2-11 shows the actual window created by a minimal "hello, world" Toolkit application 
xhello, and Example 2-1 shows the code for it. xhello simply displays the string "hello" in a 
window. 

hello 

Figure 2-11. xhello: appearance on screen 

Most window managers add a decorated border above or surrounding the window; this is not 
part of the application. Likewise, the placement of the widget on the screen depends on the 
window manager. Since no coordinates are specified as resources for the widget, most win- 
dow managers will require the user to place it interactively. Some window managers can be 
configured to place new windows at an arbitrary default location. 

2.3.1 

The Code 

Example 2-1 shows the code for xhello.c. 

Example 2-1. xhello.c: a minimal "hello, world" application 
/* 
* xhello.c - simple program to put up a banner on the display 
*/ 

/* 
* Include files required for all Toolkit programs 
*/ 
#include <Xll/Intrinsic.h> /* Intrinsics Definitions*/ 
#include <Xll/StringDefs.h> /* Standard Name-String definitions*/ 
/* 
* Public include file for widgets we actually use in this file. 
*/ 
#include <Xll/Xaw/Label.h> 

main(argc, argv) 
int argc; 
char **argv; 
{ 
XtAppContext app_context; 
Widget topLevel, hello; 

/* Athena Label Widget */ 

Introduction to the X TooAkit 33 



XtRealizeWidget as long as there is a good reason to do so (for example, when it 
cannot be known whether the widget would be needed until a certain user event arrives). 
The realization step also maps all the widget windows. Mapping is an X concept, not 
something added by Xt. Mapping a window makes it eligible for display. For a window 
to actually become visible, all its ancestors must be mapped. Since XtRealize- 
widget is called for the widget created by XtVaAppTnitialize, which is the 
ancestor of all widgets in the application, the end result is that the entire application is 
displayed.* 
XtAppMainLoop transfers control of the application to Xt. From this point on, Xt 
drives all the widgets in response to events, and it interacts with the application only at 
times the application has arranged ahead of time. xhello did not arrange any interaction 
with the widget, so Xt operates the Label widget without returning to xhello's code. 
Examples 2-3 through 2-8 will demonstrate how to make such arrangements. 
Xt programming is event-driven. XtAppMainLoop dispatches events to widgets and 
functions in the order in which they occur. These events can be caused by user actions 
such as pressing a key or by window system actions such as displaying a new window. 
This is fundamentally different from procedural programming, where the application is in 
charge and polls for user input at certain points. 

2.3.2 Compiling the Application 

You can get the code for xhello.c and all the rest of the examples in this book via uucp or 
anonymous ftp, as described in the Preface. The code is also on the Release 4 distribution 
tape from MIT in the "contrib" section. It is a good idea to compile and run each example as 
it is presented. 

The example programs come with Imakefiles that should make building them easy if you 
have the X source. To do this you need the imake program (which should already be in 
lusrllib/X11 on your system), and you need the configuration files in TOP/mitlconJig, where 
TOP is the root of your X sources. An Imakefile is a system-independent makefile that is 
used by imake to generate a Makefile. This is necessary because it is impossible to write a 
Makefile that will work on all systems. You invoke imake using the ximake.sh shell script 
also provided in the X sources. Complete instructions for compiling the examples using 
imake are provided in a README file in the example source. 

*There are several other conditions that can prevent or delay a window from becoming visible, described in Section 
2.2.5 of Volume One, Xlib Programming Manual (Section 2.2.4 in the 2rid edition of Volume One). These will not 
affect your Toolkit application as long as you draw into windows at the right time, using one of the techniques de- 
scribed in Section 4.3 and Section 6.3. 

36 X Toolkit Intrinsics Programming Manual 



Is the X Toolkit Too Complex? 
An editorial aside 

i . 

Window systems may be simple to use, but they are very complex to program. The first 
thing that strikes the novice X programmer is how complicated everything is. Learning to 
program the X Window System, even with the help of the X Toolkit, is afar cry from learn- 
ing say, the C programming language, where the very first page of the tutorial presents a 
complete running program. The program itself is trivial, but this, the "hello worM" pro- 
gram, has become a tacit benchmark of programmability. The assumption is "'if you can't 
write "hello world' simply, things are badly designed." 

In fact, "hello, worM" is a pathological example for X; it is a case where the stylized scaf- 
folding outweighs the functional code. You've just seen an X Toolkit equivalent to "hello 
worM," and it is nearly thirty lines long. But it is node-independent, does device- 
independent graphics, and can be customized by the user to control what font to use, and 
what color to use for the border, background, and text. 

The "hello worM" example is indeed a good benchmark of language complexity, but it is 
not necessarily a good general benchmark for overall programming complexity. It is an 
especially poor measure for a system that encompasses a generalized distributed software 
environment, network communication, and device-independent graphics. Most people 
write complicated applications, not trivial programs like "hello, worM," and it is the ease 
with which a complicated program can be written that is the true test of a language. 

For example, consider the difference in the number of lines of code between "hello worM" 
and a text editor. Kernighan & Ritchie' s C Programming Language, where "hello worM" 
was first introduced, doesn't present an editor. However, Kernighan and Plaugher' s Soft- 
ware Tools, an equally sacred reference from the same era, presents a text editor that con- 
tains well over one thousand lines. Furthermore, the editor is line-oriented, not screen- 
oriented. By comparison, because of the modular design of the Toolkit, and the develop- 
ment of widgets as reusable user-interface components, a programmer can construct a 
simple screen editor using the Athena Text widget in about 170 lines of code. This editor is 
user-configurable, device-independent, and based on a ready-made component that can 
easily be incorporated into any program needing to provide text-editing capabilities. 

This is not to invite absurd comparisons of incommensurate programming tools, but to 
emphasize that the complexity of X is the outgrowth of added functionality, not unneces- 
sary convolutions of straightforward algorithms. What really matters is what features are 
provided, how difficult is it to write the kind of application you want to write, and what 
performance can be achieved. 

reMark Langley 

Introduction to the X Too/k# 37 



To compile any of the examples on a UNIX system without using imake, use the following 
command line: 
cc -o filename filename.c -IXaw -iXmu -iXt -iXext -iXll 
The order of the libraries is important. Xaw relies on Xmu (miscellaneous utilities), and both 
rely on Xt. Xaw relies on Xext, the X Consortium extension package which supports non- 
rectangular windows (if you have a pre-R4 server, applications linked with this library will 
run but you will not see any non-rectangular windows). Both Xmu and Xt in turn depend on 
Xlib (the -IXll link flag specifies Xlib). 

The Application-defaults File 

As mentioned above, the resource mechanism allows widgets and applications to be custom- 
ized. Resources may be declared by either a widget or an application, and can be set from 
any one of several sources, including a user's resource file, the command line, or an applica- 
tion-specific defaults file. 
Each resource of a widget has a default value determined by the widget class that declared 
the resource. However, in many cases, the application wants a different default value, but 
still wants the user to be able to change the value of that resource. 
The Label widget is a case in point. Example 2-1 (xhello) set the default string displayed in 
the Label widget, "hello," by naming the widget hello in the call to XtVaCreate- 
ManagedWidget. It just so happens that the Label widget uses its widget name as the 
string to be displayed if no other string has been specified in the resource database. However, 
this trick doesn't exist for the other resources of Label or of other widgets. 
The application can provide a default value for resources by hardcoding them in the applica- 
tion source file using the fallback resources argument of XtAppTnitialize. However, 
changing these settings would require recompiling the source. Xt provides a better way. 
To provide defaults, applications should always create an "application-defaults" resource file, 
which on UNIX systems is usually stored in the directory lusrlliblXlllapp-defaults.* For any 
application, the name of this file should be the same as the classname argument to Xt- 
VaApplnitiali ze. By convention, this string is the same as the name of the application, 
with the first letter capitalized. If the application name begins with X, the first two letters 
should be capitalized. For xhello this is XHello/f 
Example 2-2 shows the contents of the application-defaults file necessary to make xhello dis- 
play the string "Hello, World!" instead of the default "hello." 

*New in R4 is a mechanism that allows you to provide a different application defaults file for each language. This 
will be described in Chapter 9, Resource Management and Type Conversion. 
%Note that existing applications do not always follow this lauer convention. For example, the application-defaults 
file for xmh is called Xmh, not XMh. 

38 X Toolkit Intrinsics Programming Manual 



A partial solution is to document the default resource specifications and require that users 
reinstall those default specifications before a technical support person tries to solve their 
problems. In some cases, dialog boxes can be added that require the user to confirm any irre- 
versible actions. 
In any case, you may eventually want to hardcode certain resources in the application so that 
they are not user configurable. This would be done for resources that, if set incorrectly, 
would make your application operate in an unsafe fashion. Hardcoding a widget resource is 
done by placing the resource name and the desired value in the final arguments to Xt- 
VaCreateManagedWidget or XtCreateManagedWidget. 
This technique is demonstrated later, because you won't need it until the final stages of 
releasing your application. While an application is under development, it is better to leave 
all resources configurable from resource files, because this allows you to change them in the 
application-defaults file without recompiling the source. When the code is stable and almost 
ready for release, then it's time to determine which resources need to be hardcoded. 

2.4 Connecting Widgets to Application Code 

The Toolkit is designed so the code that implements the user interface and the code that 
implements application features can be kept separate. This is an advantage, because it allows 
either part to be modified without affecting the other. However, these two pieces of code 
need to be intimately connected, because the user interface must drive the application code. 
This section describes the two basic ways of making this connection using callbacks and 
actions. As mentioned earlier, the general idea of both techniques is that the application reg- 
isters functions to be called by Xt in sequence in response to occurrences within certain 
widgets. 
The two techniques differ in the way that the registered function is invoked. For callbacks, 
the trigger is an abstract occurrence defined by the widget, which may or may not be event 
related. When this happens, the routines on one of a widget's callback lists is invoked by the 
widget code, using a call to XtCallCallbacks or XtCallCallbackList. Actions, 
on the other hand, are invoked directly by Xt's translation mechanism, as the result of an 
event combination. 
An action is a function that Performs one widget feature. A callback is a function that per- 
forms one application feature. This distinction should be kept in mind, but is not quite as 
clear as it sounds, since one widget feature is often the ability to call a function that imple- 
ments an application feature. Callbacks are often invoked by widgets from within action rou- 
tines. For example, the Command widget defines a callback resource called xt Nc a 11 b a c k 
and several action routines, one of which (not if y) simply calls the functions registered 
with the XtNcallback resource. This combination of the two mechanisms makes the 
abstract occurrence that triggers a callback customizable. In other words, when these mecha- 
nisms are combined you can configure what user behavior will trigger the callback by using 
the translation manager which maps events into actions. 

Introduction to the X Toolkit 41 



The two mechanisms also differ in the way they are added to a widget. The application can 
add a callback roudne to a widget using Xt;/ddCa]_]_back or Xt;/ddCa]_]_backs only if 
the widget has declared a callback list as a resource. When a widget has a callback resource, 
it means that the widget writer foresaw that users of the widget would want to have applica- 
tion code called in response to a particular user behavior in that widget. Actions, on the other 
hand, can be added to a widget using Xt:AppAdclkct:i.ons without the widget's knowledge 
or consent. 
A widget class may have more than one callback resource. For example, the Athena 
Scrollbar widget defines a xt:t,lacrollt:'roc callback resource to be invoked when the first 
or third buttons are clicked in the scrollbar, a Xt;Nt;humbProc callback resource to be 
invoked when the user drags the thumb with the pointer, and a Xt;NjumpProc callback 
resource when the user clicks the second button. Each of these callbacks indicates a different 
kind of user behavior, and requires a different kind of movement of the data in the associated 
window. The callback function registered with each of these callback resources would actu- 
ally move the data in the various ways. 
Widgets define actions in order to implement their basic features in a modular way that 
allows the event sequences that trigger the actions to be customizable. Applications can also 
add actions to add features that a widget does not already provide. When working with a 
widget set such as Modf or OPEN LOOK that has clearly-defined user-interface conventions, 
adding new behavior to a widget may not be an appropriate thing to do. In addition, using 
actions is somewhat more complex than using callbacks, and actions have no advantages 
over callbacks when an appropriate callback is available. 
The next two sections describe how to use callbacks and then how to use actions. 

2.4.1 

Callbacks 

To illustrate the use of callbacks from the application, we will write an application that uses 
the Athena Command widget. This type of widget is also known as a pushbutton; some 
analogue will be present in every widget set. It contains a string or picture, and executes a 
command when a pointer button is clicked on it. 
A Command widget calls an application function when you press and release the first pointer 
button Coy default) in its window. It also highlights the window border of the Command 
widget when you move the pointer into it. When you press and hold the pointer button in the 
Command widget's window, the Command widget redraws the window in reverse video. 
Moving the held button out of the window resets the widget without executing the command. 
The xgoodbye program creates a single Command widget. It is very similar to xhello, but 
takes advantage of the callback provided by the Command widget. Clicking on the "Good- 
bye, Cruel World" button exits the program. 
Figure 2-12 shows the window that xgoodbye creates if you have installed the suggested 
application-defaults file (otherwise, it will display "goodbye"). It is suggested that you com- 
pile and run xgoodbye.c, testing its response to moving the pointer in and out of its window, 
and clicking the various pointer buttons on its window. 

42 X Toolkit Intrinsics Programming Manual 



Figure 2-12. The appearance of xgoodbye when the pointer is in the window 

This example is not as frivolous as it seems. Many applications use code identical to this to 
implement their "Quit" button. 

The code for xgoodbye.c is shown in Example 2-3. 

Examp 23. xgoodbye.c:compcode 
/. 
* xgoodbye.c - simple program to put up a banner on the display 
* and callback an application function. 
*/ 
#include <stdio.h> 
/* 
* Include files required for all Toolkit programs 
*/ 
#include <Xll/Intrinsic.h> /* Intrinsics Definitions */ 
#include <Xll/StringDefs.h> /* Standard Name-String definitions */ 
/* 
* Public include file for widgets we actually use in this file. 
*/ 
#include <Xll/Xaw/Command.h> /* Athena Command Widget */ 
/* 
* Quit button callback function 
*/ 
/* ARGSUSED */ 
void Quit(w, client_data, call_data) 
Widget w; 
XtPointer client data, call data; 
_ -- 
{ 
fprintf(stder, "It was nice knowing you.ln"); 
exit(0); 
} 
main(argc, argv) 
int argc; 
char **argv; 
{ 
XtAppContext app_context; 
Widget topLevel, goodbye; 
topLevel = XtVaAppInitialize( 
&app_context, /* Application context */ 
"XGoodbye", /* Application class */ 
NULL, 0, /* command line option list */ 
&argc, argv, /* command line args */ 
NULL, /* for missing app-defaults file */ 

Introduction to the X Toolkit 43 



Example 2-3. xgoodbye.c: complete code (continued) 

NULL); /* terminate varargs list */ 
goodbye = XtVaCreateManagedWidget( 
"goodbye", /* arbitrary widget name */ 
commandWidgetClass,/* widget class from Command.h */ 
topLevel, /* parent widget*/ 
NULL); /* terminate varargs list */ 
XtAddCallback(goodbye, XtNcallback, Quit, 0 /* client data */); 
-- 

/* 
* Create windows for widgets and map them. 
*/ 
XtRealizeWidget (topLevel) ; 
/* 
* Loop for events. 
*/ 
XtAppMa inLoop (app_context) ; 
) 
And here is xgoodbye's application-defaults file: 

Example 2-4. XGoodbye: the app/ication-defautts file 
*goodbye.label: Goodbye, Cruel World! 
The differences between xgoodbye and xhello all apply to adding a callback function. In this 
example we have some application code (the Quit function) that we register with Xt as a 
callback function for the widget called goodbye using the XtAddCallback call. 
The Quit function is defined before main, so that we can use the function pointer Quit in 
the XtAddCallback call. It is also possible to declare Quit as a function pointer early in 
the application, but actually to define it further down in the source code. 
The XtAddCallback call used to register Quit as the Command widget's callback is as 
follows: 
XtAddCallback(goodbye, XtNcallback, Quit, 0); 
The first argument, goodbye, is the widget that is to trigger the callback. The second argu- 
ment, XtNcallback, is a symbolic constant that identifies which of the widget's callback 
resources is being set. (This constant, like most resource names defined by Xt, is defined in 
the file <X111StringDefs.h>. Additional resource names are often defined by an individual 
widget's public header file.) In this particular case, the name XtNcallback does not shed 
any light on the real purpose of the callback. A better name would have been XtNnotify- 
Callback or XtNcommandCallback. All widgets also have the callback Xt- 
NdestroyCallback, which is called when the widget is destroyed. Scrollbar widgets 
often have at least two callbacks in addition to XtNdestroyCallback; in the Athena set 
these are called XtNscrollProc and XtNthumbProc, and they are called, respectively, 
when the user clicks in the scroll area or drags the thumb. 
The third argument of XtAddCallback is the function the widget is to call, and the last 
argument is any data to be passed to the callback function. No data is to be passed to Quit. 

44 X Toolkit Intdnsics Programming Manual 



A simple example that shows the power of actions is to replace the Quit callback function 
shown in Example 2-2 with two separate quit actions, one of which prompts the user for con- 
firmation, the other of which does not. As separate actions, these functions can be configured 
to respond to different events. Ideally, we'd like to emulate the Macintosh user-interface 
semantic, which allows a single click to select a button, which is then confirmed by a carriage 
return in response to a dialog box, while a double click performs the button's action right 
away, without confirmation. However, the way the Translation Manager interprets event 
sequences, you cannot specify both a single and double click for the same widget if you want 
them to execute mutually exclusive functions (i.e., unless you don't mind the single-click 
action being executed in addition to the double-click action whenever you double click). 
Instead, we'll have the confirm action respond to a click of the first pointer button, and quit 
without confirmation in response to the second. 

Here's the complete code for xfarewell.c. 

Examp 2-5. xrewec: comp code 
* xfarewell.c - simple program to provide a Command widget 
* that performs a different action in response to a 
* click of the first and second pointer buttons. 
./ 

#include <stdio.h> 
/. 
* Include files required for all Toolkit programs 
./ 
#include <Xll/Intrinsic.h> /* Intrinsics Definitions */ 
#include <Xll/StringDefs.h> /* Standard String definitions */ 
/. 
* Public include file for widgets we actually use in this file. 
./ 
#include <Xll/Xaw/Command.h> /* Athena Command Widget */ 

* 
* Confirm action 
./ 
/*ARGSUSED*/ 
static void Confirm(w, event, params, num_params) 
Widget w; 
XButtonEvent *event; 
String *params; 
Cardinal *num_params; 
{ 
/. 
* Once we show how to do it, we could pop-up a dialog box to do this. 
* Since we haven't yet, simply print a message to stderr. 
./ 
fprintf(stderr, "Are you sure you want to exit?\n\ 
Click with the middle pointer button if you're sure.\n"); 

* 
* Quit action 
./ 
/*ARGSUSED*/ 
static void Quit(w, event, params, num_params) 

46 X Toolkit Intrinsics Programming Manual 



Example 2-5. xfarewell.c: complete code (continued) 

Widget w; 
XButtonEvent *event; 
String *params; 
Cardinal *num_params; 
{ 
"It was nice knowing you.ln"); 

fprint f (stderr, 
exit ( 0 ) ; 
} 
main(argc, argv) 
int argc; 
char **argv; 
{ 

XtAppContext app_context; 
Widget topLevel, farewell; 
static XtActionsRec two_quits[] = { 
{"confirm", Confirm}, 
{"quit", Quit}, 
}; 
topLevel = XtVaAppInitialize( 

&app_context, 
"XFarewell", 
NULL, 0, 
&argc, argv, 
NULL, 
NULL); 

/* Application context */ 
/* Application class */ 
/* command line option list */ 
/* command line args */ 
/* for missing app-defaults file */ 
/* terminate varargs list */ 

farewell = XtVaCreateManagedWidget( 
"farewell", /* arbitrary widget name */ 
commandWidgetClass, /* widget class from Command.h */ 
topLevel, /* parent widget*/ 
NULL) ; /* terminate varargs list */ 
XtAppAddActions (app_context, two_quits, XtNumber (two_quits)) ; 
/* 
* Create windows for widgets and map them. 
*/ 
XtRea i i zeWidget (topLeve i ) ; 
/* 
* Loop for events. 
*/ 
XtAppMainLoop (app_context) ; 
} 
In Example 2-5 above, we have dispensed entirely with the use of the Command widget's 
callback. Instead, we have implemented two separate application functions, Confirra and 
Quit, that will be registered as actions of the Command widget. To make the actions avail- 
able, you must declare an actions table, which maps strings that the user can specify in a 
translation table to function pointers. 
You must register the actions table with Xt by calling XtAppAddActions. (The Xt- 
Number call counts the number of entries defined in the actions table--you will see this 
macro often.) You should also create a default translation table and store it in the 
application-defaults file. 

Introduction to the X Toolkit 47 



Examp 2-& Code Fragment specifying transitions  e progm 
static char defaultTranslations[] = "#override\n\ 
<BtnlDown>,<BtnlUp>: confirm()\n\ 
<Btn2Down>: set()\n\ 
<Btn2Down>,<Btn2Up>: quit()"; 
XtTranslations mytranslations; 

mytranslations = XtParseTranslationTable(defaultTranslations); 
XtOverrideTranslations(farewell, mytranslations); 

As mentioned earlier, you will find it more convenient to place the translation table in the 
application-defaults file until the last minute, because this allows changes without recompil- 
ing the source. 

2.5 More About Resources 

You now have read about enough techniques to construct an application that uses widgets for 
its user interface and connects the widgets to application code. However, in order to really 
take advantage of any widget class, you have to learn about its resources, so that you can set 
the desired resources in the application-defaults file. 

A class defines its own resources and also inherits the resources of all its superclasses. For 
example, Command supports not only its own resources but also the resources of its super- 
classes, Label and Core. The documentation for a widget class may describe only the 
resources for that class and list the name of the superclass (which you can then look up), or it 
may list all the resources of that class and all superclasses. 

2.5.1 

Setting and Getting Resources from the Application 

Resources are not just for customization of widgets at application startup. The application 
can change resources of widgets that have already been created, before or while the applica- 
tion is displayed. The application can also query the value of most resources. This section 
describes first how to set resources and then how to get them. 
Setting resources is perhaps most often used for resetting strings in Label widgets. This can 
be very useful, but you should be aware that setting a resource from the application wipes out 
the app-defaults or user-specified value for that same resource (if any), unless you first query 
the resource, and then set it based on its earlier value. It is especially important not to hard- 
code strings if you want to be able to change the language used by the application simply by 
changing app-default files. 
There are two parallel sets of functions that set or get resources. The two versions of each 
function have the same name except that one begins with xtva and the other with xt only. 
The arguments of both functions pass in or pass out resource name/value pairs, but they do it 
using a slightly different format of arguments. The xtva style uses an ANSI C varargs list, 

52 X Toolkit Intrinsics Programming Manual 



which is a NULL-terminated list of resource name/value pairs. The xt version takes an array 
of Arg structures (called an rgLis0 and an array length. Each Arg structure contains a 
resource name/value pair. We will call these two styles the varargs style and the argList 
style. The argList routines were the only interface until R4, and they can still be used. Using 
the argList form of call is slightly more efficient than the varargs form, since internally the 
varargs routines simply massage their arguments into the argList forms. However, using the 
argList form is somewhat more verbose, hard to read, and error-prone, and lacks some of the 
features supported by the varargs form. The loss of efficiency of the varargs form is probably 
insignificant unless you depend on maximum speed in setting or getting resources many 
times in a loop. We use the varargs interface in most of this book, but will also show you 
how to use the arglist form in the following sections so that you can understand existing 
applications written using them. 

The following sections demonstrate how to set and get resources of an existing widget using 
the arglist and varargs interfaces. The same form of arguments are used in many other func- 
tions that set resources for other purposes (usually while creating various types of widgets). 
Table 2-1 presents the parallel lists of functions. The final arguments of all of these (many of 
which have not yet been described) are used in exactly the same manner as is about to be 
shown. 

Table 2-1. Functions that Set Resources: arglist and varargs Counterparts 

ArgList 

XtSetValues 
XtGetValues 
XtCreateWidget 
XtCreateManagedWidget 
XtAppCreateShell 
XtGetSubresources 
XtGetApplicationResources 
XtCreatePopupShell 
XtSetSubvalues 
XtGetSubvalues 
XtAppInitialize 

Varargs 

XtVaSetValues 
XtVaGetValues 
XtVaCreateWidget 
XtVaCreateManagedWidget 
XtVaAppCreateShell 
XtVaGetSubresources. 
XtVaGetApplicationResources 
XtVaCreatePopupShell 
XtVaSetSubvalues 
XtVaGetSubvalues 
XtVaAppInitialize 

2.5.1.1 

Setting Resources with the Varargs Interfaces 

The easiest way to set and get resources is to use the Xt functions XtVaSetValues and 
XtVaGetValues. Each of these functions takes a widget argument and a variable length 
list of resource name/value pairs, terminated by NULL. These interfaces are new to R4. 
Example 2-9 shows the code needed to change the string of a Label widget--this will work 
any time after the widget has been created, either before or after the widget is realized. 

Introduction to the X Toolkit 53 



typedef struct { 
String name; 
XtArgVal value; 
} Arg, *ArgList; 

The definition of XtArgVal differs depending on architecture--its purpose is precisely to 
make code portable between architectures with different byte sizes. Its use in application 
code will be demonstrated in Section sargLists. All resource values (in all varargs and arg- 
List calls) are limited to the size of XtArgVal, which is the largest of char *, caddr_t, 
long, int *, and proc *. This means that for larger pieces of data, a pointer must be 
used. For example, data of type float or double must be passed as pointers. The docu- 
mentation for a widget class that declares a resource with a large value should document the 
fact that a pointer must be passed rather than the value itself. 

XtSetArg is a macro that makes it more convenient to set the two members of the Arg 
structure. If desired, you can also set the Arg structure members like any other C structure 
by using the. or -> syntax. 

Note that the first member of Arg is of type String, but should be set to one of the XtN 
constants defined in the header file for the widget whose resources are being set. 

XtSetValues is the call that actually changes the widget resource. You pass it the widget 
to be reconfigured, a list of Arg structures, and the length of the list. Example 2-9 sets only 
one resource, so the list length is 1. 

XtSetValues can set any number of resources of a single widget instance. Example 2-11 
shows the code necessary to set two resources. Compare this to Example 2-9 to see how 
much clearer the varargs interfaces are. 

Examp 2-11. Code fragment setmultip resouesofa widget 
static String new label = "Hi there." 
-- 
Arg args[3]; 
int i; 

i = 0; 
XtSetArg(args[i], XtNwidth, i00); i++; 
XtSetArg(args[i], XtNlabel, new label); i++; 
-- 
XtSetValues(w, argO, i) ; 
Note that the counter i cannot be incremented inside the XtSetArg macro, because that 
macro references its first argument twice. Therefore, the counter is customarily incremented 
on the end of the same line, so that additional resource settings can easily be added. 

Introduction to the X Toolkit 55 



2.5.1.3 Getting a Resource Value 

It is also useful to be able to get the current value of a widget resource. One use of this is to 
get the current size of a widget. Another use is in finding out what value the user has speci- 
fied for a particular resource, so that it can be modified with application data. Because C- 
language arguments are passed by value, and some resource values are not actual values but 
pointers to them, it is a little more difficult to get widget values than to set them. Example 
2-12 shows how to get a pointer to the current string in a Label widget, using the varargs 
interface. 

Example 2-12. Code fragment to get a widget resource using XtVaGetValues 
#define MAXLEN 256 

Widget hello; 
char userstring[MAXLEN]; /* memory allocated */ 
String p; /* NOTE - memory for array not allocated */ 

/* Label widget named hello created here. */ 
XtVaGetValues (hello, 
XtNlabel, &p, 
NULL) ; 
strcpy (userstring, p) ; 
The XtSetArg call sets the XtNlabel argument in the argument list to a pointer to the 
application variable p (which itself is a pointer), and then XtGetValues is called, which 
sets the pointer p to point to the widget's resource. The result is that the application knows 
the value of p and p points to the resource. 
This code may seem nonintuitive. However, since this method is the same for any resource, 
you can just remember it or look it up even if you don't understand it. 
When you query a resource value you are getting the actual address of the storage that Xt 
uses to store that value. Therefore, you should usually copy any values you have queried 
from a widget, because if you yourself later change the value pointed to by your variable, it 
will have unpredictable effects on the widget. For example, if after calling XtVaGet- 
Values you copy a new string into p, the Label widget will display the new string. The 
widget will remain the old width, however, regardless ofthe length of the new string, and if 
the new string is shorter than the old, the remainder of the old string will still be shown. Fur- 
thermore, if you change the same resource with a later call to xtvaSetValues elsewhere 
in the application, the value pointed to by your variable will also be changed even though 
your code never changed it. In short, don't change a queried resource valuemchange a copy 
of it. 
Example 2-13 shows how to query a widget resource using the arglist interface, XtGet- 
Values. 

56 X Toolkit Intfinsics Programming Manual 



Example 2-13. Code fragment to get a widget resource using XtGetValues 
#define MAXLEN 256 

Widget hello; 
Arg arg; 
char userstring[MAXLEN]; /* memory allocated */ 
String p; /* NOTE - memory for array not allocated */ 

/* Label widget named hello created here. */ 
XtSetArg(arg, XtNlabel, &p) ; 
XtGetValues(hello, &arg, I) ; 
strcpy (userstring, p) ; 
Note, however, that some resources are not designed to be queried. For example, translation 
tables and callbacks are compiled into an internal representation, so it is pointless to try to 
read them. 

2.5.2 

Core Resources 

All widgets are subclasses of Core. Therefore, the resources of the Core class are available 
for all widgets. Table 2-2 shows the Core resources. 
For each resource, both name and class strings are defined. Class strings are often the same 
as the corresponding resource name string, but with the prefix xtc instead of xtN, and with 
the first letter of the resource name capitalized. 
The use of resource classes allows the user or the application programmer to specify that all 
resources of a particular type be given the specified value. 

Table 2-2. Core Resources 

Name 

XtNx 
XtNy 
XtNwidth 
XtNheight 
XtNscreen 

XtNcolormap 

XtNdepth 

XtNbackground 
XtNbackgroundPixmap 
XtNborderWidth 

Class 

.XtCPosition 
XtCPosition 
XtCWidth 
XtCHeight 
XtCScreen 

XtCColormap 

XtCDepth 

XtCBackground 
XtCPixmap 
XtCBorderWidth 

Type 

Position 
Position 
Dimension 
Dimension 
Pointer 

Pointer 

int 

Pixel 
Pixmap 
Dimension 

Default 

0 
0 
0 
0 
from 
Display 
from 
parent 
from 
parent 
White 
NULL 
1 

Introduction to the X Toolkit 57 



Table 2-2. Core Resources (continued) 

Name 

XtNborderColor 
XtNborderPixmap 
XtNtranslations 
XtNaccelerators 
XtNmappedWhenManaged 
XtNdestroyCallback 
XtNsensitive 
XtNancestorSensitive 

XtCBorderColor 
XtCPixmap 
XtCTranslations 
XtCAccelerators 
XtCMappedWhenManaged 
XtCCallback 
XtCSensitive 
XtCSensitive 

Type 

Pixel 
Pixmap 
XtTranslations 
XtTranslations 
Boolean 
Pointer 
Boolean 
Boolean 

Default 

Black 
NULL 
NULL 
NULL 
TRUE 
NULL 
TRUE 
TRUE 

The fact that size and position are resources of all widgets means that your application-de- 
faults file can control the layout of the application. You should always resize widgets by set- 
ting these resourcesmnever resize or move a widget's window using Xlib calls since this 
would make Xt's knowledge of window geometries inaccurate. Nor should you use the Xt 
functions XtConfigureWidget, XtMoveWidget, or XtResizeWidget from e 
application. These routines are intended to be used only by geometry-managing composite 
widgets. 
The XtNscreen, XtNcolormap, and XtNdepth resources hold the default screen, 
colormap, and depth (the number of bits per pixel used for indexing colors in the colormap). 
The top-level shell widget gets the screen from the DISPLAY environment variable or 
-display command-line option; other widgets inherit that value and cannot change it. The 
top-level shell widget gets the root window's depth and default colormap; other widgets in- 
herit their parent's depth and colormap, so unless an intervening widget has set a different 
depth or colormap, a widget will have the root window's depth and colormap by default. 
Normally you will set the depth and colormap resources only on Shell widget and only when 
your application has special color requirements. 
The XtNbackground, XtNbackgroundPixmap, XtNborderWidth, Xt- 
NborderColor, and XtNborderPixmap widget resources control the background and 
border of the window created by a widget. The background and border of a window are 
maintained by the X server, and setting these resources causes an immediate change in the 
window on the screen. You can set either a background color or a background pixmap, but 
not both. Whichever is set later takes priority. The same applies to the border. 
A pixmap is similar to a window but is off-screen. It is an array of pixels. When used as a 
background or border, a pixmap is tiled by laying out multiple copies of it side by side, for 
the purpose of patterning. Pixmaps are also used for icon patterns, in drawing, and as a 
temporary drawing surface later copied to a window. 
The XtNbackground and XtNborderColor resources can be set using either a color 
name string or a hexadecimal color specification. (See Appendix B, Specifying Fonts and 
Colors, for more information on acceptable forms of color specification.) 

58 X Toolkit Intrinsics Programming Manual 



The value of the XtNbackgroundPixmap and XtNborderPixmap resources should 
be a pathname to a file containing the bitmap, or to a bitmap created in your program. On 
UNIX systems, standard X bitmaps are stored in the directory lusrlincludelXlllbitmaps. See 
Appendix F in Volume Three, X Window System User's Guide, for information on these 
standard bitmaps. 
XtNtranslations is the resource that contains the translation table described in Section 
2.4.2 above. As we demonstrated there, by setting this resource you can change the events 
that trigger a widget's actions or the actions your application has registered. Xt- 
Naccelerators contains an accelerator table. (Accelerators are an extended form of 
translations that allow events in one widget to be bound to actions in another.) 
XtNmappedWhenManaged is a resource used by geometry-managing widgets to specify 
whether a widget should be eligible for display (i.e., mapped to the screen) as soon as it is 
placed under parental geometry management, or whether this should not happen until some 
later time. We'll talk more about this concept in Chapter 11, Geometry Management. 
The XtNdestroyCallback resource, as described in Section 2.4.1 above, lets you 
provide an application function to be called when a widget is destroyed. This is infrequently 
used, since the Toolkit normally handles the job of freeing widget data structures and any 
server resources. 
The XtNsensitive resource controls whether a widget responds to user input. This 
allows you to turn on or off user input in a certain widget at will. For example, if you have a 
Command widget whose command is not allowed at certain times, you would set Xt- 
Nsensitive to FALSE during the period the command is not allowed. The Command 
widget changes its own look to indicate that it is invalid. 
The XtNancestorSensitive resource specifies whether the widget's parent (or earlier 
ancestor) is sensitive. Sensitivity is propagated downward, such that if any ancestor is 
insensitive, a widget is insensitive. This resource will often be hardcoded by the application, 
since if set incorrectly by the user, it could make the application inoperable. 

2.5.3 Other Inherited Resources 

Besides the resources inherited from Core, a widget inherits resources from each of its 
superclasses. For example; theCommand widget used in xfarewell inherits resources from its 
superclass, the Label widget class, and from Label's superclass, Simple. As shown in Table 
2-3, these include, in addition to the label itself, a font, a foreground color, spacing above and 
below the string, and a value specifying how the string should be placed in the widget (Note 
that there are other resources not listed.) 

Introduction to the X Toolkit 59 



Table 2-3. Label Resources 

Name 

XtNfont 
XtNforeground 
XtNinternalHeight 
XtNinternalWidth 
XtNjustify 
XtNlabel 

Class 

XtCFont 
XtCForeground 
XtCHeight 
XtCWidth 
XtCJustify 
XtCLabel 

XFontStruct* 
Pixel 
Dimension 
Dimension 
XtJustify 
String 

Default 

XtDefaultFont 
XtDefaultForeground 
2 
4 
XtJustifyCenter 
NULL 

It is a worthwhile exercise to experiment with the resources available to an application 
through its widgets, even with such a simple example as xgoodbye or xfarewell. For 
example, consider the resource settings for xfarewell shown in Example 2-14.* 

Examp 2-14. Aemate resource seings r xrewe# 
! Core resources 
! The following two lines don't work, but demonstrate a point 
*farewell.x: i00 
*farewell.y: i00 
! Even though the following specification syntactically applies to 
! all widgets in the application, and all windows have borders, the 
' borderWidth resource value is only used by certain widgets. 
! Command is not one of them, so this instruction is ignored. 
*borderWidth: i0 
*farewell.width: 200 
*farewell.height: i00 
*farewell.translations: #override\n\ 
Shift<BtnlUp>: quit()\n\ 
<BtnlDown>,<BtnlUp>: confirm() 
! Label resources 
*farewell.foreground: blue 
*farewell.font: helvetical6b 
*farewell.label: Click on me. 

Note that an exclamation point (!) in column zero begins a comment line in a resource file. 
The number sign (#), the standard UNIX comment symbol, should not be used. 

These settings can either be placed in an .Xdefaults file in your home directory, or you can 
save them in any file you like and load them into the server using the xrdb client, as follows: 

xrdb -merge resource file 
-- 

*See Appendix B, Specifying Fonts and Colors, for more information on the font resource specification shown in the 
example. 

60 X Toolkit Intrinsics Programming Manual 



(If you want to repeat the experiment with different values, you should be aware that once 
resources are set with xrdb, they remain in effect. Subsequent invocations of xrdb -merge 
will replace settings for the same resources, but won't remove any others that were set 
before. To start with a clean slate, use xrdb -load instead. Note, however, that this will 
replace all of your resource settings, including those for other applications. See Chapter 9 of 
Volume Three, X Window System User's Guide, for more information on using xrdb. See 
Chapter 9 of this book for more information on other possible sources of resource settings.) 

The window that results when you run xfarewell with these resource settings is shown in 
Figure 2-13. 

Figure 2-13. xfarewell run with new resource settings 

If you spend some time playing with different resource settings, you will find some 
unexpected behavior. For instance, setting the value of the x and , resources has no effect 
Regardless of their value, the xfarewell application is simply placed at the current pointer 
position. 
The reason for this is that these resources set the widget position relative to its parent, and 
since the fareraell widget is a child of an identically sized Shell widget, they are 
meaningless. In its geometry-management policy, the shell widget ignores the value of these 
resources. 

Introduction to the X Toolkit 61 



3 

More Techniques for Using Widgets 

This chapter describes how to use some of the more complex widgets found 
in applications, including composite widgets, constraint widgets, and pop ups. 
It also describes how to define application resources and command-line 
options, and how to hardcode the value of widget resources when you create 
a widget. 

In This Chapter: 

Using Composite Widgets .................................................................... 65 
Setting Resources for an Instance Hierarchy ................................... 68 
Geometry Management in Practice .................................................. 69 
Using Constraint Widgets .................................................................... 72 
Using Pop Ups .................................................................................... 75 
More About Callbacks .......................................................................... 81 
Passing Data to Callback Functions ................................................. 81 
Callback Lists .................................................................................. 84 
Application Resources ......................................................................... 85 
The Application Data Structure ........................................................ 86 
The Resource .List ........................................................................... 86 
Getting the Resources ..................................................................... 90 
Command-line Options ........................................................................ 91 
Standard Command-line Options ..................................................... 91 
Defining Your Own Command-line Options ...................................... 93 
Preventing User Customization of Widget Resources .......................... 97 
Using the Varargs Interfaces ............................................................ 97 
Using the Argument List Interfaces .................................................. 99 
Another Way to Set Arguments .................................................... 100 
Merging Argument Lists ............................................................... 102 
More About Application Contexts ....................................................... 102 



I Press Me I 

Figure 3-1. xbox 1: appearance on the screen 

Example 3-1. xboxl.c: complete code 
I* 
* xboxl.c - simple button box 
*/ 

/* 
* So that we can use fprintf: 
*/ 
#include <stdio.h> 

* Standard Toolkit include files: 
*/ 
#include <Xll/Intrinsic.h> 
#include <Xll/StringDefs.h> 
/* 
* Public include files for widgets used in this file. 
*/ 
#include <Xll/Xaw/Command.h> 
#include <Xll/Xaw/Box.h> 

/* 
* quit button callback function 
*/ 
/*ARGSUSED*/ 
void Quit(w, client_data, call_data) 
Widget w; 
XtPointer client data, call data; 
_ -- 
{ 
exit(0); 

/* 
* "Press me!" button callback function 
*/ 
/*ARGSUSED*/ 
void PressMe(w, client_data, call_data) 
Widget w; 
XtPointer client_data, call_data; 
{ 
fprintf(stderr, "Thankyou!\n") ; 

main(argc, argv) 

66 Xt Intrinsics Programming Manual 



Example 3-1. xboxl.c: complete code (continued) 

int argc; 
char **argv; 
{ 
XtAppContext app_context; 
Widget box, quit, pressme, topLevel; 

topLevel = XtVaAppInitialize( 
&app_context, 
"XBoxl", 
NULL, 0, 
&argc, argv, 
NULL, 
NULL); 
box = XtVaCreateManagedWidget( 
"box", 
boxWidgetClass, 
topLevel, 
NULL); 

/* Application context */ 
/* Application class */ 
/* command line option list */ 
/* command line args */ 
/* for missing app-defaults file */ 
/* terminate varargs list */ 

/* widget name */ 
/* widget class */ 
/* parent widget*/ 
/* terminate varargs list */ 

quit = XtVaCreateManagedWidget 
"quit", 
commandWidgetClass, 
box, 
NULL); 

( 
/* widget name */ 
/* widget class */ 
/* parent widget*/ 
/* terminate varargs list */ 

pressme = XtVaCreateManagedWidget( 
"pressme", /* widget name */ 
commandWidgetClass, /* widget class */ 
box, /* parent widget*/ 
NULL); /* terminate varargs list */ 

XtAddCallback(quit, XtNcallback, Quit, 0); 
XtAddCallback(pressme, XtNcallback, PressMe, 0) ; 
XtRealizeWidget (topLevel) ; 
XtAppMainLoop (app_context) ; 
} 
Example 3-1 creates a Box widget called box as a child of topLevel, and then creates 
each Command widget as" a child of box. Notice how the parent argument of each genera- 
tion of widgets is used. Also notice that the Shell widget topLevel is exactly the same 
size as box and therefore is not visible. 
If your application creates many children for a single widget, it may be preferable to create 
the children with XtVaCreateWidget, and then manage all the children of that parent 
with a single call to XtManageChildren (instead of calling XtVaCreateManaged- 
Widget for each child).* 

*Just a reminder that all statements about functions such as XtVaCreateWidget also apply to the other version 
of these same functions, such as XtCreateWidget, unless specifically stated otherwise. 

More Techniques for Using Widgets 67 



3.1.1 Setting Resources for an Instance Hierarchy 

You have already seen how an application-defaults file can set the string for a Command 
widget. However, xboxl contains two Command widgets, and a widget instance hierarchy 
that also includes a Box widgeL It is worth seeing how to set the Command widget labels in 
this new situation. (We will be returning often to the subject of setting resources, because it 
is so important to Toolkit programming. Each time, new ideas will be presented.) 

Example 3-2 shows an application-defaults file for xboxl. 

Example 3-2. XBoxl : application-defaults file 
*pressme*label : Press Me 
*quit*label : Quit 
*Command*background : green 
' The following entry would place the buttons side by side, 
' regardless of font. No setting makes the box widget wider than 
! all children side by side or narrower than the widest child. 
' *box. width: i000 
When an application contains multiple widgets of the same class, resource specifications can 
either identify individual widget instances by name or can use wildcards or widget class 
names to reference more than one widget. The first two entries in the example identify the 
pressme and quit widgets by instance name. The third entry uses the class name Com- 
mand to set the background of both Command widgets (but not the Box widget) to the color 
green. This line shows that resources of groups of widgets can be set at the same time. (The 
second asterisk in each specification is equivalent to a dot, because an asterisk matches zero 
or more intervening instances or classes.) Because we've used the class name, the back- 
ground color of all Command widgets in the application, even ones we add later, will be 
green. To make the Box widget green as well, we could have used an even more general 
specification such as *background: green. 
Note that you need to know the instance name for each widget in the application in order to 
set its resources individually. This is true for all resource files, including the ones customized 
by the user. Therefore, in the documentation for your application, be sure to include the 
name and class of each widget in your instance hierarchy. To be thorough, also include a 
description of the resources of each class, and specify which resources the user can custom- 
ize. 
The first argument of each XtVaCreateManagedWidget call is the widget instance 
name. This name can be used to set resources for this widget in the resource databases. The 
widget instance name is often the same as that of the variable of type Widget that holds the 
widget ID. This lexical connection is not mandatory, but it is highly recommended because it 
reduces confusion by helping you to remember the connection between entries in the applica- 
tion-defaults file and the widget instances in the application. 

68 Xt Intrinsics Programming Manual 



3.1.2 Geometry Management in Practice 

Build and run xboxl, and then try resizing it to see how the Box widget deals with various 
geometries. Two possibilities are shown in Figure 3-2. 

I Press I 

Figure 3-2. Two configurations of xboxl 

When you start up the xboxI application with its default size, you may notice that the Box 
widget initially places the widgets one above the other, but upon resizing it places them side 
by side if there is room. To have the buttons placed side-by-side by default, use resources to 
set the width of the button box to a value greater than the sum of the widths of the enclosed 
Command widgets. The commented-out entry in Example 3-2 would do the trick. 
Notice also that the effects of resizing from the window manager and resizing by setting the 
xbox:t, box. aS.dt:la resource are quite different. Using the window manager, you can 
resize the box to be smaller than the buttons, causing them to be clipped, or to be far larger 
than needed, so that they sit at the upper-fight corner of a large window. By using resource 
specifications, however, you can make the box large enough to hold the buttons side-by-side, 
but no larger. You cannot make it narrower than the width of the widest button, or shorter 
than the height of a button. 
Every widget's size and position is ultimately under the control of the window manager. A 
box widget attempts to make it.self just big enough to hold its children, using the resources 
provided by the application as a guide, but the window manager can override anything the 
widget or the application does. 
What happens when the user resizes an application is only part of the picture. The applica- 
tion itself may need to resize one of its widgets in order to display more widgets. Or the 
application may tell a widget to display more data and the widget will have to ask its parent 
to be resized. 
For example, what happens when the application changes the string in one of the Command 
widgets while the application is displayed? 
The Command widget attempts to resize itself to display the current string, by asking its par- 
ent for permission. Whether this request is granted depends on the position of the widget in 
the instance hierarchy, the resizing policy imposed by each composite widget in the hier- 
archy, and the window manager. This is because each widget, from the Command widget on 
up, negotiates with its parent when the Command widget requests a new size. If the Com- 
mand widget already has enough space, it changes the string and no geometry change is nec- 
essary. But if the Command widget tries to change size to accommodate the new string 

More Techniques for Using Widgets 69 



Figure 3-3. Results upon resize of Scmllbar widgets inside a Box widget 

More Techniques for Using Widgets 71 



3.3 Using Pop Ups 

Pop ups are widgets that are not visible until a certain user command is given, or a situation 
arises in which the program requires user input, and even then are visible for only a short 
period. The most common examples of pop ups are dialog boxes and menus. In general, a 
pop up gets information from the user and then goes away. 
Pop ups are not a kind of widget, but rather a way of using widgets. Any widget can be used 
as a pop up. You first create a special parent widget called a TransientShell or a Override- 
Shell as a child of topr.evel. Then you create the widget to appear in the pop up, which 
may be a simple widget or a composite widget with children. However, the TransientShell or 
OverrideShell widget, like the topr.evel widget created by XtVaAppTnitialize, 
must have only one child. 
This process sets up the pop-up widget, but does not put it on the screen. Somewhere in your 
code you need to call xtpopup to pop up the widget and xtPopdown when you want to 
make it invisible again (or use one of a number of other mechanisms for popping up or down 
widgets). This is typically done in callback or action routines. 
The xbox3 application shown in Example 3-5 adds a pop-up dialog box to xboxl. The actual 
widget popped up is an Athena Dialog widget. The Dialog widget is a widget designed to 
prompt for auxiliary input from a user. For example, you can use a Dialog widget when an 
application requires the user to enter some information such as a file name. A Dialog widget 
is actually just a special case of the Form widget. It provides a convenient way to create a 
"preconfigured form" useful for dialog boxes. 
The typical Dialog widget contains three areas. The first line contains a Label widget provid- 
ing a description of the function of the Dialog widget, for example, the string "Filename:". 
The second line contains a Text widget into which the user types input. The third line can 
contain one or more Command widgets that let the user confirm or cancel the Dialog input. 
(Other types of dialogs may just provide buttons to choose from.) The class variable for the 
Dialog widget is dialogWidgetClass. 
Figure 3-6 shows the appearance of xbox3 when the Dialog widget is popped up. 
Note that without proper resource settings in the application-defaults file, the text entry 
widget will not appear, a4a. d the buttons will have different text in them. Example 3-4 shows 
the required application-defaults file. 

Example 3-4. xbox3: application-defaults file 
*value : 
*pressme*label: Press Me 
*quit*label : Quit 
*dialog*label: Enter Text Below: 
*dialog*Command*label : Dialog Done 
The *value : resource setting tells the Dialog widget to provide a text entry widget but to 
give it no initial text. 

More Techniques for Using Widgets 75 



" Examp 3-5. Creating a pop-up diabg box ontued) 
* declared global as well. 
*/ 
Widget pshell, pressme, quit; 
/* 
* dialog button 
*/ 
void PopupDialog(w, client_data, call_data) 
Widget w; 
XtPointer client data; /* cast to topLevel */ 
-- 
XtPointer call data; 
-- 
{ 
Widget topLevel = (Widget) client_data; 
Position x, y; 
Dimension width, height; 
Arg arg[2]; 
int i; 
/* 
* get the coordinates of the middle of topLevel widget. 
*/ 
XtVaGetValues(topLevel, 
XtNwidth, &width, 
XtNheight, &height, 
NULL); 

/* 
* translate coordinates in application top-level window 
* into coordinates from root window origin. 
*/ 
XtTranslateCoords(topLevel, /* Widget */ 
(Position) width/2, /* x */ 
(Position) height/2, /* y */ 
&x, &y); /* coords on root window */ 
/* move popup shell to this position (it's not visible yet) */ 
XtVaSetValues (pshell, 
XtNx, x, 
XtNy, y, 
NULL) ; 
/* 
* Indicate to user that no other application functions are 
* valid while dialog is popped up... 
*/ 
XtSetSensitive(pressme, FALSE) ; 
XtPopup (pshell, XtGrabNonexclusive) ; 
} 
/* 
* dialog done button 
*/ 
void DialogDone(w, client data, call data) 
_ -- 
Widget w; 
XtPointer client data; /* cast to dialog */ 
-- 
XtPointer call data; 
-- 
{ 

More Techniques for Using Widgets 77 



Examp 3-5. Creating a pop-up dialog box (contue 
Widget dialog = (Widget) client data; 
-- 
String string; 
XtPopdown(pshell); 
XtSetSensitive(pressme, TRUE); 
string = XawDialogGetValueString(dialog); 
printf("User typed: %s\n", string); 
) 
/* 
* quit button callback function 
*/ 
void Quit(w, client data, call data) 
-- _ 
Widget w; 
XtPointer client_data, call_data; 
{ 
exit (0) ; 
) 
main(argc, argv) 
int argc; 
char **argv; 
( 
XtAppContext app_context; 
Widget box, topLevel, dialog, dialogDone; 
/* XtAppInitialize, create box, quit, etc. */ 
pressme = XtVaCreateManagedWidget( 
"pressme", 
commandWidgetClass, 
box, 
NULL); 

/* widget name */ 
/* widget class */ 
/* parent widget*/ 
/* terminate varargs list */ 

pshell = XtVaCreatePopupShell( 
"pshell", /* widget name */ 
transientShellWidgetClass, /* widget class */ 
topLevel, /* parent widget*/ 
NULL); /* terminate varargs list */ 
dialog = XtVaCreateManagedWidget( 
"dialog", 
dialogWidgetClass, 
pshell, 
NULL); 
dialogDone = XtVaCreateManagedWidget( 
"dialogDone", 
commandWidgetClass, 
dialog, 
NULL); 
/* callback for quiting application */ 
XtAddCallback(quit, XtNcallback, Quit, 0); 
/* callback for popping down dialog */ 
XtAddCallback(dialogDone, XtNcallback, DialogDone, dialog); 
/* callback for popping up dialog */ 

78 Xt Intrinsics Programming Manual 



Example 3-5. Creating a pop-up dialog box (continued) 
XtAddCallback(pressme, XtNcallback, PopupDialog, topLevel) ; 
XtRealizeWidget (topLevel) ; 
XtAppMainLoop ( app_context ) ; 
} 
The pop-up shell widget is created by a call to XtVaCreatePopupShell rather than 
XtVaCreateManagedWidget. The arguments of these two functions are the same, 
however. The widget class is specified as transientShellWidgetClass for dialog 
boxes, and overrideShellWidgetClas for menus. The difference between these 
two classes is that they are treated differently by the window manager, as will be described 
further in Chapter 12, Menus, Gadgets, and Cascaded Pop Ups. 
Note that you must include <Xll/Shell.h> to create a TransientShell or OverrideS hell widget. 
The Shell class actually has several subclasses, each with slightly different characteristics. 
For convenience, all of Shell's subclasses use the same header file. The subclasses of Shell 
other than ApplicationShell (returned by XtVaAppInitiali ze), TransientShell (used for 
dialog boxes), and OverrideShell (used for menus), are described in Section 13.7. 
It is often helpful for some or all of the widget IDs involved in pop ups to be global variables 
in the application. As we will see in the discussion of passing data to callback functions, it is 
awkward to pass more than one piece of data into any one callback function (one has to cre- 
ate a structure containing them and pass the pointer to the structure). When two or more 
widget IDs are used in any callback, it is simplest to declare one or more of them global. In 
Example 3-5, pshell, pressme, d quit are decked global. 
The Dialog widget is a compound widget--it creates its own widget children in addition to 
letting the application add children. Its purpose is to make it easier to combine existing 
widgets in a standard, useful way. It is really a subclass of the Form widget, to which a Label 
widget child is added to tell the user the purpose of the box and, with certain resource values, 
an Athena Text widget child is added for text entry. 
Ideally, the Text widget should provide a callback (which could be used to provide the data 
the user entered and popdown the dialog box) when the user types the Return key. Many 
applications add this missing feature by overriding the translation for the Return key in the 
Text widget, or by displaying a Command button to provide the callback. 
The Label widget and Text widget are automatically created as part of the Dialog widget. 
You have to explicitly create the Command widget as a child of the Dialog widget. The Dia- 
log widget does, however, automatically set the constraint resources that Form uses to place 
and size the Command widget. The callback function called by this Command widget is 
called DialogDone. 
The presume Command widget's callback function is called PopupDialog. Most of its 
code places the pop-up widget, because pop ups appear at the top left corner of the screen by 
default. This example centers the corner of the pop up in the top level widget of the applica- 
tion. Since pop up coordinates are relative to the corner of the root window, centering is a 
three-step process: 

More Techniques for Using Widgets 79 



See Chapter 9, Resource Management and Type Conversion, for a description of the standard 
representation types, as well as information on how to write your own converter routine. 

Example 3-11 shows the resource list for xbitmap, followed by a description of each of the 
fields in each entry. 

Examp 3-11. Theresource trxbitmap 
/* 
* The following could be placed in a "xbitmap.h" file. 
*/ 
#define XtNdebug "debug" 
#define XtCDebug "Debug" 
#define XtNpixmapWidthInCells "pixmapWidthInCells" 
#define XtCPixmapWidthInCells "PixmapWidthInCells" 
#define XtNpixmapHeightInCells "pixmapHeightInCells" 
#define XtCPixmapHeightInCells "PixmapHeightInCells" 
#define XtNcellSizeInPixels "cellSizeInPixels" 
#define XtCCellSizeInPixels "CellSizeInPixels" 
static XtResource resources[] = { 
XtNforeground, 
XtCForeground, 
XtRPixel, 
sizeof(Pixel), 
XtOffset(AppDataPtr, copy_fg), 
XtRString, 
XtDefaultForeground 
), 
XtNbackground, 
XtCBackground, 
XtRPixel, 
sizeof(Pixel), 
XtOffset(AppDataPtr, copy_bg), 
XtRString, 
XtDefaultBackground 
), 
XtNpixmapWidthInCells, 
XtCPixmapWidthInCells, 
XtRInt, 
sizeof(int), 
XtOffset(AppDataPtr, pixmap_width_in_cells), 
XtRImmediate, 
(XtPointer) 32, 

XtNpixmapHeightInCells, 
XtCPixmapHeightInCells, 
XtRInt, 
sizeof(int), 
XtOffset(AppDataPtr, pixmap_height_in_cells), 
XtRImmediate, 
(XtPointer) 32, 

More Techniques for Using Widgets 87 



3.5.3 Getting the Resources 

Once the application data structure and resource list are set up, you pass pointers to them to 
XtGetApplicationResources, just after calling XtAppInitialize. XtGet- 
ApplicationResources will search the databases for any matching resource settings 
and set the fields in the application data structure. 

The last requirement is that you check the values specified by the user to make sure they are 
acceptable. Example 3-12 shows these two steps from xbitmap4. 

Example 3-12. Calling XtGetApplicationResources and checking values 

AppData app_data; 

main(argc, argv) 
int argc; 
char *argv[]; 
( 
XtAppContext app_context; 
Widget toplevel, vpane, buttonbox, quit, output; 

/* call XtAppInitialize here */ 

XtVaGetApplicationResources(toplevel, 
&app_data, 
resources, 
XtNumber(resources), 
/* varargs list here for making 
* application resources 
* non-user-configurable */ 
NULL); /* terminate varargs list */ 

* We must check the application resource values here. 
* Otherwise, user could supply out of range values. 
* Conversion routines do this automatically, so 
* colors are already checked. 
*/ 
if ((app_data.pixmap_width_in_cells > MAXBITMAPWIDTH) II 
(app_data.pixmap_width_in cells < MINBITMAPWIDTH) 
(app_data.pixmap_height i cells > MAXBITMAPWIDTH) II 
(app_data.pixmap_height in cells < MINBITMAPWIDTH)) { 
fprintf(stderr, "xbitmap: error in resource settings:", 
"bitmap dimension must be between %d and %d cells\n", 
MINBITMAPWIDTH, MAXBITMAPWIDTH); 
exit(l); 
} 
if ((app_data.cell_size in pixels < MINCELLSIZE) 

90 Xt Intrinsics Programming Manual 



Example 3-12. Calling XtGetApplicationResources and checking values (continued) 

(app_data.cell_size_in_pixels > MAXCELLSIZE)) { 
fprintf(stderr, "xbitmap: error in resource settings:", 
"cell size must be between %d and %d pixels\n", 
MINCELLSIZE, MAXCELLSIZE); 
exit(l); 

} 
Only certain of the application resources need their values checked. Because Xt automati- 
cally converts the user's color specifications (such as "blue") into the form required by X, it 
warns the user when a color is specified improperly.* In this case, only the bitmap dimen- 
sions and cell size are checked, since they are critical to the application's operation. 

3.6 Command-line Options 

You already know that Xt automatically customizes widgets according to the resource data- 
base, but this is not the whole story. Users often expect command-line arguments for the 
most important aspects of an application. By default, XtAppTnitialize understands 
only a minimal set of command-line arguments; more need to be added so that application 
resources and certain widget resources can be set from the command line. 

There is no point, however, in trying to make every widget resource settable from the com- 
mand line, because that's the purpose of the resource database. You should concentrate on 
the resources that the user is most likely to want to have different between two simultaneous 
instances of the application (since it is difficult to arrange this with the resource database). 

Before describing how to define your own command-line arguments, we need to describe 
what command-line arguments XtAppInitiali ze already handles. 

Standard Command-line Options 

First of all, XtAppInitialize recognizes the -xrm option for setting any widget or 
application resource. For example: 
spike% x.hello -xrm ' *background: blue' 
This option is a little awkward. Not only is it long, but csh users must quote the suing with 
right-handed single quotes so that the * is not interpreted by the shell. 

*That is, if the resource in a database file is specified properly, but the value is not, Xt will warn the user. However, if 
the resource is not specified properly, Xt has no way of knowing that the resource was intended to specify a color, 
and therefore, no message will be issued. For example, "*background: grein" will elicit a warning message because 
green is misspelled, but "*backgruond: green" will not, because the resource identifier is misspelled. 

More Techniques for Using Widgets 91 



XtApplnitiali ze also understands some command-line options that were considered so 
basic that they should be the same for all applications. The above -xrm command line can be 
replaced by: 
spike% xhello -background blue 
or: 
spike% xhello -bg blue 
XtAppI n i t i a l i z e also understands any unique abbreviation of an option name, such as: 
spike% xhello -backg blue 
These resources will work with any application written using the X Toolkit--with any widget 
set. Try the command line above if you have a color screen. If not, try specifying a different 
font, using the -fn or -font option. 
Table 3-2 lists the complete set of standard options.* Resources starting with a dot rather 
than an asterisk indicate that that option affects only the application's top-level Shell. 

Table 3-2. Standard Command-line Parameters 

Option 

-background 
-bd 
-bw 
-borderwidth 
-bordercolor 
-display 
-fg 
-fn 
-font 
-foreground 
-geometry 
-iconic 
-name 
-reverse 
-rv 
+Iv 
-selectionTimeout 
-synchronous 

Resource 

*background 
*background 
*borderColor 
.borderWidth 
.borderWidth 
*borderColor 
.display 
*foreground 
*font 
*font 
*foreground 
.geometry 
.iconic 
.name 
*reverseVideo 
*reverseVideo 
*reverseVideo 
.selectionTimeout 
*synchronous 

Value 

next argument 
next argument 
next argument 
next argument 
next argument 
next argument 
next argument 
next argument 
next argument 
next argument 
next argument 
next argument 
"on" 
next argument 
lion,, 
"on" 
"off'" 
Null 

Sets 

background color 
background color 
border color 
width of border in pixels 
width of border in pixels 
color of border 
server to use 
foreground color 
font name 
font name 
foreground color 
size and position 
start as an icon 
name of application 
reverse video 
reverse video 
No Reverse Video 
selection timeout 
synchronous debug mode 

*There is no legitimate way for the application to access this parse table, which is necessary to show the user an error 
in a parameter. Furthermore, this table is in the source for Xt and therefore not available online to some Toolkit 
users. However, this parse table is not expected to change radically in new releases. Therefore it can probably be 
safely copied from this document into application code to provide a synopsis of valid options. Most current applica- 
tions simply say "This application understands all standard X Toolkit command-line options." 

92 Xt Intrinsics Programming Manual 



databases, it may apply to a single widget or to many widgets. If it applies to no widgets, 
no error message will be issued. 
The argument style. This field is one of seven constants describing how the opdon is to 
be interpreted. These constants are described below in Table 3-3. 
The value. This field is the value to be used for the resource if the argument style is 
XrmOptionNoArg. This field is not used otherwise. Note that this value must already 
be converted to the value expected for the resource (often not a string). You may be able 
to use Xt's type converter routines explicitly to convert this data to the right type (sec 
Section 9.3.5). 

The enum constants that specify the various command-line argument styles are as shown in 
Table 3-3. 

Table 3-3. XrmOptionKind: Command-line Option Style Constants 

Constant 

XrmoptionNoArg 

XrmoptionIsArg 

XrmoptionStickyArg 

XrmoptionSepArg 

XrmoptionResArg 

XrmoptionSkipNArgs 

XrmoptionSkipArg 
XrmoptionSkipLine 

Meaning 

Take the value in the value field of the options table. For 
example, this is used for Boolean fields, where the option 
might be -debug and the default value FALSE. 
The flag itself is the value without any additional information. 
For example, if the option were -on, the value would be "on." 
This constant is infrequently used, because the desired value 
such as "on" is usually not descriptive enough when used as 
an option (-on). 
The value is the characters immediately following the option 
with no white space intervening. This is the style of argu- 
ments for some UNIX utilities such as uucico where -sventure 
means to call system venture. 
The next item after the white space after this flag is the value. 
For example, -fg blue would indicate that "blue" is the value 
for the resource specified by -fg. 
The resource name and its value are the next argument in 
argv after the white space after this flag. For example, the 
flag might be: 
-res basecalc*background : white; 
then the resource name/value pair would be used as is. This 
form is rarely used because it is equivalent to -xrm, and 
because the C shell requires that special characters such as * 
be quoted. 
Ignore this option and the next N arguments in argv, where 
N is the value in the last field of this option table entry. 
Ignore this option and the next argument in argv. 
Ignore this option and the rest of argv. 

More Techniques for Using Widgets 95 



The options table is passed to XtAppInitialize as its third argument, and the number of 
options table entries as the fourth. The XtNumber macro is a convenient way to count the 
number of entries (this is only one of many contexts in which you'll see this macro used). 
Note that you cannot override the standard options by providing options with the same names 
in your own parsing table. If you try this, your options with the same names will simply not 
be set to the values specified on the command line. Instead, the standard options will be set 
to these values. This was a design decision in Xt, one of the few cases where a user-interface 
policy is enforced. Uniformity in this basic area was deemed more valuable than flexibility. 
Also note that there is no way to insU-uct Xt to interpret more than one argument format for 
the same option. For example, you cannot arrange for -size 3 and -size3 both to work. 
It is important to check whether there is more than one argument left after XtApp- 
Initialize has returned. XtAppInitialize conveniently removes from argc and 
a rgv the command-line arguments that it has already used to set resources. Command-line 
options that XtAppInitialize doesn't recognize will be left in argv and argc. This 
is your chance to catch this error and tell the user.* The Syntax function shown in 
Example 3-12 demonslrates code that informs the user of the proper syntax and the option 
that was not understood. (In response to incorrect command-line options, UNIX programs 
traditionally print only the correct calling sequence. However, you can be even nicer to the 
user by printing the option or options that were in error, by passing a rgv and a rgc into 
your Syntax function, as is done in Example 3-12. 
Experienced UNIX programmers will note that Xt applications can (but usually don't) use the 
single-letter command-line arguments mandated by POSIX and the System V Interface Defi- 
nition. As mentioned earlier, Xt automatically matches any unique abbreviation for any com- 
mand-line option. For example, by default the -display option can be specified as -d, but only 
if you haven't included any other option in the options table that also begins with d. You can 
define the meaning of single-letter options simply by including them verbatim in the options 
table. In other words, if you specify that -d turns on a debugging resource, Xt will no longer 
try to match any other, longer option that also begins with d. 
Note that the argc and argv arguments of XtAppInitialize are in the same order as 
in the call to main. This is the opposite order of arrays and array lengths throughout other 
Xt and Xlib routine calls. Also note that the address of a rgc, not a rgc itself, is passed to 
XtAppInitialize. This is so that XtAppInitialize can decrement the count to 
reflect recognized options. Watch out for these snags. 

*You can, of course, intentionally treat the arguments remaining after XtAppInitialize as filenames or other 
pieces of dta. 

96 Xt Intrinsics Programming Manual 



Example 3-14. The R4 varargs interface to creating a widget (continued) 

XtNjustify, XtJustifyCenter, 
XtNsensitivity, TRUE, 
XtNlabel, "Quit", 
NULL); 

} 
The standard varargs list entry is a resource name/value pair. XtVaTypedArg is a special 
symbol used just before a resource name, which, when encountered, indicates that the next 
four arguments specify a resource that needs to be converted. In Example 3-14, the value 
"red" needs to be converted into a pixel value, which is the index to the colormap register 
that contains the correct RGB values to display on the screen. The argument Xt- 
Nbackground is the resource to be set. XtRString is the type of the value to be con- 
verted. The final two arguments are the pointer to the value (or the pointer to the pointer to 
the value if not a string) and the size of the value pointed to in bytes. XtVaTypedArg can 
be used to convert any string that is valid in a resource file but is otherwise difficult to set in 
the source file. But don't use XtVaTypedArg unnecessarily, since it adds overhead. 
The varargs interfaces will also accept an arglist as one item in the list, using the symbol Xt- 
VaNestedList as the resource name. XtVaNestedList allows you to create one 
argument list and pass it to a series of widget creation routines, instead of listing all the same 
resource settings in each widget creation routine. For more details on this, see Chapter 
9, Resource Management and Type Conversion. 
There is some extra overhead involved in using the varargs interfaces because they massage 
the arguments into an argument list and call XtCreateWidget, XtCreateManaged- 
widget, XtSetValues, or XtGetValues. However, the added convenience seems 
worth it. Plus, the XtVaTypedArg feature is not supported in the arglist style of call. 
Unless you use the XtVaTypedArg feature, no diagnostic is printed when you specify a 
resource value incorrectly in the argument list. Therefore, make sure you specify the resource 
values correctly, and recognize this as a possible place to begin looking for bugs. (This is 
another reason to hardcode resources only when the application is almost ready for release. 
If you do it all at once in a methodical fashion, you are less likely to make mistakes than if 
you are always adding, subtracting, and changing values in the argument lists.) 

NOTE 

If you use the varargs style of arguments, but forget to type the Va in the func- 
tion name, you can get various types of errors. If you specify resources in the 
call, you will get a core dump at run time, but you can detect the problem with 
lint, which will note the function as having a variable number of arguments. If 
you don't specify resources in the call, the application will work but you will get 
the message: 
Warning: argument count > 0 on NULL argument list 

98 Xt Intrinsics Programming Manual 



3.7.2 Using the Argument List Interfaces 

Widget resources can also be hardcoded by creating an argument list containing the 
resources to be set and their values, and passing it to XtCreateManagedWidget. 
An argument list is just an array of/kEg structures, of the same type as you set up to call xt- 
SetValues or XtGetValues. Once set, this array is used as an argument to Xt- 
CreateManagedWidget. Each Arg structure contains a resource/value pair. Attributes 
specified here override the same ones specified from the command line or from resource data- 
bases. 
Example 3-15 shows an argument list that hardcodes the sensitivity of a Command widget 
and its callback list. The sensitivity is a good thing to hardcode for Command widgets, 
because if set by the user it could disable an application.* The callback list cannot be speci- 
fied by the user anyway; setting it here is just an alternative to calling XtAddCallback. 
The XtArgVal type used in the callback list aids in porting Toolkit programs to different 
architectures. It allows the system manufacturer to select the type in the typedef for Xt- 
ArgVal, so that the application program need not worry about it. The value field of the 
Arg structure may be a number or a pointer. 

Example 3-15. An argument list 
Arg quit_args [ ] = { 
XtNsensitive, (XtArgVal) TRUE, 
XtNcallback, (XtArgVal) quit callback list, 
}; 
An argument list can be used as an argument in the call to create a widget, as shown in 
Example 3-16. 

Example 3-16. Using an argument list in widget creation 
/* define quit_args */ 

main(argc, argv) 
int argc; 
char *argyll; 
{ 
Widget quit, box; 

/* create box */ 

quit = XtCreateManagedWidget( 
"quit", 
commandWidgetClass, 

/* widget name */ 
/* widget-class */ 

*Sensitivity is a basic resource of all widgets. When set to TRUE, the default, a widget accepts input and operates 
normally. When FALSE, a widget displays itself in gray (or otherwise indicates insensitivity) and does not act on 
user input. The purpose of sensitivity is to allow the application to disable certain commands when they are not val- 
id. If sensitivity were left configurable, the user could rum it off on some widgets and effectively cripple an applica- 
tion. It is hard to imagine the user doing this by accident, but it is not worth taking a gamble. 

More Techniques for Using Widgets 99 



Example 3-16. Using an argument list in widget creation (continued) 

box 
quit_args, 
XtNumber (quit_args) 
); 

/* parent widget*/ 
/* argument list*/ 
/* arglist size */ 

3.7.2.1 

} 
Notice the use of the XtNumber macro to calculate how many arguments there are in the 
statically initialized argument list. This macro eliminates the need to keep track of the num- 
ber of resources you have set. 
Note that the value field in the argument list must be in the correct representation type for 
that resource, which is often not a string. You may need to call XtConvertAndStore to 
arrive at the right representation of the data to be placed in the argument list. For details on 
calling XtConvertAndStore, see Chapter 9, Resource Management and Type Conver- 
sion. An easier way to do this is to use the XtVaTypedArg feature supported by the 
varargs interfaces. 
As mentioned earlier, unless you invoke a converter, no diagnostic is printed when you spec- 
ify a resource value incorrectly in the argument list. Therefore, make sure you specify these 
correctly. 

Another Way to Set Arguments 

Instead of creating the argument list as a static array, you can allocate storage at run time and 
use the XtSetArg macro to set values into the storage. XtSetArg Sets a single argument 
to a resource identifying a constant and a value. Example 3-17 shows the code that would 
create an argument list with the same contents as the one created in Example 3-15 above. 
Some people prefer this technique because it places the argument list Setting closer to the 
XtCreatewidget call, making the code easier to read. (However, it is still more difficult 
to read than when using the varargs interfaces.) 

Examp 3-1Z Seing e aumenttwith XtSe 
int i; 
Arg args[10]; 
/* XtAppInitialize may be called before or after the XtSetArg calls */ 

i = 0; 
XtSetArg(args[i], XtNcallback, 
XtSetArg(args[i], XtNsensitive, 

(XtArgVal) quit_callback_list); i++; 
(XtArgVal) TRUE); i++; 

banner = XtCreateManagedWidget( 
banner, /* widget name */ 
commandWidgetClass, /* widget class from Label.h */ 
toplevel, /* parent widget */ 
args, /* argument list */ 
i /* arg list size from XtSetArg counter */ 
); 

100 Xt Intrinsics Programming Manual 



3.7.2.2 Merging Argument Lists 

XtMergeArgLists lakes two argument lists and counts all arguments, allocates the stor- 
age for a single argument list big enough to hold them, and stores all the entries from both in 
the returned argument list. It does not remove duplicate entries. The calling application can 
use XtNumber to determine the resulting argument count (or can add the original counts). 

3.8 More About Application Contexts 

We have used application contexts in the examples so far, but not discussed what they really 
are or what they are for. 
An application context is a structure maintained by Xt that stores all the data associated with 
the application, including the functions registered by the application and other information 
about the application. Primarily, its purpose is to allow Xt applications to run without modi- 
fication on certain operating systems that do not have a separate address space for each pro- 
cess. These systems include the Xerox Cedar environment, the Symbolics Genera environ- 
ment, and the TI Explorer system. Although systems like this are not common, the goal of all 
X software in C is to be portable to any system that supports C.* 
Why then is the XtAppContext exposed in the programming interface? It is possible, 
though difficult, to create more than one application context within a single program. This is 
rarely done and its implications are complex, so we will reserve discussion of it until Section 
13.6. 
The important thing to remember is that, for maximum portability, you need to use the ver- 
sions of routines that begin with XtApp instead of those that don't. For instance, use Xt- 
AppInitialize instead 0fXtlnitialize. 
Of the routines you have seen so tar in this book, only XtVaAppInitialize, XtApp- 
Initialize, XtAppMainLoop, and XtAppAddActions use explicit application 
contexts. The complete list of routines that have equivalents is presented in Section 13.6. 
Throughout this book we will continue to use the routines that use the explicit application 
context. 

*It is almost a maxim that there is no such thing as portable software, only software that has been ported. The goal 
(and more or less the reality) of X is that the porting process should be much easier than it has traditionally been, and, 
most important, that only one version of a particular piece of software should need to be maintained. The various 
idiosyncrasies of particular compilers can be dealt with using conditional preprocessor directives (#ffdef). X features 
were designed specifically to provide ways to handle differences in screens and keyboards. The application context 
is an effort to provide a way to handle odd operating systems. 

102 Xt Intrinsics Programming Manual 



4 

An Example Application 

This chapter describes a complete application, in several iterations. First, it 
shows a simple version of the program, a bitmap editor, as it would be written 
assuming the existence of a BitmapEdit widget (which is actually developed 
in ). Then, two refined versions are developed, each demonstrating addi- 
tional Toolkit programming techniques. Finally, the same application is 
shown as it would be written if the bitmap editor were implemented in an 
application window rather than with the BitmapEdit widget. 

In This Chapter: 

xbitmapl" Bitmap Editor Using a BitmapEdit Widget ......................... 106 
Widget Public Functions ................................................................. 109 
Application-defaults File ................................................................. 109 
xbitmap2: Adding Scrollbars to Handle Large Bitmaps ...................... 109 
Overriding Translations .................................................................. 114 
Action Arguments in the Translation Table ...................................... 114 
The resize_thumbs Action .............................................................. 115 
Scrollbar Callbacks- 116 
xbitmap3: Adding Graphics to Display the Bitmap ............................. 118 
Graphics from the Application ........................................................ 121 
Writing a Bitmap File ...................................................................... 124 
xbitmap4: Bitmap Editor Without a BitmapEdit Widget ...................... 125 



4.1 xbitmapl- Bitmap Editor Using a BitmapEdit Widget 

The screen appearance of xbitmapl is shown in Figure 4-1. As usual, it is a good idea to 
compile and run each example as it is discussed.* 

Figure 4-1. xbitmap l : how it looks on the screen 

The BitmapEdit widget lets you set bits in the visible bitmap by clicking the first pointer but- 
ton or dragging the pointer with the first button held down, lets you erase bits using the sec- 
ond button, or lets you toggle bits using the third button. The "Print Output" button simply 
prints on the standard output an array of l's and O's representing the set and unset bits in the 
bitmap. (Code to read and write standard X11 bitmap files is added in a later version.) 
xbitmapl consists of only five widgets other than the top-level Shell; one Form, one Box, one 
BitmapEdit, and two Command widgets. The Form widget is the child of the Shell widget. 
One child of the Form widget is a Box containing the two Command widgets, and the other is 
the BitmapEdit widget. This arrangement of geometry-managing widgets keeps the appear- 
ance of the application neat even when the application is resized. 

*How to get and compile the example source code is described in the Preface and Section 2.3.2. 

106 X Toolkit Intrinsics Programming Manual 



Example 4-1. xbitmap l : complete code (continued) 

static XrmOptionDescRec table[] = { 
{"-pw", "*pixmapWidthInCells", XrmoptionSepArg, NULL}, 
{"-pixmapwidth", "*pixmapWidthInCells", XrmoptionSepArg, NULL}, 
{"-ph", "*pixmapHeightInCells", XrmoptionSepArg, NULL}, 
{"-pixmapheight", "*pixmapHeightInCells", XrmoptionSepArg, NULL}, 
{"-cellsize", "*cellSizeInPixels", XrmoptionSepArg, NULL}, 

]; 

topLevel = XtVaAppInitialize( 
&app_context, /* Application context */ 
"XBitmapl", /* Application class */ 
table, XtNumber(table), /* command line option list */ 
&argc, argv, /* command line args */ 
NULL, /* for missing app-defaults file */ 
NULL); /* terminate varargs list */ 
form = XtVaCreateManagedWidget("form", formWidgetClass, 
topLevel, NULL); 
buttonbox = XtVaCreateManagedWidget("buttonbox", boxWidgetClass, 
form, NULL); 
output = XtVaCreateManagedWidget("output", commandWidgetClass, 
buttonbox, NULL); 
/* callback added below after big bitmap is created */ 
quit = XtVaCreateManagedWidget("quit", commandWidgetClass, 
buttonbox, NULL); 
XtAddCallback(quit, XtNcallback, exit, NULL); 
bigBitmap = XtVaCreateManagedWidget("bigBitmap", 
bitmapEditWidgetClass, form, NULL); 
XtAddCallback(output, XtNcallback, Printout, bigBitmap); 
/* need the following values for the printout routine. */ 
XtVaGetValues(bigBitmap, 
XtNpixmapWidthInCells, &pixmap_width_in_cells, 
XtNpixmapHeightInCells, &pixmap_height_in_cells, 
NULL); 
XtReallzeWidget(topLevel); 
XtAppMainLoop(app_context); 
] 
You should recogze e command-le options ruble  e one described in Section 3.6.2. 
No that xbitmapl does not require application sourc, becau e is noing r them 
to L The widge emselves profide l needed resources. 

108 X Toolkit Intrinsics Programming Manual 



. .. 
.. :- ... ...... . .. ........ .:.: .. .. :.... 
[Print firral  

m 

Figure 4-2. xbitmap2: scrollbars added 

The easy way to add scrollbars is to use a widget provided just for this purpose, such as the 
Athena Viewport widget. Simply by inserting a Viewport widget into the instance hierarchy 
between the Form widget and the BitmapEdit widget and providing the right resource set- 
tings, scrollbars will appear around the BitmapEdit widget. This example program is 
included with the source distribution as xbitmap5, but is not described here because it is a 
simple improvement from xbitmapl. 
The Viewport widget, like the Dialog widget described in the last chapter, is really just a 
Form widget, two Scrollbar widgets, and the code to link them together. The window 
displayed is blank until you create a widget like BitmapEdit as a child of Viewport. This 
child can be a composite widget with children of its own, if desired.* 

*of course, it is also possible to create a widget similar to Viewport that combines BitmapEdit and scrollbars into a 
single unit. This widget could be a subclass of a geometry managing widget such as Form, and would create a 
BitmapEdit widget and the scrollbar widgets as children. It would add the code necessary to create the child widgets 
and link the scrollbars with BitmapEdit. This widget is described in Chapter 11, Geometry Management. 

110 X Toolkit Intrinsics Programming Manual 



independent action routines when the applicable translations are user-configurable (which 
they are not, in this case). Remember that since the translation table is a string, the argument 
placed in the translation table is passed to the action routine as a string. This argument, 
therefore, is basically a constant hardcoded into each translation table. It cannot be used in 
the same way that the c2i en t_da t a argument of callback functions can be used, to pass 
general data into an action routine. 

The action argument is not limited to a single string. You can place a series of words 
separated by spaces between the parentheses after an action in the translation table. These 
words will be passed into the action in the third argument, params, which is an array of 
strings just like argv. The fourth argument is the number of parameters, num_params, 
analogous to argc. (As mentioned earlier, for ANSI C Conformance it is important to 
declare the params and num_params arguments even if they are not used in the routine.) 
Also remember that translation tables must be compiled with XtParseTranslation- 
Table before passing them to XtOverrideTranslations, XtAugment- 
Translations, or in an argument list passed to xtSetValues. 

The resize thumbs Action 

Now, let's move on to the routine referenced in this translation table, resize thumbs. 
-- 
Example 4-4 shows this code. It simply sets the thumb of either scrollbar based on the cur- 
rent position of the data and the size of the BitmapEdit widget's window. 

Examp 4-4. xbmap2: rese_umbs routine 
/*ARGSUSED*/ 
static void 
Resize thumbs(w, event, params, num_params) 
-- 
Widget w; 
XEvent *event; 
String *params; 
Cardinal *num_params; 
{ 
String *orientation = (String *) params; 
Dimension width, height; 
int cur_x, cury; 
XtVaGetValues(bigBitmap, 
XtNheight, &height, 
XtNwidth, &width, 
XtNcurX, &cur_x, 
XtNcurY, &cur_y, 
NULL); 
if (*orientation[0] == 'h') 
XawScrollbarSetThumb(w, 
(float)cur_x/pixmap_width_in_pixels, 
(float)width/pixmap_width_in_pixels); 
else 
XawScrollbarSetThumb(w, 
(float)cur_y/pixmap_height_in_pixels, 
(float)height/pixmap_height_in_pixels); 

An Example Application 115 



Example 4-6. xbitmap3: implementing small pixmaps by drawing into Core widgets 
maln(argc, argv) 
int argc; 
char *argv[]; 
{ 
XtAppContext app_context; 
Widget toplevel, form, buttonbox, quit, output; 

static XtActionsRec window actions[] = { 
{"redraw_small._picture W, Redraw_small__picture} 
); 

String trans = "<Expose>: redraw_small_picture()"; 

blgBitmap = XtCreateManagedWidget("bigBitmap", 
bitmapEditWidgetClass, form, NULL, 0); 
XtAddCallback(bigBitmap, XtNcallback, cell_toggled, NULL); 
XtAppAddActions(app_context, window_actions, XtNumber(window_actions)); 

XtVaGetValues(bigBitmap, 
XtNpixmapHeightInCells, &pixmap_height in cells, 
XtNpixmapWidthInCells, &pixmap_width_in_cells, 
NULL); 
showNormalBitmap = XtVaCreateManagedWidget("showNormalBitmap", 
widgetClass, buttonbox, 
XtNwidth, pixmap_width in cells, 
XtNheight, pixmap_height_in_cells, 
XtNtranslations, XtParseTranslationTable(trans), 
NULL); 
showReverseBitmap = XtVaCreateManagedWidget("showReverseBitmap", 
widgetClass, buttonbox, 
XtNwidth, pixmap_width in cells, 
XtNheight, pixmap_height_in_cells, 
XtNtranslations, XtParseTranslationTable(trans), 
NULL); 
XtRealizeWidget(toplevel); 
XtAppMainLoop(app_context); 
} 
Con widge e eated using e class pointer widgetClass, raer an core- 
WidgetClass as you might have expected.* The include files r Con (and Composite 
and ConsainO are included by <Xllllntrinsics.h> and erere don't need  appe in e 
application. 
No at e size of e Con widget must be t bere e Con widge are reafized (either 
in e application or in e application-deul file), since e Con widget has a deult size 
of zero and Xt does not glow widge wi a size of zero. Hen we use xt SetArg to set e 

*As of Release 4, coreWidgetClass wig also work. 

120 X Toolkit Intrinsics Programming Manual 



size in the argument list used to create the widgets. The same argument list is used to create 
both widgets. 

The main routine aanges for the Redraw_small_picture routine to be called when- 
ever an Expose event arrives for either Core widget, and registers the cell toggled 
-- 
callback with the BitmapEdit widget. These routines depend on the setup performed in 
set_up_things. 

4.3.1 

Graphics from the Application 

Drawing in the X Window System is done by creating a graphics context (GC) that specifies 
such things as colors and line widths, and then calling a drawing routine that specifies what 
shape is to be drawn. These two steps are basic to X and required in programs written in any 
language with or without a toolkit. For example, the call to draw a line specifies only the 
start and endpoints of the line. The GC specifies everything else about how the server will 
actually draw this line. 
A GC is a server-side object that must be created by the application. The purpose of the GC 
is to cache on the server side information about how graphics are to be executed by the 
server, so that this information doesn't have to be sent over the network with every graphics 
call. If X did not have GCs, every graphics call would have many arguments and this would 
waste network time (and be annoying to program). Instead, you create a small number of 
GCs before drawing (in the startup phase of the application). Each represents a particular 
color or line style you will need to draw with at some point. You then specify one of these 
GCs in each call to draw. For example, to draw text and be able to highlight it at will, it is 
customary to create two GCs, one for drawing in white on black, and one for drawing in 
black on white (where colors can be substituted for black and white on color screens). 
Once created, a GC is referred to by its ID, of type GC. This ID is specified in calls to draw 
using that GC. 
From the application, the Xlib routine XCreateGC is usually used to create GCs. Xt also 
provides the XtGetGC routine for creating GCs, but it is typically used only inside widget 
code when there could be many of the same GCs created. XtGetGC is very similar to 
XCreateGC, except .that !t arranges for GCs to be shared among widgets (within one appli- 
cation). XtGetGC will be described in Section 6.1. 
Xt does not provide drawing calls of its own. You must call Xlib directly to draw. An Xlib 
drawing routine is known as a primitive. Under X, text is drawn by a graphics primitive, just 
as lines, arcs, and other graphics are drawn. 
Colors are normally specified by the user as strings such as "blue," but the X server under- 
stands colors only when specified as numbers called pixel values. A pixel value is used as an 
index to a lookup table called a colormap, which contains values for the RGB (red-green- 
blue) primaries used to generate colors on the screen. However, a particular pixel value does 
not necessarily always map to the same color, even when run twice on the same system, 
because the contents of the colormap are configurable on most color systems. The wide vari- 
ation of graphics hardware that X supports has required that the design of color handling in X 
be very flexible and very complex. 

An Example Application 121 



Note that BitmapEdit passes a structure called BitmapEditPointInfo into the callback 
function as an argument. This structure is defined in the public include file, BitmapE&'t.h, 
and it provides the information necessary to keep the small bitmaps displaying the same pat- 
tern as BitmapEdit. The fields of BitmapEditPointlnfo are the mode (whether drawn 
or undrawn) and the coordinates of the point toggled. The cell toggled routine draws 
points into the pixmaps according to the information pased in, and then calls 
Redraw_small__picture to copy the pixmaps into each Core widget. 
The first line of cell_toggled casts the generic pointer info into the structure type 
defined by BitmapEdit, BitmapEditPointlnfo. This can also be done (perhaps more 
clearly) by declaring the info argument as type BitmapEditPointlnfo in the first 
place. However, some programmers have a preference for using a cast. 

The Redra w_sma i l_pi ct u re routine is shown in Example 4-8. 

Examp 4-8. xb#map3: e Redraw_small_picture routine 
/*ARGSUSED*/ 
static void 
Redraw_small_picturew, event, params, num_params) 
Widget w; 
XEvent *event; 
String *params; 
Cardinal *num_params; 
{ 
Pixmap pixmap; 

if (w == showNormalBitmap) 
pixmap = normal_bitmap; 
else 
pixmap = reverse_bitmap; 
/* 
* Note that DefaultGCOfScreen is one plane on monochrome 
* screens, but multiple planes on color screens. The GCs 
* created in set_up_things are always single plane. 
*/ 
if (DefaultDepthOfScreen(XtScreen(w)) == i) 
XCopyArea(XtDisplay(w), pixmap, XtWindow(w), 
DefaultGCOfScreen(XtScreen(w)), 0, 0, 
pxmp_width in cells, pixmap_height_in_cells, 0, 0); 
else 
XCopyPlane(XtDisplay(w), pixmap, XtWindow(w), 
DefaultGCOfScreen(XtScreen(w)), 0, 0, 
pixmap_width in cells, pixmap_height in cells, 0, 0, 

This routine is cMled from cell_toggled and by Xt in response to Expose even 
because we registered it as an action and specified it in the translation table resource of each 
of the Core widgets. The use of one of two Xlib routines, depending on the depth of the 
screen, is an optimization. XCopyArea is faster, but can be used for this job only on mono- 
chrome displays, because the pixmaps used here are one plane deep on all displays and must 
be translated into muldple planes with xcopyt:,l a ne on color displays. 

i); 

An Example Application 123 



4.4 xbitmap4: Bitmap Editor Without a BitmapEdit Widget 

Many applications have at least one window that has certain characteristics not available in 
any existing widget class in any widget set. The small bitmaps added in the last section pro- 
vided a simple example of making a custom window by creating a Core widget and drawing 
into it from the application. 
Until you have experience working with widget code, it may be easier to prototype the "cus- 
tom window" for your application by adding to a Core widget using just the techniques 
described so far in this book. Once this code is working, and you have read Chapter 
5, Inside a Widget, and Chapter 6, Basic Widget Methods, you can easily move the code into 
a widget when you want to package it or take advantage of any of the features of Xt that are 
inaccessible from the application. 
The code for the BitmapEdit widget was originally wduen in an application, and later moved 
into a widget. In this section we describe this original application, a version of xbitrnap that 
works just like xbitmapl but without using the BitrnapEdit widget, xbi tmap4 is a culmina- 
tion of many of the techniques described so far in this book. In addition, you will be seeing 
this same code inside the BitmapEdit widget in Chapters 5 and 6, and it should be easier to 
understand the additional widget code when you have already seen the functional code 
described in a familiar setting. 
This example takes advantage of application resources to set the configurable parameters of 
the bitmap code. The code that sets up the application resources was described in Section 
3.5. When moving the code into a widget framework, the same resource list will be used ver- 
batim. The example also provides command-line options to set the important parameters of 
the bitmap code. The code for processing these options was described in Section 3.6. The 
code is the same whether used for setting application resources or widget resources, except 
no call equivalent to XtGetApplicationResources is necessary in a widget. 
The exposure strategy used for the bitmap editor is the same as for the small bitmaps in the 
previous section. The application creates a large pixmap of depth one that stores the current 
image of the bitrnap being edited. Whenever the screen needs updating, the applicable part 
of the pixmap is copied to the Core widget in the Redraw_picture routine. Because this 
pixmap is much bigger than the ones in the last section, it is an important optimization that 
only the required pans 'of the pixmap are copied. (This is not the only possible exposure 
strategy. This particular strategy has very low network load, but uses a relatively large 
amount of server memory. For this reason it is not ideal for PC servers.) 
The set_up_things routine creates the pixmap, draws a grid into it that will persist for 
the life of the application, and creates three GCs. One GC is for copying from the pixmap to 
the window, and two are for drawing and undrawing cells in the pixmap. The btn_event 
routine draws and undraws cells in the pixmap according to pointer clicks and drags, and 
calls Redraw_picture to update the Core widget display. 
Redraw_picture is called both from the application and from Xt. This is a common 
lick used to reduce the duplication of drawing code. Since Redraw_picture is an 
action, it has an event argument that is used by Xt to pass in the Expose event describing 
the area exposed. This application also uses this argument by constructing a fake event to 
pass in information about which part of the widget to draw. 

An Example Application 125 



The application adds actions and sets the XtNtranslations resource of the Core widget 
so that Xt calls the application routine Redraw_picture whenever Expose events 
anive, and calls btn_event when ButtonPress or MotionNotify events anive. 

Example 4-10 shows the complete code for xbitmap4. You have seen all the techniques here 
in various examples before. You should work through the code and make sure you under- 
stand the pmTose of each section. However, don't worry about the details of the Xlib calls, 
since they are specific to this application. 

Examp 4-10. xbitmap4:impmenting ebitmapeditorfrom eapplication 
/* 
* xbitmap4.c 
*/ 
#include <Xll/Intrinsic.h> 
#include <Xll/StringDefs.h> 
#include <Xll/Xaw/Paned.h> 
#include <Xll/Xaw/Box.h> 
#include <Xll/Xaw/Command.h> 

#include <stdio.h> 

The following could be placed in an "xbitmap.h" file. 

,/ 
#define 
#define 
#define 
#define 
#define 
#define 
#define 
#define 

XtNdebug "debug" 
XtCDebug "Debug" 
XtNpixmapWidthInCells "pixmapWidthInCells" 
XtCPixmapWidthInCells "PixmapWidthInCells" 
XtNpixmapHeightInCells "pixmapHeightInCells" 
XtCPixmapHeightInCells "PixmapHeightInCells" 
XtNcellSizeInPixels "cellSizeInPixels" 
XtCCellSizeInPixels "CellSizeInPixels" 

#define DRAWN 1 
#define UNDRAWN 0 

#define DRAW 1 
#define UNDRAW 0 

#define MAXLINES i000 

#define MINBITMAPWIDTH 2 
#define MAXBITMAPWIDTH I000 
#define MINBITMAPHEIGHT 2 
#define MAXBITMAPHEIGHT I000 
#define MINCELLSIZE 4 
#define MAXCELLSIZE I00 

#define SCROLLBARWIDTH 15 

Pixmap big_picture; 
GC draw_gc, undraw_gc; /* for drawing into the big_picture, 
* 1-bit deep */ 

GC copy_gc; 
Widget bitmap; 
char *cell; 
int cur_x, cur_y; 

/* for copying from pixmap into window, 
* screen depth */ 
/* drawing surface */ 
/* array for printing output and keeping 
* track of cells drawn */ 

126 X Toolkit Intrinsics Programming Manual 



Examp 4-1 xbitmap4: impmenting e bitmap editor from e application (continue 
XtOffsetOf(AppData, cell_size_in_pixels), 
XtRImmediate, 
(XtPointer) 30, 

XtNdebug, 
XtCDebug, 
XtRBoolean, 
sizeof(Boolean), 
XtOffsetOf(AppData, debug), 
XtRImmediate, 
(XtPointer) FALSE, 

/* Command-line options table */ 
static XrmOptionDescRec options[] = { 
{"-pw", "*pixmapWidthInCells", 
{"-pixmapwidth", "*pixmapWidthInCells", 

XrmoptionSepArg, NULL}, 
XrmoptionSepArg, NULL}, 

{"-ph", "*pixmapHeightInCells", XrmoptionSepArg, NULL}, 
{"-pixmapheight", "*pixmapHeightInCells", XrmoptionSepArg, NULL}, 
{"-cellsize", "*cellSizeInPixels", XrmoptionSepArg, NULL}, 
{"-fg", "*foreground", XrmoptionSepArg, NULL}, 
{"-foreground", "*foreground", XrmoptionSepArg, NULL}, 
{"-debug", "*debug", XrmoptionNoArg, "True"}, 

}; 

/* callback function to print cell array to stdout */ 
/* ARGSUSED */ 
static void 
Printout(w, event, params, num_params) 
Widget w; 
XEvent *event; 
String *params; 
Cardinal *num_params; 
{ 
int x, y; 
putchar('\n'); 
for (y = 0; y < app_data.pixmap_height in cells; y++) { 
for (x = 0; x < app_data.pixmap_width_in_cells; x++) 
putchar(cell[x + y * app_data.pixmap_width_in_cells] 
 'i' : '0'); 
putchar('\n'); 
} 
putchar('\n'); 

/* 
* It wouldn't be hard to write a function to convert from cell format 
* to one accepted by XWriteBitmapFile, and the reverse to import 
* such files. This is done in xbitmap3, where it is even easier. 
*/ 

static void RedrawPicture(), DrawCell(), UndrawCell(), ToggleCell(), 
DrawPixmaps(); 

static void Syntax(argc, argv) 
int argc; 

128 X Toolkit Intrinsics Programming Manual 



Example 4-1 xbmap4: implementing e bmap edor fmm e application (continue 
char * argv[]; 
{ 
int i; 
static int errs = False; 
/* first argument is program name - skip that */ 
for (i = i; i < argc; i++) { 
if (!errs++) /* do first time through */ 
fprintf(stderr, "xbitmap4: command line option not 
understood:\n"); 
fprintf(stderr, "option: %s\n", argv[i]); 
} 
fprintf(stderr, "xbitmap understands all standard Xt command\ 
line options.\n"); 
fprintf(stderr, "Additional options are as follows:\n"); 
fprintf(stderr, "Option Valid Range\n"); 
fprintf(stderr, "-pw MINBITMAPWIDTH to MAXBITMAPWIDTH\n"); 
fprintf(stderr, "-pixmapwidth MINBITMAPWIDTH to MAXBITMAPWIDTH\n"); 
fprintf(stderr, "-ph MINBITMAPHEIGHT to MAXBITMAPHEIGHT\n"); 
fprintf(stderr, "-pixmapheight MINBITMAPHEIGHT to MAXBITMAPHEIGHT\n"); 
fprintf(stderr, "-cellsize MINCELLSIZE to MAXCELLSIZE\n"); 
fprintf(stderr, "-fg color name\n"); 
fprintf(stderr, "-foreground color name\n"); 
fprintf(stderr, "-debug no value necessary\n"); 

main(argc, argv) 
int argc; 
char *argv[]; 
{ 

XtAppContext app_context; 
Widget topLevel, vpane, buttonbox, quit, output; 
extern exit(); 
/* translation table for bitmap core widget */ 
String trans = 
"<Expose>: RedrawPicture() 
<BtnlDown>: DrawCell() 
<Btn2Down>: UndrawCell() 
<Btn3Down>: ToggleCell() 
<BtnMo%ion>: DrawCell() 
<Btn2Motion>: UndrawCell() 
<Btn3Motion>: ToggleCell()"; 

\n\ 
\n\ 
\n\ 
\n\ 
\n\ 
\n\ 

static XtActionsRec window_actions[] = { 
{"RedrawPicture", RedrawPicture}, 
{"DrawCell", DrawCell}, 
{"UndrawCell", UndrawCell}, 
{"ToggleCell", ToggleCell], 
}; 

topLevel = XtVaAppInitialize( 
&app_context, /* Application context */ 
"XBitmap4", 
options, XtNumber(options), 
&argc, argv, /* command line args */ 
NULL, /* for missing app-defaults file */ 

An Example Application 

129 



Examp 4-10. xbitmap4: impmenting e bitmap editor from e application (continue 
NULL); /* terminate varargs list */ 
/* XtInitialize leaves program name in args */ 
if (argc > I) 
Syntax(argc, argv); 
XtGetApplicationResources(topLevel, 
&app_data, 
resources, 
XtNumber(resources), 
NULL, 
0); 

/* 

* We must check the application resource values here. 
* Otherwise, user could supply out of range values and 
* crash program. Conversion routines do this automatically, 
* so colors are already checked. 
*/ 
if ((app_data.pixmap_width in cells > MAXBITMAPWIDTH) II 
(app_data.pixmap_width_in_cells < MINBITMAPWIDTH) I 
(app_data.pixmap_height_in_cells > MAXBITMAPWIDTH)  
(app_data.pixmap_height_in_cells < MINBITMAPWIDTH)) { 
fprintf(stderr, "xbitmap: error in resource settings:\ 
dimension must be between %d and %d cells\n", 
MINBITMAPWIDTH, MAXBITMAPWIDTH); 
exit(l); 
) 
if ((app_data.cell_size_in_pixels < MINCELLSIZE) I I 
(app_data.cell_size in pixels > MAXCELLSIZE)) { 
fprintf(stderr, "xbitmap: error in resource settings:\ 
cell size must be between %d and %d pixelskn", 
MINCELLSIZE, MAXCELLSIZE); 
exit(l); 
) 
/* begin application code */ 
set_up_things(topLevel); 
cell = XtCalloc(app_data.pixmap_width_in_cells * 
app_data.pixmap_height_in_cells, sizeof(char)); 
if (app_data.debug) 
fprintf(stderr, "xbitmap: pixmap dimensions are %d by %d\n", 
app_data.pixmap_width in cells, 
app_data.pixmap_heigh i cells); 
vpane = XtVaCreateManagedWidget("vpane", panedWidgetClass, topLevel, 
XtNwidth, pixmap_width_in_pixels, 
NULL); 
buttonbox = XtCreateManagedWidget("buttonbox", boxWidgetClass, 
vpane, NULL, 0); 
output = XtCreateManagedWidget("output", commandWidgetClass, 
buttonbox, NULL, 0); 
XtAddCallback(output, XtNcallback, Printout, NULL); 
quit = XtCreateManagedWidget("quit", commandWidgetClass, 

130 X Toolkit Intrinsics Programming Manual 



Examp 4-1 xbmap4: impmenting He bmap edor from He application (continue 
buttonbox, NULL, 0); 
XtAddCallback(quit, XtNcallback, exit, NULL); 
bitmap = XtVaCreateManagedWidget(-bitmap-, widgetClass, vpane, 
XtNtranslations, XtParseTranslationTable(trans), 
XtNwidth, pixmap width in_pixels, 
XtNheight, pixma_heigt in .pixels, 
NULL); 
XtAppAddActions(app_context, window_actions, XtNumber 
(window_actions)); 
XtRealizeWidget(topLevel); 
XtAppMainLoop(app_context); 
set_up_things(w) 
Widget w; 
XGCValues values; 
int x, y; 
XSegment segment[MAXLINES]; 
int n_horiz_segments, n_vert_segments; 
pixmap_width_in_pixels = app_data.pixmap_width in cells * 
app_data.cell size in pixels; - - 
pixmap_height in pixeYs = ppZdata.pixmap_height in cells * 
app_data.cell_size_in_pixels; 
big_picture = XCreatePixmap(XtDisplay(w), 
RootWindowOfScreen(XtScreen(w)), 
pixmap_width_in_pixels, pixmap_height_in_pixels, i); 
values.foreground = i; 
values.background = 0; 
values.dashes = i; 
values.dash offset = 0; 
-- 
values.line_style = LineOnOffDash; 
draw_gc = XCreateGC(XtDisplay(w), big_picture, 
GCForeground  GCBackground  GCDashOffset  GCDashList 
GCLineStyle, &values); 
values.foreground = 0; 
values.background = i; 
undraw_gc = XCreateGC(XtDisplay(w), big_picture, 
GCForeground I GCBackground  GCDashOffset  GCDashList 
GCLineStyle, &values); 
values.foreground = app_data.copy_fg; 
values.background = app_data.copy_bg; 
copy_gc = XCreateGC(XtDisplay(w), RootWindowOfScreen(XtScreen(w)), 
GCForeground I GCBackground, &values); 
XFillRectangle(XtDisplay(w), big_picture, undraw_gc, 0, 0, 
pixmap_width in pixels, pixmap_height_in_pixels); 
/* draw permanent grid into pixmap */ 
n_horiz_segments = app_data.pixmap_height in cells + i; 
n_vert_segments = app_data.pixmap_width_in_cells + i; 

An Example Application 131 



Example 4-10. xbitmap4: implementing the bitmap editor from the application (continued) 

for (x = 0; x < n_horlz_segments; x += I) { 
segment[x].xl = 0; 
segment[x].x2 = plxmap_width in pixels; 
segment[x].yl = app_data.cell_slze_In_plxels * x; 
segment[x].y2 = app_data.cell_slze_In_pixels * x; 
} 
/* drawn only once into pixmap */ 
XDrawSegments(XtDisplay(w), blg_picture, draw_gc, segment, 
n_horlz_segments); 
for (y = 0; y < n_vert_segments; y += I) { 
segment[y].xl = y * app_data.cell_slze in pixels; 
segment[y].x2 = y * app_data.cell_size in pixels; 
segment[y].yl = 0; 
segment[y].y2 = pixmap_height_in_pixels; 
} 
/* drawn only once into pixmap */ 
XDrawSegments(XtDisplay(w), big_picture, draw_gc, segment, 
n_vert_segments); 
} 
/* ARGUSED*/ 
static void 
RedrawPicture(w, event, params, num_params) 
Widget w; 
XExposeEvent *event; 
String *params; 
Cardinal *num_params 
{ 
register int x, y; 
unsigned int width, height; 
if (event) { /* drawing because of expose or button press */ 
x = event->x; 
y = event->y; 
width = event->width; 
height = event->height; 
} 
else { /* drawing because of scrolling */ 
x = 0; 
y = 0; 
width = I0000; /* always the whole window! */ 
height = I0000; 
} 
if (DefaultDepthOfScreen(XtScreen(w)) == I) 
XCopyArea(XtDisplay(w), big_picture, XtWindow(w), 
copy_gc, x + cur_x, 
y + cur_y, width, height, x, y); 
else 
XCopyPlane(XtDisplay(w), big_picture, XtWindow(w), 
copy_gc, x + cur_x, 
y + cur_y, width, height, x, y, I); 

/* ARGUSED*/ 

132 X Toolkit Intrinsics Programming Manual 



Examp 4-10. xbmap4: impmenting the bmap edor fmm e applicatn (continue 
static void 
DrawCell(w, event, params, num_params) 
Widget w; 
XButtonEvent *event; 
DrawPixmaps(draw_gc, DRAW, w, event); 
/* ARGUSED */ 
static void 
UndrawCell(w, event, params, num_params) 
Widget w; 
XButtonEvent *event; 
String *params; 
Cardinal *num_params; 
DrawPixmaps(undraw_gc, UNDRAW, w, event); 
/* ARGUSED */ 
static void 
ToggleCell(w, event) 
Widget w; 
XButtonEvent *event; 
String *params; 
Cardinal *num_params; 
static int oldx = -i, oldy = -i; 
GC gc; 
int mode; 
int newx = (cur x + event->x) / app_data.cell_size_in_pixels; 
int newy = (cury + event->y) / app_data.cell_size_in_pixels; 
if ((mode = cell[newx + newy * app_data.pixmap_width_in_cells]) 
== DRAWN) { 
gc = undraw_gc; 
mode = UNDRAW; 
else { 
gc = draw_gc; 
mode = DRAW; . 
if (oldx != newx  I oldy != newy) { 
oldx = newx; 
oldy = newy; 
DrawPixmaps(gc, mode, w, event); 
/* Private Function */ 
static void 
DrawPixmaps(gc, mode, w, event) 
GC gc; 
int mode; 
Widget w; 
XButtonEvent *event; 

An Example Application 

133 



Example 4-10. xbitmap4: implementing the bitmap editor from the application (continued) 

int newx = (cur_x + event->x) / app_data.cell_size_in_pixels; 
int newy = (cur_y + event->y) / app_data.cell_size in pixels; 
XExposeEvent fake event; 
-- 
/* if already done, return */ 
if (cell[newx + newy * app_data.pixmap_width_in_cells] == mode) 
return; 
XFillRectangle(XtDisplay(w), big_picture, gc, 
app_data.cell_size_in_pixels*newx + 2, 
app_data.cell_size_in_pixels*newy + 2, 
(unsigned int)app_data.cell_size_in_pixels - 3, 
(unsigned int)app_data.cell_size_in_pixels - 3); 
cell[newx + newy * app_data.pixmap_width_in_cells] = mode; 
fake event.x = app_data.cell_size_in_pixels * newx - cur_x; 
-- 
fake event.y = app_data.cell size in pixels * newy - cur_y; 
_ -- 
fake event.width = app_data.cell size in pixels; 
_ -- 
fake_event.height = app_data.cell_size in pixels; 
RedrawPicture(bitmap, &fake event); 
-- 

134 X Toolkit Intrinsics Programming Manual 



5 

Inside a Widget 

This chapter describes the code inside a basic widget. Much of this code is 
common to all widgets.. You can think of it as a framework that Xt uses to 
implement a widget's features. After reading this chapter, you should under- 
stand the procedure for creating your own widget around this framework. 

In This Chapter: 

Widget Source File Organization ........................................................ 138 
The Private Header FilenBitmapEdiP.h ............................................ 138 
Parts and Records ......................................................................... 139 
Class Part and Class Record ......................................................... 140 
Instance Part and Instance Record ................................................ 141 
The Widget Implementation FilenBitmapEdit.c ................................. 143 
Obligatory Include Files .................................................................. 145 
Defining the Resource List ............................................................. 145 
The Translation Table and Actions Table ........................................ 148 
Declaring Methods ......................................................................... 150 
Initializing th.e Class Record ........................................................... 151 
The Core Class Part .................................................................... 151 
Initializing the Core Methods ........................................................ 153 
Description of Core Methods .......................................................... 155 
Packaging the Class Record for Application Use ............................ 157 
A Sample Method .......................................................................... 157 
The Public Header File--BitmapEdit.h ............................................... 160 
The Process of Widget Writing ........................................................... 163 
Summary of Conventions ................................................................... 164 



5 
Inside a Widget 

This chapter reveals the framework of code common to all widgets. As an example, it 
describes the code for the BitmapEdit widget that was used in versions of the xbitmap appli- 
cations early in Chapter 4, An Example Application. Later examples in that chapter 
described how to implement the bitmap editor without a BitmapEdit widget. Therefore, you 
have already seen the code that is specific to this widget, and can concentrate on the frame- 
work and how to place widget-specific code within this framework. 
Some applications use only the standard user interface elements defined in the widget set. If 
you are writing an application like this, you have no need to write your own widgets, and no 
real need to understand the internals of widgets. However, many applications have at least 
one custom window which has features not supported by any existing widget. To implement 
such features, you can add to a Core widget or you can write your own widget. 
Placing specialized user-interface code into a widget has several advantages. For one, the 
widget becomes a self-contained module that can be modified and documented separately 
and used in other programs. Second, the code will take advantage of Xt's automatic dis- 
patching of events to widgets, and several other features that you can't use from the applica- 
tion. Finally, it is a general premise of Xt that application code should be separated as much 
as possible from user-interface code. 
It is important to remember that widget classes are never written from scratch. People 
always start from template f'des that contain the frarnework for a widget without the specific 
code, or even better, if possible, from an existing widget that has some similar characteristics. 
Therefore, you'll never have to type in the framework you're about to see. You'll only have 
to learn where to insert your code into it. The beauty of the widget framework is that the 
code within it is very modular--each module has a specific place and purpose. Once you 
understand the framework, you can locate these modules in existing code and use them as 
examples. Chapter 6, Basic Widget Methods, shows you how to write the most important 
modules within the framework. 

Inside a Widget 137 



Core is the class upon which all widgets are based. It defines common characteristics of all 
widgets, such as their methods, and basic resources such as height and width. Even if your 
widget is unlike any existing widget, it will still inherit features from the Core widget. The 
class and instance structures of a subclass of Composite such as Box begin with the fields 
from Core, continue with fields from Composite, and end with the fields defined by Box. 
Composite and Conslraint are subclasses of Core that have additional methods that allow 
them to manage children; they are described in Chapter 11, Geometry Management. This 
chapter concentrates on the features of the Core widget. 
Xt requires that you implement each class's new fields as a separate structure called a part, 
and then combine this Part: structure with each superclass's Part: structure in the complete 
structure called a Rec, or record. In real code, these structures are called 
widgetnarneCa.aaaPart: and widgetnameCa.aaaRec for the class structure, and simply 
widgetname  a rt: and widgetnameRec for the instance structure. 
The reason for this "structure within a structure" design is primarily to reduce the changes in 
the code of subclasses that would be required if changes were made to the superclass's struc- 
tures. As we will see later, only the portion of the .c file that initializes the class structure 
will need changing if a superclass class structure is changed. A second benefit of this design 
is that it reduces the amount of typing required to implement a new class. 

5.2.2 Class Part and Class Record 

Let's make these ideas concrete by showing the class structure for BitmapEdit. The complete 
class structure is called Bit:mapEdit:C'lassRec, and the partial structure is called 
Bit:mapEdit:ClasaPart:. Their definitions from BitmapEdiP.h are shown in Example 
5-1. 

Example 5-1. BitmapEdiP.h: the class part and class record 
/. 
* BitmapEditP.h - Private definitions for BitmapEdit widget 
*/ 

/* protect against multiple including of this file */ 
#ifndef _ORABitmapEditP_h 
#define _ORABitmapEditP_h 
/* 
* This include not needed unless the .c file includes 
* IntrinsicP.h after this file. 
./ 
include <Xll/CoreP.h> 

/ 
typedef struct { 
int make_compiler_happy; 
} BitmapEditClassPart; 

Anyway, it doesn't hurt. 

* 
* This one is always needed! 
./ 
include "BitmapEdit.h" 
* New fields for the BitmapEdit widget class record */ 

/* need dummy field */ 

140 X Toolkit Intrinsics Programming Manual 



The compiler makes sure that the definition of the class record (in BitmapEdiP.h) and the ini- 
tialization of the class record (in BitmapEdit.c) use identical structures, since BitmapEdiP.h 
includes BitmapEdit.c. If a field is accidentally left out of the class structure in either file, the 
compiler will catch the problem (but if the same member is left out of both files, the problem 
won't be caught and Xt will likely dump core). 

BitmapEdiP.h contains an extern reference to the class structure initialized in Bitmap- 
Edit.c. This reference is shown in Example 5-3. 

Example 5-3. BitmapEdiP.h: declaring the external class record 
extern BitmapEditClassRec bitmapEditClassRec; 
Because the private header file includes the public header file, there is no obvious reason for 
this extern declaration. But since all widget code seems to have it, we go along with the 
convention. 

The naming conventions for the various structure declarations in the private header file are 
important, and can be confusing. A table summarizing the conventions for types and vari- 
ables in the widget implementation files is shown in Section 5.6 (after the contents of the .c 
and .h files are shown). 

That's all there is in the private header file! If you should need to refer back to the private 
header file for BitmapEdit, it is listed with the rest of the source for the widget in Appendix 
E, The xbitmap Application. 

5.3 The Widget Implementation File--BitmapEdit.c 

The central element of the .c file is the initialization of the class record. Remember that the 
typedef of the class record was declared in BitmapEdiP.h, but the record is allocated and 
the actual values in each field are set in BitmapEdit.c. When Xt takes over control of the 
widgets after the application calls XtAppNainr,oop, it is the values in this class record 
that supply Xt with all the information it uses to manage widget instances. 

The organization of the .c file is quite simple. First, it defines everything that will be placed 
into the class record, "and-then initializes the class record, setting fields using these defini- 
tions. The major things that need defining are the functions that implement each method, the 
resource list, the translation table, and the actions table. It would be logical to define these 
four things at the beginning of the source file, and then put the class record last. This is 
almost the case, except that by convention the methods and acdons are declared at the top of 
the source file and then defined at the end after the class record initialization. This actually 
makes the widget code clearer because the method declarations provide a complete list of the 
methods that will be defined later in the file, and the class record remains near the top of the 

Inside a Widget 143 



Examp 5- BitmapEd# resource list (continue 
XtRPixel, 
sizeof(Pixel), 
offset(bitmapEdit.foreground), 
XtRString, 
XtDefaultForeground 
}, 
{ 
XtNcallback, 
XtCCallback, 
XtRCallback, 
sizeof(XtPointer), 
offset(bitmapEdit.callback), 
XtRCallback, 
NULL 
}, 
{ 
XtNcellSizeInPixels, 
XtCCellSizeInPixels, 
XtRInt, sizeof(int), 
offset(bitmapEdit.cell_size_in_pixels), 
XtRImmediate, 
(XtPointer)DEFAULT CELL SIZE 
-- -- 
}, 
{ 
XtNpixmapWidthInCells, 
XtCPixmapWidthInCells, 
XtRDimension, 
sizeof(Dimension), 
offset(bitmapEdit.pixmap_width in cells), 
XtRImmediate, 
(XtPointer)DEFAULT PIXMAP WIDTH 
-- -- 
}, 
{ 
XtNpixmapHeightInCells, 
XtCPixmapHeightInCells, 
XtRDimension, 
sizeof(Dimension), 
offset(bitmapEdit.pixmap_height_in_cells), 
XtRImmediate, 
(XtPointer)DEFAULT PIXMAP HEIGHT 
-- -- 
}, 
{ 
XtNcurX, 
XtCCurX, 
XtRInt, 
sizeof(int), 
offset(bitmapEdit.cur x), 
-- 
XtRImmediate, 
(XtPointer) 0 
}, 
{ 
XtNcurY, 
XtCCurY, 
XtRInt, 
sizeof(int), 
offset(bitmapEdit.cur_y), 

146 X TooAk# Intrinsics Programming Manual 



Example 5-5. BitmapEdit's resource list (continued) 

XtRString, 
(XtPointer) NULL 
}, 
{ 
XtNcellArray, 
XtCCellArray, 
XtRString, 
sizeof(String), 
offset(bitmapEdit.cell), 
XtRImmediate, 
(XtPointer) 0 
}, 
{ 
XtNshowEntireBitmap, 
XtCShowEntireBitmap, 
XtRBoolean, 
sizeof(Boolean), 
ofset(bitmapEdit.showAll), 
XtRImmediate, 
(XtPointer) TRUE 
}, 
} 

The details of each field in a resource list entry will be presented in Chapter 9, Resource 
Management and Type Conversion. 
As mentioned earlier, a widget class inherits all the resources defined in the resource lists of 
its superclasses. If a resource is given the same name as a superclass resource, it overrides 
the superclass resource. The only reason to create a new resource with the same name as a 
superclass resource is to give it a new, subclass-specific default value. The type and offset 
should remain the same. 
When defining a resource list, use as many as possible of the constants defined in 
<Xll/StringDefs.h>. However, any constant unique to this widget class can be defined in the 
public include file, as will be described in the next section. 
Table 5-1 summarizes the conventions for the constants used in the resource list. 

Table 5-1. Resource List Constant Conventions 

Prefix 

XtN 
XtC 
XtR 

First word capitalization 

Lower 
Upper 
Upper 

Description 

Resource name 
Resource class 
Representation type 

The representation type of a resource is a string that represents the type in which the widget 
stores the resource value. Xt constants and functions of all types use upper case letters when- 
ever a word break might otherwise be called for. Two examples of resource names following 
this convention e XtNborderColor and XtNmappedWhenManaged. 

Inside a Widget 147 



5.3.5 Initializing the Class Record 

We've already shown you how to create the resource list, the translation table, and the 
actions table, and set into the class structure. A major part of the work is done. Now we just 
need to insert the method names we declared earlier into the class record, and set a few of the 
miscellaneous data fields. 

As we saw in the discussion of the private header file, the BitmapEdit class record includes 
class parts for BitmapEdit itself and for each superclass of BitmapEdit, in this case only 
Core. To initialize the class record, each class part has to be initialized field by field. But for 
simple (noncomposite) widgets this job comes down to initializing the Core class part, 
because few classes actually define new class part fields. 

5.3.5.1 

The Core Class Part 

Since all widget classes are subclasses of Core, all need to initialize the Core class part. 
Example 5-10 shows the core part initialized as needed by the BitmapEdit widget. The 
actual name of each field is shown in the comment at left. Each field will be discussed after 
the example. 

Example 5-10. BitmapEdit.c: initialization of Core class record 
BitmapEditClassRec bitmapEditClassRec = { 

{ 
/* core class fields */ 
/* superclass */ 
/* class name */ 
-- 
/* widget_size */ 
/* class initialize */ 
/* class_part_initialize */ 
/* class inited */ 
/* initialize */ 
/* initialize hook */ 
-- 
/* realize */ 
/* actions */ 
/* num actions */ 
/* resources */ 
/* num resources */ 
/* xrm class */ 
/* compress_motion */ 
/* compress_exposure */ 
/* compress_enterleave */ 
/* visible interest */ 
-- 
/* destroy */ 
/* resize */ 
/* expose */ 
/* set values */ 
/* set values hook */ 
/* set--values--almost */ 
/* get,values--hook_ */ 
/* accept_focus */ 
/* version */ 
/* callback_private */ 

(WidgetClass) &coreClassRec, 
"BitmapEdit", 
sizeof(BitmapEditRec), 
NULL, 
NULL, 
FALSE, 
Initialize, 
NULL, 
XtInheritRealize, 
actions, 
XtNumber(actions), 
resources, 
XtNumber(resources), 
NULLQUARK, 
TRUE, 
TRUE, 
TRUE, 
FALSE, 
Destroy, 
Resize, 
Redisplay, 
SetValues, 
NULL, 
XtInheritSetValuesAlmost, 
NULL, 
NULL, 
XtVersion, 
NULL, 

Inside a Widget 

151 



Xlib DoesBackingStore macro to determine whether this feature is 
supported on a particular screen on your server. 
Saving Under Provides hints about whether or not the screen area beneath a window 
should be saved while a window such as a pop-up menu is in place, to save 
obscured windows from having to redraw themselves when the pop up is 
removed. Not all servers can save under windows. You can find out 
whether this feature is supported on a particular screen with the Xlib 
DoesSaveUnders macro. 
Colormap Determines which vklual colormap should be used for this window. If 
your widget requires a lot of specific colors--for example, to draw a 
shaded image, it may need to create its own virtual colormap. In that case, 
it would set this attribute to the ID of the created colormap. For more 
information, see Chapter 7, Color, in Volume One, Xlib Programming 
Manual. 
Cursor Determines which cursor should be displayed when the pointer is in this 
window. You must create this cursor before setting this atwibute. This can 
be done with a standard type converter, as described in Chapter 13, Mis- 
cellaneous Toolkit Programming Techniques. 
It may clarify the picture to describe the features that window attributes do not affect. Set- 
ting the window attributes does not determine a window's parent, depth, or visual. These are 
all set when a window is created, and are permanent. The window attributes are also not 
used for setting the size, position, or border width of a widget. These are set using xtSet- 
Values. Window attributes do not determine how graphics requests are interpreted; this is 
the job of the graphics context (GC). 
Note that some of the window attributes are not listed here because they should not be set 
directly by widgets, in the realize method or anywhere else. These include the 
event_mask, which controls which events are sent to this widget. Xt itself sets this win- 
dow attribute based on the translation table. Another is override redirect, which is 
-- 
handled by the Shell widget. 
You could write a realize method that set your desired attributes and then called Xt- 
CreateWindow. But this is slightly wasteful, since Core already has a realize method 
that creates a window and you can take advantage of it. This is the second inheritance 
scheme used for self-contained fields. You define your own realize method just as if you 
were going to write it from scratch, but then you call the superclass's realize method directly, 
as shown in Example 5-13. 

Examp 5-1 her#ing by voking e supess meod from a widget meod 
#define superclass (&coreClassRec) 
static void Realize(w, valueMask, attributes) 
Widget w; 
XtValueMask *valueMask; 
XSetWindowAttributes *attributes; 
{ 
/* this is already set, but just for example */ 
*valueMask I = CWBitGravity; 

Inside a Widget 159 



Examp5-14. B#mapEd#.h: cidenldeclatns(continue 
* (from BitmapEdit) 
* foregroundPixel Foreground Pixel Black 
* backgroundPixel Background Pixel White 
* callback Callback Callback NULL 
* cellSize CellSize Int 30 
* pixmapWidth PixmapWidth Int 32 
* pixmapHeight PixmapHeight Int 32 
*/ 
/* 
* This public structure is used as call data to the callback. 
* It passes the x, y position of the cell toggled (in units of 
* cells, not pixels) and a mode flag that indicates whether the 
* cell was turned on (i) or off (0). 
*/ 
typedef struct { 
int mode; 
int newx; 
int newy; 
} BitmapEditPointInfo; 
#define XtNcellSizeInPixels "cellSizeInPixels" 
#define XtNpixmapWidthInCells "pixmapWidthInCells" 
#define XtNpixmapHeightInCells "pixmapHeightInCells" 
#define XtNcurX "curX" 
#define XtNcurY "curY" 
#define XtNcellArray "cellArray" 
#define XtNshowEntireBitmap "showEntireBitmap" 
#define XtCCellSizeInPixels "CellSizeInPixels" 
#define XtCPixmapWidthInCells "PixmapWidthInCells" 
#define XtCPixmapHeightInCells "PixmapHeightInCells" 
#define XtCCurX "CurX" 
#define XtCCurY "CurY" 
#define XtCCellArray "CellArray" 
#define XtCShowEntireBitmap "ShowEntireBitmap" 
extern char *BitmapEditGetArrayString(); /* w */ 
/* Widget w; */ 
/* Class record constants */ 
extern WidgetClass bitmapEditWidgetClass; 
typedef struct _BitmapEditClassRec *BitmapEditWidgetClass; 
typedef struct _BitmapEditRec *BitmapEditWidget; 
#endif /* _ORABitmapEdit_h */ 
/* DON'T ADD STUFF AFTER THIS #endif */ 
It is a good idea to comment e types of e resources for 1 supercsses as shown in 
Example 5-14. Not only is this a good summary for you of 1 e resoues of yo widget, 
but it glows e application programmer to use is file for documentation when creating 
gument lis. 

162 X Toolkit Intrinsics Programming Manual 



Table 5-3. Summary of Xt Structure Name Conventions (continued) 

Sumcture Name 

_BitmapEditClassRec 
BitmapEditWidget 

BitmapEditWidgetClass 

bitmapEditWidgetClass 

Description 

Type of BitmapEditClassRec, used for defining 
BitmapEditWidgetClass pointer in .h file. 
Pointer to BitmapEditRec (complete instance structure), 
used to reference instance structure fields in .c file (passed as 
argument to methods). 
Pointer to _BitmapEditClassRec, used to cast bitmap- 
EditClassRec for superclass in class record initialization of 
subclasses of this widget (.c file). 
Of type WidgetClass, address of bitmapEditClass- 
Rec, used in XCreateWidget calls to identify class to be 
created. 

Inside a Widget 

165 



6 

Basic Widget Methods 

This chapter describes the initialize, expose, set_values, resize, 
query_geometry, and destroy methods. It explains when Xt calls each 
method, and describes in detail what should be in each of these methods. 
Among other things, these methods prepare for and do the drawing of graph- 
ics that appear in a widget. This chapter describes what the Toolkit adds to 
the graphics model provided by Xlib, but does not describe in detail how to 
draw using Xlib; this topic is described in Chapters 5, 6 and 7 of Volume 
One, Xlib Programming Manual. This chapter also describes how to write 
action routines that work in the widget framework. 

In This Chapter: 

The X Graphics Model Inside Widgets ............................................... 170 
The initialize Method .......................................................................... 170 
Creating GCs ................................................................................. 172 
The expose Method ........................................................................... 175 
The set_values Method ...................................................................... 178 
The resize Method ............................................................................. 181 
The query_geonetry Method ............................................................. 184 
The destroy Method ........................................................................... 187 
Actions in the Widget Framework ....................................................... 188 



6.1 The X Graphics Model Inside Widgets 

Section 4.3.1 described the X graphics model and how drawing from the application is 
accomplished. In summary, the process consisted of creating GCs and then drawing from a 
function that Xt calls on receipt of Expose events. Drawing from inside a widget follows 
the same general procedure, but the code is organized differently. 
Inside a widget, you normally create GCs with the Xt routine XtGetGC instead of the Xlib 
routine XCreateGC. XtGetGC is similar to the Xlib routine except that it arranges for the 
sharing of GCs among widgets within an application. This is important because each GC has 
some overhead and servers can achieve better performance when handling fewer GCs. 
Because Xt applications often have many instances of the same widget class, each needing 
the same GC characteristics (unless the user specifies a different color for each one), Xt 
arranges for them to share GCs when possible. 
Xt organizes GC creation and drawing into separate methods. Setting initial values for the 
GC and creating the GC is done in the initialize method, and actual drawing is done in 
the expose method. This makes it very easy to find this code in existing widgets and 
straightforward to write this code for new widgets. 
Since Xt allows resources to be changed during program execution by calling xtvaSet- 
Values, the widget code must be prepared to change the GC at any time if the GC compo- 
nents depend on resource values. The set values method calculates the new values 
-- 
based on resource changes and updates the appropriate GCs. 
The next six major sections discuss the code needed to implement the initialize, 
expose, set_values, resi ze, query_geomet ry, and dest roy methods. 

6.2 The initialize Method 

As described in Section 5.3.5.2, the initialize method has basically one function: it 
sets instance structure members (also called instance variables).* This job has two pans: 
setting the initial values of private instance variables, and checking to make sure that the val- 
ues of the public instance variables are valid (since they are user configurable). Since the 
initialize method is upward chained (defined in Section 5.3.5.2), the method for this 
class needs to initialize only the fields present in the instance pan structure for this class. 
The exceptions are width and height. Even though they are instance variables of Core, 
they need to be checked by the subclass, because only this class knows its desired initial size. 
Example 6-1 shows the initialize method from BitmapEdiL 

*As described in Chapter 11, Geometry Management, the i n i t i al i ze method can also be used for creating child 
widgets, to build a compound widget. This is a way of getting around Xt's geometry management scheme, and is not 
frequently done. 

170 X Toolkit Intrinsics Programming Manual 



Examp 6-1. The #ialize meod 
/* ARGSUSED */ 
static void 
Inltlalize(treq, tnew, args, num_args) 
Widget treq, tnew; 
ArgList args; 
Cardinal *num_args; 
BitmapEdltWidget new = (BitmapEdltWidget) tnew; 
new->bltmapEdit.cur x = 0; 
-- 
new->bitmapEdit.cur_y = 0; 
/* 
* Check instance values set by resources that may be invalid. 
*/ 
if ((new->bitmapEdit.pixmap width in cells < I) 
-- _ _ 
(new->bitmapEdit.pixmap height in cells < I)) { 
XtWarning("BitmapEdit: pixmapWith andTor--pixmapHeight\ 
is too small (using I0 x I0)."); 
new->bitmapEdlt.pixmap_width in cells = I0; 
-- _ 
new->bitmapEdit.pixmap_height_in_cells = I0; 
} 
if (new->bitmapEdit.cell size in pixels < 5) { 
-- 
XtWarning("BitmapEdit: cellSize is too small (using 5)."); 
new->bitmapEdit.cell_size in pixels = 5; 
} 
if ((new->bitmapEdit.cur_x < 0)  (new->bitmapEdit.cur_y < 0)) 
XtWarning("BitmapEdit: cur_x and cur_y must be\ 
non-negative (using 0, 0)."); 
new->bitmapEdit.cur x = 0; 
-- 
new->bitmapEdit.cur_y = 0; 
} 
/* 
* Allocate memory to store array of cells in bitmap, if not 
* already done by application. 
*/ 
if (new->bitmapEdit.cell == NULL) 
new->bitmapEdit.cell = 
XtCalloc(new->bitmapEdit.pixmap_width_in_cells 
* new->bitmapEdit.pixmap_height_in_cells, sizeof(char)); 
/* Calculate useful values */ 
new->bitmapEdit.pixmap_width_in_pixels = 
new->bitmapEdit.pixmap_width_in_cells 
* new->bitmapEdit.cell size in pixels; 
-- 
new->bitmapEdit.pixmap_height in pixels = 
new->bitmapEdit.pixmap_height_in_cells 
* new->bitmapEdit.cell_size_in_pixels; 
/* set initial size of window */ 
if (new->core.width == O) { 
if (new->bitmapEdit.showAll == False) 
new->core.width = (new->bitmapEdit.pixmap_width_in_pixels 
DEFAULTWIDTH) ? DEFAULTWIDTH : 
(new->bitmapEdit.pixmap_width_in_pixels); 
else 

Basic Widget Methods 171 



Example 6-1. The initialize method (continued) 
new->core, width = new->bitmapEdit .pixmap_width_in_pixels; 
l 
if (new->core.height == O) { 
if (new->bitmapEdit.showAll == False) 
new->core.height = (new->bitmapEdit.pixmap_height_in_pixels > 
DEFAULTWIDTH) ? DEFAULTWIDTH : 
(new->bitmapEdit. pixmap_height_in_pixels) ; 
else 
new->core, height = new->bitmapEdit, pixmap_height_in_pixels; 
} 
CreateBigPixmap (new) ; 
GetDrawGC (new) ; 
GetUndrawGC (new) ; 
GetCopyGC (new) ; 
DrawIntoBigPixmap (new) ; 
} 
Even though the specific instance variables initialized here are particular to BitmapEdit, the 
techniques are common to all initialize methods. Some private instance variables, 
such as cur__x and cur_y, do not depend on resource settings and are simply initialized to 
a fixed value. Public instance variables are checked; if their values are out of range, xt- 
warning is called to print a message on the standard output and they are instead initialized 
to a fixed value. Some private instance variables are set based on public instance variables. 
GCs are the most common example. 
As you should recall from Chapter 5, Inside a Widget, all the variables set in initialize 
are declared in the BitmapEditPart instance structure in the private header file. 
Note that most of the arguments of initialize are rarely used. When initialize is 
called, the request argument is an instance structure containing the same values as new. 
But as new is changed, request provides a sometimes useful record of the resource set- 
tings originally made by the user. The args and num__args arguments contain the 
resource settings provided in the call to XtVaCreateManagedWidget. These are some- 
times useful in distinguishing between settings made by the application (args) from settings 
made by the user (which already appear in new and request). As of R4, the code in the 
initialize hook method, described in Chapter 9, Resource Management and Type 
Conversion, can optionally be placed in the i nit i al i z e method. 

6.2.1 

Creating GCs 

In any widget that does drawing, some of the private instance variables will hold the IDs of 
GCs created in the initialize method. These variables will be read when the GCs are 
needed in the expose method, and will be reset if necessary in the set_values method. 
Example 6-1 called separate routines, GetDrawGC, GetUndrawGC, and GetCopyGC to 
create the GCs. Example 6-2 shows these routines. 

172 X Toolkit Intrinsics Programming Manual 



A program prepares for creating a GC by setting the desired characteristics of the GC into 
members of a large structure called XGCValuea (defined by Xlib), and specifying which 
members of XGCValuea it has provided by setting a bitmask. This bitmask is made by 
ORing the GC mask symbols defined in <XI1/X.h>. Each bitmask symbol represents a mem- 
ber of the XGCValuea structure. Every GC field has a default value, so only those values 
that differ from the default need to be set. The default GC values are discussed in Volume 
One, Xlib Programming Manual. 
Widget code normally creates a GC with the XtGetGC call, not the Xlib analogue 
XCreateGC. XtGetGC keeps track of requests to get GCs by all the widgets in an appli- 
cation, and creates new server GCs only when a widget requests a GC with different values. 
In other words, after the first widget creates a GC with XtGetGC, any subsequent widget 
that calls XtGetGC to create a GC with the same values will get the same GC, not a new 
one. Using this client-side caching also reduces the number of requests to the server. 
Xlib provides XChangeGC to change the values in an existing GC. Xt provides no analo- 
gue. Because of the sharing of GCs allocated with XtGetGC, you must treat them as read- 
only. If you don't, you may confuse or break other widgets. In cases where your widget cre- 
ates a GC that needs changing in such a way that it is impractical to create a new GC each 
time, it may be appropriate to use the Xlib call XCreateGC instead of the Xt call XtGet- 
GC. 
BitmapEdit must use XCreateGC for two of its three GCs because these GCs are for draw- 
ing into pixmaps of depth 1, while XtGetGC always creates GCs for drawing into windows 
or pixmaps of the default depth of the screen. In other words, XtGetGC would work on a 
monochrome screen, but not on color. However, this is an unusual situation. Most widgets 
can use XtGetGC exclusively. 

Examp 6- Creating GCs from e itialize meod 
static void 
GetDrawGC(w) 
Widget w; 
BitmapEditWidget cw = (BitmapEditWidget) w; 
XGCValues values; 
XtGCMask mask = GCForeground 
GCDashList I GCLineStyle; 
/* 
* Setting foreground and background to 1 and 0 looks like a 
* kludge but isn't. This GC is used for drawing 
* into a pixmap of depth one. Real colors are applied with a 
* separate GC when the pixmap is copied into the window. 
*/ 
values.foreground = I; 
values.background = 0; 
values.dashes = I; 
values.dash offset = 0; 
values.line,style = LineOnOffDash; 
cw->bitmapEdit.draw gc = XCreateGC(XtDisplay(cw), 
cw->bitmapEit.big_picture, mask, &values); 

Basic Widget Methods 

173 



6.3 The expose Method 

The expose method is responsible for initially drawing into a widget's window and for 
redrawing the window every time a part of the window becomes exposed. This redrawing is 
necessary because the X server does not maintain the contents of windows when they are 
obscured. When a window becomes visible again, it must be redrawn. 
The expose method usually needs to modify its drawing based on the geometry of the win- 
dow and other instance variables set in other methods. For example, the Label widget will 
left-justify, center, or fight-justify its text according to the XtNjustify resource, and the 
actual position to draw the text depends on the widget's current size. The Label widget has 
an instance variable called justify, which is set initially in the initialize method, 
and is read in Label's expose method. 
Another factor to consider when writing the expose method is that many widgets also draw 
from action routines, in response to user events. For example, BitmapEdit toggles bitmap 
cells in action routines. The expose method must be capable of redrawing the current state 
of the widget at any time. This means that action routines usually set instance variables 
when they draw so that the expose method can read these instance variables and draw the 
fight thing. 
Most widgets keep track of what they draw in some form of arrays or display lists. When 
they need to redraw, they simply replay the saved drawing commands in the original order to 
redraw the window. For example, BitmapEdit keeps track of the state of each bitmap cell in 
a character array. It could easily traverse this army and redraw each cell that is set in the 
array. 
However, BitmapEdit does not use this strategy. In order to improve its scrolling perfor- 
mance, the expose method copies an off-screen pixmap into the window whenever 
redisplay is required. The actions draw into this off-screen pixmap (in addition to updating 
the character array), and then call the expose method directly to have the correct portion of 
the pixmap copied to the window. 
The expose method is passed an event that contains the bounding box of the area exposed. 
To achieve maximum performance it copies only this area from the pixmap to the window. 
The BitmapEdit actions take advantage of this, too. They manufacture an artificial event 
containing the boundirig box of the cell to be toggled, and pass it when they call expose. 
This causes the expose method to copy that one cell that was just updated to the window. 
Example 6-3 shows the expose method from the BitmapEdit widget. 

Examp 6-3. The expose meod 
/* ARGSUSED */ 
static void 
Redisplay(w,-event) 
Widget cw; 
XExposeEvent *event; 
BitmapEditWidget cw = (BitmapEditWidget) w; 
register int x, y; 

Basic WkJget Methods 175 



Example 6-3. The expose method (continued) 
unsigned int width, height; 
if (!XtIsRealized(cw)) 
return; 
if (event) { /* called from btn-event */ 
x = event->x; 
y = event->y; 
width = event->width; 
height = event->height; 
} 
else {/* called because of expose */ 
x = 0; 
y= 0; 
width = cw->bitmapEdit.pixmap_width_in_pixels; 
height = cw->bitmapEdit.pixmap_height in pixels; 
} 
if (DefaultDepthOfScreen(XtScreen(cw)) == i) 
XCopyArea (XtDisplay (cw), cw->bitmapEdit.big_picture, 
XtWindow (cw) , cw->bitmapEdit.copy_gc, x + 
cw->bitmapEdit.cur_x, y + cw->bitmapEdit.cur_y, 
width, height, x, y); 
else 
XCopyPlane (XtDisplay (cw), cw->bitmapEdit.big_picture, 
XtWindow(cw), cw->bitmapEdit.copy_gc, x + 
cw->bitmapEdit.cur_x, y + cw->bitmapEdit.cur_y, 
width, height, x, y, i); 
} 
Note that the expose method first checks to see that the widget is realized using Xt- 
IsRealized. This is a precaution against the unlikely event that an instance of this 
widget is suddenly destroyed or unrealized by an application while Expose events are still 
pending. If this did happen, drawing on the nonexistent window would cause an X protocol 
error. 
Next, BitmapEdit's expose method sets the rectangle it will redraw based on the event 
passed in by Xt. We also call this method directly from the action that processes button 
presses. That action routine creates a pseudo-event to pass to expose to describe the area 
to be drawn. 
If the compress_exposure field of the class structure is initialized to XtExpose- 
CompressMultiple (or one of a few other constants, described in Chapter 8, More 
Input Techniques), as it is in BitmapEdit, Xt automatically merges the multiple Expose 
events that may occur because of a single user action into one Expose event. In this case, 
the Expose event contains the bounding box of the areas exposed. BitmapEdit redraws 
everything in this bounding box. For widgets that are very time-consuming to redraw, you 
might want to use the third argument of the expose method, which is a region. The 
Region type is opaquely defined by Xlib (internally a linked list of rectangles). The 
Region passed into expose describes the union of all the areas exposed by a user action. 
You can use this region to clip output to the exposed region, and possibly calculate which 
drawing primitives affect this area. Xlib provides region mathematics routines (such as 
XRectrnRegion) tO compare the regions in which your widget needs to draw with the 

176 X Toolkit Intrinsics Programming Manual 



region needing redrawing. If certain areas do not require redrawing, you can skip the code 
that redraws them, thereby saving valuable time. However, if this calculation is complicated, 
its cost/benefit ratio should be examined. 

Consider the arrangement of windows shown in Figure 6-1. 

expose A 

.bounding rectangle 
n merged expose 
event 

region 

B 

expose B 

window 3 
(overlapping window) 

Figure 6-I. compress_exposure: 2 rectangles if XtExposeNoCompress; bounding box and re- 
gion if XtExposeCompressSeries or XtExposeCompressMultiple 

Window 1 and Window 3 are other applications, and Widget 2 is an application consisting 
solely of our widget. 

Initially, Window 3 is on top, Window 1 is behind it, and Widget 2 is hidden completely 
behind Window 1. When Window 1 is lowered, Widget 2 becomes visible, except where it is 
still overlapped by Window 3. The newly-exposed area can be described by two rectangles; 
A and B. If compress_exposure is FALSE, Widget 2's expose method will be called 

Basic Widget Methods 177 



twice, and passed an Expose event first describing Rectangle A, then Rectangle B. But if 
compress_exposure is TRUE, Widget 2's expose method will be called just once, 
passed an Expose event describing the bounding box of all the original Expose events 
(which would be the entire widget in this case), and passed a Region which is the union of 
the rectangles described by all of the Expose events. The region argument of the 
expose method is unused unless compress_exposure is TRUE. Each of these expo- 
sure-handling techniques may be the best for certain widgets. For a widget like BitmapEdit, 
any of the three methods will work, but the bounding box method is the most efficient and 
convenient. For a complete description of Expose event handling strategies, see Chapter 8, 
Events, in Volume One, Xlib Programming Manual. 
The remainder of BitmapEdit's expose method shown in Example 6-3 consists of a single 
Xlib call to copy from a pixmap into the widget's window. As described in Chapter 4, An 
Example Application, BitmapEdit makes a large pixmap that is one plane deep and draws the 
current bitmap into it. When needed in the expose method, this pixmap just has to be 
copied into the window. This approach was chosen for its simplicity. When scrollbars are 
added, the widget is able to pan around in the large bitmap quickly and efficiently. Note that 
one of two Xlib routines is called based on the depth of the screen. This is because XCopy- 
Area is slightly more efficient than xCopyplane and should be used when running on a 
monochrome screen. 
Note that instance variables are used for the arguments of the Xlib routines in Example 6-3. 
Don't worry about exactly what each Xlib routine does or the meaning of each argument. 
See the reference page for each routine in Volume Two, Xlib Reference Manual, when you 
need to call them in your code. 
See Chapters 5, 6, and 7 in Volume One, Xlib Programming Manual, for more information 
on the GC, drawing graphics, and color, respectively. 

6.4 

The set values Method 

When the application calls xtvaSetValues (or XtVaSetValues) to change widget 
resources during run time, Xt calls the set_values method. The set_values method 
is where a widget responds to changes in its public instance variables. It should validate the 
values of the public variables, and recalculate any private variables that depend on public 
variables that have changed. 
Example 6-4 shows the set values method for BitmapEdit. 
-- 

Examp 6. The selvages meod 
/* ARGSUSED */ 
static Boolean 
SetValues(current, request, new, args, num_args) 
Widget current, request, new; 
ArgList args; 
Cardinal *num_args; 
{ 

178 X Toolkil Intrinsics Programming Manua/ 



Example 6-4. The set_values method (continued) 
BitmapEditWidget curcw = (BitmapEditWidget) current; 
BitmapEditWidget newcw = (BitmapEditWidget) new; 
Boolean do_redisplay = False; 
if (curcw->bitmapEdit.foreground != newcw->bitmapEdit.foreground) 
XtReleaseGC (curcw, curcw->bitmapEdit.copy_gc) ; 
GetCopyGC (newcw) ; 
do_redisplay = True; 

} 
if 

((curcw->bitmapEdit.cur x != newcw->bitmapEdit.cur x) II 
(curcw->bitmapEdit?cur_y != newcw->bitmapEdit?cur y)) 
do_redisplay = True; -- 
if (curcw->bitmapEdit.cell_size_in_pixels != 
newcw->bitmapEdit.cell size in_pixels) { 
ChangeCellSize(curcw, newc->bimapEdit.cell size in pixels); 
do_redisplay = True; -- 
) 
if (curcw->bitmapEdit.pixmap_width in cells != 
newcw->bitmapEdit.pixmap_width in cells) { 
newcw->bitmapEdit.pixmap_width in cells = 
-- _ 
curcw->bitmapEdit.pixmap_width in cells; 
XtWarning("BitmapEdit: pixmap_width in cells cannot\ 
-- _ 
be set by XtSetValues.\n"); 
) 
if (curcw->bitmapEdit.pixmap_height in cells != 
newcw->bitmapEdit.pixmap_height in cells) { 
newcw->bitmapEdit.pixmap_height in els = 
curcw->bitmapEdit.pixmap_height_in_cells; 
XtWarning("BitmapEdit: pixmap_height in cells cannot\ 
be set by XtSetValues.\n"); 
) 

return do_redisplay; 

The set_values method is called with three copies of the widget's instance structure as 
arguments: current, request, and new. The current copy includes the current set- 
tings of the instance .variables, and request includes the settings made through xt- 
VaSetValues but not yet changed by the superclasses' set values methods. The 
-- 
new copy is the same as request except that it has already been processed by the 
set_values methods of all superclasses. 

For each public variable, set values compares the current value and the new value, and 
-- 
if they are different, validates the new value or changes any private values that depend on it. 
The new copy is the only one that the method changes; request and current are only 
for reference. As in the initialize method, you have to deal only with the instance vari- 
ables for your-subclass, and perhaps with width and height, because the set__values 
method is downward chained. Superclass set__values methods take care of setting all the 
superclass instance fields. However, if desired, you can change superclass fields in your 
method since it is called last. For example, this might be useful if your class has different cri- 
teria for determining valid values or dependencies. 

Basic WMget Methods 179 



The request copy of the instance variables is used only if your class needs to decide 
between a superclass setting and your widget's setting; disagreements about this usually 
occur over the size of the widget For more information on when to use request, see the 
reference page for XtSetValuesFunc in Volume Five, X Toolkit Intrinsics Reference 
Manual. 
It is also important to notice that the set values method, if it exists at all (that is, if it is 
not specified as NULL in the class structure), must return TRUE or FALSE tO indicate whether 
the changes made to the state variables require the widget to be redrawn. If it is TRUE for this 
class or any superclass, Xt calls the Xlib routine XClearArea with the exposures argu- 
ment set to TRUE (tO force the background of the widget to be redrawn, which normally 
occurs only after Expose events), and then Xt calls the expose method. In other words, 
you should make set_values return TRUE whenever the changes to the instance variables 
will change what is drawn in the widget. 
Note, however, that set_values should not return TRUE if width and height change, 
because the X server automatically generates Expose events for a window when it is 
resized. If you do return TRUE in this case, your expose method will be called twice. 
Since the application may call xtvaSetValues before the widget is realized, it is impor- 
kant not to assume in the set values method that the widget has a window. In other 
-- 
words, the code must use xtI s Reali z ed to check whether the widget is realized before 
using the xtwindow macro, such as in a call to set window attributes. 
As mentioned earlier, some of the private variables are usually GCs. Whenever the public 
variable for a color or font is changed through xtvaSetValues, a GC also has to be 
changed. This is an example of a private variable depending on a public one. GCs allocated 
with XtGetGC should not be changed since they may be shared by other widgets. There- 
fore, the normal response to a change in one of the resources on which a GC depends is to 
release the GC with XtReleaseGC and request a new one with XtGetGC. 
If some of your widget's GCs are unlikely to be shared by other widget instances in an appli- 
cation (either because each instance will use different values for the GC components or there 
will be only one instance), and the widget needs to be able to make changes to them, and the 
changes are not predictable enough or few enough to reasonably create a GC for each varia- 
tion, then the XtGetGC/XtReleaseGC approach is not ideal. What happens in this situa- 
tion is that XtGetGC creates a new GC and XtReleaseGC frees the old GC every time a 
change is made, even if the changes are small. It is more efficient in this situation to change 
the affected values in the existing GC. But this can be done only with an Xlib routine--there 
is no Toolkit routine for changing a GC. To implement this approach, you create, modify, 
and free the unusual GC using Xlib routines only. You call XCreateGC in the initial- 
ize method to create the GC, XChangeGC in the set values method to change the 
GC, and XFreeGC in the destroy method to free the GC. All of these Xlib routines are 
described in Chapter 5, The Graphics Context, in Volume One, Xlib Programming Manual. 
XtGetGC always creates a GC that can only be used on drawables (windows and pixmaps) 
of the default depth of the screen. Drawing into a pixmap of depth one using a GC created 
with XtGetGC works on a monochrome display, but usually does not work on a color dis- 
play. (The depth is the number of bits per pixel used to represent colors on the screen.) This 
is another situation in which you will need to call XCreateGC instead of XtGetGC. 

180 X Toolkit Intrinsics Programming Manual 



Examp 6-5. BitmapEdit: erese meod 
/* ARGSUSED */ 
static void 
Resize(w) 
Widget w; 
BitmapEditWidget cw = (BitmapEditWidget) w; 
/* resize does nothing unless new size is bigger than entire pixmap */ 
if ((cw->core.width > cw->bitmapEdit.pixmap_width in plxels) && 
(cw->core.height > cw->bitmapEdit.pixmap_height_in_pixels)) { 
/* 
* Calculate the maximum cell size that will allow the 
* entire bitmap to be displayed. 
*/ 
Dimension w_temp_cell_size_in_pixels, h_temp_cell_size_in_pixels; 
Dimension new_cell_size_in_pixels; 
w_temp_cell_size_in_pixels = cw->core.width / 
cw->bitmapEdit.pixmap_width in cells; 
h_temp_cell_size_in_pixels = cw->core.height / 
cw->bitmapEdit.pixmap_height in cells; 
if (w_temp_cell_size in pixels < h_temp_cell size_in_pixels) 
new_cell_size_in_pixels = w_temp_cell_sie_in_pixels; 
else 
new_cell_size in pixels = h_temp_cell_size_in_pixels; 
/* if size change mandates a new pixmap, make one */ 
if (new_cell_size in pixels != cw->bitmapEdit.cell_size_in_pixels) 
ChangeCellSize(cw, new_cell_size_in_pixels); 
) 
) 
static void 
ChangeCellSize(w, new cell size) 
Widget w; 
int new cell size; 
BitmapEditWidget cw = (BitmapEditWidget) w; 
int x, y; 
cw->bitmapEdit.cell_size_in_pixels = new_cell_size; 
/* recalculate variables based on cell size */ 
cw->bitmapEdit.pixmap_width in pixels = 
cw->bitmapEdit.pixmap_width in cells * 
cw->bitmapEdit.cell_size_in_pixels; 
cw->bitmapEdit.pixmap_height_in_pixels = 
cw->bitmapEdit.pixmap_height in cells * 
cw->bitmapEdit.cell_size_in_pixels; 
/* destroy old and create new pixmap of correct size */ 
XFreePixmap(XtDisplay(cw), cw->bitmapEdit.big_picture); 
CreateBigPixmap(cw); 
/* draw lines into new pixmap */ 
DrawIntoBigPixmap(cw); 
/* draw current cell array into pixmap */ 
for (x = 0; x < cw->bitmapEdit.pixmap_width_in_cells; x++) { 

182 X Toolkit Intrinsics Programming Manual 



Example 6-5. BitmapEdit: the resize method (continued) 
for (y = 0; y < cw->bitmapEdit.pixmap_height in cells; y++) 
if (cw->bitmapEdit.cellIx + (y * 
cw->bitmapEdit.pixmap_width in cells)] == DRAWN) 
DoCell (cw, x, y, cw->bitmapEdit.draw_gc) ; 
else 
DoCell (cw, x, y, cw->bitmapEdit.undraw_gc) ; 

} 
} 

static void 

DoCell(w, x, y, gc) 
Widget w; 
int x, y; 
GC gc; 
{ 
BitmapEditWidget cw = (BitmapEditWidget) w; 
/* otherwise, draw or undraw */ 
XFillRectangle(XtDisplay(cw), cw->bitmapEdit.big_picture, gc, 
cw->bitmapEdit.cell size in pixels * x + 2, 
-- 
cw->bitmapEdit.cell_size in .pixels * y + 2, 
(unsigned int)cw->bitmapEdit.cell_size_in_pixels - 3, 
(unsigned int)cw->bitmapEdit.cell_size_in_pixels - 3); 
} 

Because of the two-phase resize strategy used by BitmapEdit, and because BitmapEdit uses a 
pixmap in its repaint strategy, this resize method is more complicated than most. When 
the widget is resized larger that necessary to show the entire bitmap in the current 
cell si ze, it destroys the current pixmap and creates a new one. Since this should not 
-- 
happen very often and because resizing does not require extremely fast response, the time it 
takes to recreate the pixmap and draw into it is acceptable. 
One difficulty in writing the reni ze method is that you do not have access to the old size or 
position of the window. The widget instance structure passed in has already been updated 
with the current size and position. If you need the old information, you can cache the old 
size in an instance part field, set first in the initialize method, and again at the end of 
the resi ze method. 
It is also important to.note, that the resi ze method is not allowed to request that the parent 
resize the widget again to get a better size. (How to suggest properly to the parent that your 
widget be resized is described in Chapter 11, Geometry Management.) 

Basic Widget Methods 183 



6.6 The query_geometry Method 

When your widget is used in an application, its parent widget will be a composite or con- 
straint widget that manages its size and position. Parent widgets need to know the preferred 
size of a widget so they can make good decisions about the size of each child. The 
query_geometry method is called when the parent is about to make a size change to 
some of its children but is not yet sure which ones and by how much. (How geometry man- 
agement works is described in Chapter 11, Geometry Management. For now, we are concen- 
trating on what you need to do to write a simple widget.) 
If your widget specifies NULL in the class structure for the query_geometry method, the 
parent will be told that your widget's current geometry is its preferred geometry. This is 
often wrong information. For example, if your widget has already been resized to be one- 
pixel-by-one-pixel because the user has resized an application to be very small, the parent 
would receive the message that your widget prefers to be that small. When the application is 
resized to be larger again, the parent will have no information on which to base its resizing 
decisions. Even if your widget has no particular preference for size, it is a good idea to spec- 
ify the widget's default size in query_geometry. Then, at least, the parent has a ballpark 
figure for typical sizes for your widget. The parent could at least find out that BitmapEdit is 
intended to be larger than a Label widget. 
The query_geometry method is passed pointers to two copies of the XtWidget- 
Geometry structure, one containing the parent's intended size for your widget, and the 
other to contain your reply to the parent's suggestion. The XtWidgetGeometry structure 
is shown in Example 6-6. 

Example 6-6. The XtWidgetGeometry structure 
typedef struct { 
XtGeometryMask request_mode; 
Position x, y; 
Dimension width, height; 
Dimension border width; 
-- 
Widget sibling; 
int stack mode; 
-- 
} XtWidgetGeometry; 
The request_mode field is a mask that indicates which other fields in the structure are set. 
It is a bitwise OR of any or all of the symbolic constants shown in Table 6-1. 

Table 6-1. XtWidgetGeometry request_mode Symbols 

Symbol 

CWX 
CWY 
CWWidth 
CWHeight 
CWBorderWidth 

Description 

The x coordinate of the widget's top left comer is specified. 
The y coordinate of the widget's top left comer is specified. 
The widget's width is specified. 
The widget's height is specified. 
The widget's borderwidth is specified. 

184 X Too&# Intrinsics Programming Manual 



Table 6-1. XtWidgetGeometry request_mode Symbols (continued) 

Symbol 

CWSibling 

CWStackMode 

Description 

A sibling widget is specified, relative to which this widget's stacking 
order should be determined. 
A stack_mode value is present, specifying how this widget should 
be stacked relative to the widget identified as sibling. 

The sibling and stack_mode fields are used together to indicate where in the stacking 
order of its siblings your widget will be placed. The symbols for stack mode are Above 
Below, TopIf, BottomIf, Opposite, and XtSMDontChange. (These symbols are 
used singly, not combined with OR.) Their meanings are summarized in Table 6-2. 

Table 6-2. XtWidgetGeometry stack_mode Symbols 

Stacking Flag 

Above 

Below 

TopIf 

BottomIf 

Opposite 

XtSMDontChange 

Position 

w is placed just above sibling. If no sibling is specified, w is 
placed at the top of the stack. 
w is placed just below sibling. If no sibling is specified, w is 
placed at the bottom of the stack. 
If sibling obscures w, then w is placed at the top of the stack. If no 
sibling is specified, then if any sibling obscures w, w is placed at 
the top of the stack. 
If w obscures sibling, then w is placed at the bottom of the stack. If 
no sibling is specified, then if wobscures any sibling, w is placed at 
the bottom of the stack. 
If sib2ing occludes w, w is placed at the top of the stack. If w 
occludes sibling, w is placed at the boUom of the stack. If no 
sibling is specified, then if any sibling occludes w, w is placed at 
the top of the stack, or if w occludes any sibling, w is placed at the bot- 
tom of the stack. 
Cun'ent position in stacking order is maintained. 

Note that Xt's handling of stacking order is cun'ently incomplete, and these symbols might 
not be honored. By default, the most recently created widget appears on the bottom. 

One more issue about the query_geometry method must be raised before showing an 
example: the method's return value. The query_geometry method must return one of 
the three enum values XtGeomet ryYes, XtGeomet ryAlmost, or XtGeomet ryNo. 
XtGeometryResult is an enum name, and it is the returned type of 

que ry_ge omet ry. 

Basic Widget Methods 185 



6.8 Actions in the Widget Framework 

Although actions, strictly speaking, are not methods, writing them is part of the process of 
writing a simple widget. Fortunately, you have already seen action routines added from the 
application. Action routines look and work the same in the widget framework as in the appli- 
cation, except that they use instance structure fields as data instead of the application data 
structure fields. Example 6-9 shows the actions of BitmapEdit. 

Examp 6-9. BitmapEdit: action routines 
/*ARGUSED*/ 
static void 
DrawCell(w, event) 
Widget w; 
XEvent *event; 
String *params; 
Cardinal *num_params; 
BitmapEditWidget cw = (BitmapEditWidget) w; 
DrawPixmaps(cw->bitmapEdit.draw_gc, DRAW, cw, event); 
/*ARGUSED*/ 
static void 
UndrawCell(w, event) 
Widget w; 
XEvent *event; 
String *params; 
Cardinal *num_params; 
{ 
BitmapEditWidget cw = (BitmapEditWidget) w; 
DrawPixmaps(cw->bitmapEdit.undraw_gc, UNDRAW, cw, event); 
) 
/*ARGUSED*/ 
static void 
ToggleCell(w, event) 
Widget w; 
XEvent *event; 
String *params; 
Cardinal *num_params; 
BitmapEditWidget cw = (BitmapEditWidget) w; 
static int oldx = -i, oldy = -i; 
GC gc; 
int mode; 
int newx, newy; 

/* This is strictly correct, but doesn't 
* seem to be necessary */ 
if (event->type == ButtonPress) { 
newx = (cw->bitmapEdit.cur x + ((XButtonEvent *)event)->x) / 
-- 
cw->bitmapEdit.cell_size_in_pixels; 
newy = (cw->bitmapEdit.cur_y + ((XButtonEvent *)event)->y) / 
cw->bitmapEdit.cell_size_in_pixels; 
) 
else { 
newx = (cw->bitmapEdit.cur x + ((XMotionEvent *)event)->x) / 
-- 

188 X Toolkit Intrinsics Programming Manual 



Example 6-9. BitmapEdit: action routines (continued) 

cw->bitmapEdit.cell_size in pixels; 
newy = (cw->bitmapEdit.cur_y + (XMtionEvent *)event)->y) / 
cw->bitmapEdit.cell_size in pixels; 

if ((mode = cw->bitmapEdit.cell[newx + newy * 
cw->bitmapEdit.pixmap_width in cells]) == DRAWN) { 
gc = cw->bitmapEdit.undraw_gc; 
mode = UNDRAW; 
} 
else { 
gc = cw->bitmapEdit.draw_gc; 
mode = DRAW; 
} 
if (oldx . 
.= newx I I oldy != newy) { 
oldx = newx; 
oldy = newy; 
DrawPixmaps(gc, mode, cw, event); 
} 
} 
static void 
DrawPixmaps(gc, mode, w, event) 
GC gc; 
int mode; 
Widget w; 
XButtonEvent *event; 
{ 
BitmapEditWidget cw = (BitmapEditWidget) w; 
int newx = (cw->bitmapEdit.cur x + event->x) / 
cw->bitmapEdit.cell sie in pixels; 
-- 
int newy = (cw->bitmapEdit.cur_y + event->y) / 
cw->bitmapEdit.cell size in pixels; 
-- 
XExposeEvent fake event; 
-- 
/* if already done, return */ 
if (cw->bitmapEdit.cell[newx + newy * 
cw->bitmapEdit.pixmap_width in cells] == mode) 
return; 
/* otherwise, .draw or undraw */ 
XFillRectangle(XtDisplay(cw), cw->bitmapEdit.big_picture, gc, 
cw->bitmapEdit.cell_size_in_pixels*newx + 2, 
cw->bitmapEdit.cell_size_in_pixels*newy + 2, 
(unsigned int)cw->bitmapEdit.cell_size_in_pixels - 3, 
(unsigned int)cw->bitmapEdit.cell_size in pixels - 3); 
cw->bitmapEdit.cell|newx + newy * 
cw->bitmapEdit.pixmap_width in cells] = mode; 
info.mode = mode; 
info.newx = newx; 
info.newy = newy; 
fake event.x = cw->bitmapEdit.cell size in pixels * 
_ -- 
newx - cw->bitmapEdit.cur x; 
-- 
fake_event.y = cw->bitmapEdit.cell_size_in_pixels * 
newy - cw->bitmapEdit.cur_y; 

Basic Widget Methods 189 



Example 6-9. BitmapEdit: action routines (continued) 
fake_event, width = cw->bitmapEdit, cell_size_in_pixels; 
fake_event, height = cw->bitmapEdit, cell_size_in_pixels; 
Redisplay(cw, &fake event); 
-- 
XtCallCallbacks(cw, XtNcallback, &info); 
} 
Notice that as in methods, the widget instance pointer passed in is declared as type Widget, 
and then, in the first line of the action, cast to the desired type. This is necessary for ANSI C 
conformance. 
An action routine in widget code can set and read fields in the widget instance structure 
passed in, while an action added from the application can access its own application data 
structure but not the widget's internal data structure because of the encapsulation rule (see 
Section 2.1.6.3). This is one of the advantages of moving this code into a widget. 
You should now be ready to go back near the end of Chapter 5, Inside a Widget, and follow 
the directions to write your first widget. You will need to review parts of both Chapter 5 and 
this chapter as the process of actually writing a widget raises new questions in your mind. 

190 X Too&# Intrinsics Programming Manual 



7 

Events, Translations, and Accelerators 

This chapter describes the complete syntax of translatton tables, and 
describes a mechanism called accelerators for mapping events in one widget 
to actions in another. 

In This Chapter: 

Translation Table Syntax .................................................................... 194 
The Directive ................................................................................. 195 
Selecting the Events to Translate ................................................... 195 
Details in Keyboard Events ............................................................ 198 
Details in Other Event Types .......................................................... 199 
Modifiers ........................................................................................ 201 
Physical Keys Used as Modifiers ................................................. 202 
Default Interpretation of the Modifier List ...................................... 204 
Prohibiting a Modifier ................................................................... 204 
Requiring an Exact Match ............................................................ 205 
Paying Attention to the Case of Keysyms .................................... 205 
Event Sequences .......................................................................... 206 
Special Corsiderations Involving Motion Events ........................... 207 
Modifiers and Event Sequences ................................................... 207 
Using Modifiers to Specify Button Event Sequences .................... 208 
Key Event Sequences ................................................................. 208 
Interactions Between Translations .................................................. 208 
Translations in Multiple Resource Files ........................................ 209 
Order of Translations ................................................................... 209 
Event Sequences Sharing Initial Events ....................................... 210 
Event Sequences Sharing Noninitial Events ................................. 210 
Accelerators ...................................................................................... 211 
Event Propagation ......................................................................... 213 
Installing Accelerators in Multiple Widgets ...................................... 215 
Defining the Accelerator Table in the Code ..................................... 216 
The display_accelerators Method ................................................... 216 



7 
Events, Translations, 
and Accelerators 

Events drive the application. They send a great variety of information from the server to the 
client and from the user to the application. More knowledge of events is necessary both to 
use existing widgets successfully in large applications and to write widgets. 
Events are sufficiently cent/al to X that we've devoted two chapters in this book to them. 
This chapter provides a closer look at translations and actions; Chapter 8, More Input Tech- 
niques, looks at lower-level event handlers, as well as at other sources of input. Appendix 
C, Event Reference, in Volume Five, X Toolkit Intrinsics Reference Manual, will also be 
useful when you need details about any of the event types. 
The basic concept and use of translations and actions has already been described. But trans- 
lation tables have a complicated syntax which can be used to do much more than the simple 
mappings you have seen up until now. Translation tables can detect user-interface idioms 
such as double- and triple-button clicks or key combinations such as Shift-Meta-M. This 
chapter focuses on the more advanced features of translation tables. 
Next, we discuss a variation of translations called accelerators. Accelerators bind events 
that occur in one widget to actions in another. This is a flexible feature with many uses. One 
common use is to supply a keyboard interface to a normally pointer-driven application. By 
adding accelerators to the top-level window of the application, a keyboard event typed with 
the pointer anywhere in the application can be translated into an action in the correct widget. 
The name "accelerator" comes from the fact that many advanced users find it faster to use 
keyboard shortcuts inst6ad of menus. 
As mentioned in Chapter 3, More Techniques for Using Widgets, it is a very good idea to 
specify translation tables (and accelerator tables, too) in the application-defaults file instead 
of hardcoding them in the application, especially while an application is under development. 
This lets you develop the translations and accelerators without recompiling the application 
every time you want to make a change. 

Events, Translations, and Accelerators 193 



7.1 Translation Table Syntax 

If you are reading this book in sequence, you've already seen translations used many times. 
However, we haven't given a formal description of their syntax or a complete listing of the 
events you can translate. 
A translation table consists of an optional directive, which specifies how the table should be 
merged with any other existing translation tables, followed by a series of production rules, of 
the form: 
[modifier_list] <event>[, <event> ... ] [ (count) ] [detail] : action( [arguments] ) [ action... ] 
where brackets ([ ]) indicate optional elements, an ellipsis (...) indicates repetition, and 
italics indicate substitution of an actual modifier, event, detail, or action name. 
At a minimum, a translation must specify at least one event, specified by a predefined event 
name or abbreviation enclosed in angle brackets; a colon separator; and at least one action. 
However, a sequence of events can be specified; likewise, more than one action can be 
invoked as a result. The scope of event matching can be limited by one or more optional 
modifiers, and, in the case of some events, by a "detail" field that specifies additional infor- 
marion about the evenL (For example, for key events the detail field specifies which key has 
been pressed.) Repeated occurrences of the same event (e.g., a double-click) can be specified 
by a count value in parentheses. A colon and optional white space separates the translation 
and the action. 
The examples below are all valid translations: 
<Enter> : doit () 
<BtnlDown>, <BtnlUp> : doit () 
<BtnlUp> (2) : dolt () 
Buttonl<Btn2Down>, <Btn2Up> : doit ( ) 
invoke doit 0 on a click o/Button 2 while Button 1 is held down 
Shift<BtnDown> : dolt () 
invoke dolt 0 on a click o/any button while the shift key is held down 
<Key>y: dolt () invoke doitO when the y key is pressed 
A translation table is a single string, even when composed of multiple translations. If a trans- 
lation table consists of more than one translation, the actual newlines are escaped with a 
backslash (except for the last one), and character newlines are inserted with the \n escape 
sequence, as you've seen demonstrated in examples throughout this book. 
The following sections provide additional detail on each of the elements of an event transla- 
tion. We'll talk first about the directive, followed by event specifiers, details, modifiers, and 
counts. We'll also provide some pointers on the proper sequence of translations, and discuss 
what happens when translations overlap. 

invoke dolt 0 on an EnterWindow event 
invoke doitO on a click of Button 1 
invoke doit 0 on a double-click of Button 1 

194 X Toolkit Intrinsics Programming Manual 



7.1.1 The Directive 

As we've already seen, the three possible directives are #replace, #override, or 
#augment. 
#replace says to completely replace the value of the translations resource in the 
widget. If no directive is specified, #replace is the default. 
The difference between #override and #augment is more subtle. They differ in how 
they treat event combinations in the new translation that also appear in the old. With 
#override, the new translation takes profity, while with #augment, the old one does. 
For example, say a widget has a default translation table that includes a translation for the 
Return key, and an application that uses this widget has an application-defaults file consisting 
of a translation table that applies to this widget. If the translation table in the application- 
defaults file began with #override, any translation for the Return key would take priority 
over the default translation for the Return key. On the other hand, if the translation table in 
the application-defaults file began with #augment, the default translations would take pri- 
ority. 
Remember that the difference between #augment and #override is only in the treat- 
ment of overlapping translations. Any translations added with either directive for events that 
do not already appear in the existing translation table will always be added. 
Because of potential overlap between translations, when you are debugging your intended 
translations it is best to use #replace at first, then test with #augment or #override 
as appropriate once you are sure that the translations themselves have the desired effect. 

7.1.2 Selecting the Events to Translate 

An X event is a packet of data sent by the server to a client in response to user behavior or to 
window system changes resulting from interactions between windows. There are 33 different 
types of events defined by X. Most (though not all*) events can be thought of as occurring in 
a window: the pointer entering or leaving a window, pointer motion within a window, 
pointer button presses, key presses, and so on. However, most events are not sent to a win- 
dow unless the window' has explicitly selected that event type; events are selected on a per- 
window basis. In Xlib programming, events are selected by specifying an event mask as a 
window atlribute. Some events, which are sent to all windows regardless of whether a win- 
dow has selected them or not, are called non-maskable events. One of the most complex 
aspects of Xlib programming is designing the event loop, which must take into account all of 
the possible events that can occur in a window. 

Xt's translation manager selects the events that are specified in the current translation table 
for each widget. In translations, events can be specified either by their actual names, as 
shown in column 1 of Table 7-1, or by means of the abbreviations shown in column 2. A 

*Others reflect internal changes in the window system not related to any window. For example, a mapping Not i fy 
event occurs in response to a change in the mappings of keysyms (potable key symbols) to keycodes (actual codes 
generated by physical keys). 

Events, Translations, and Accelerators 195 



complete reference to each event type is provided in Appendix C, Event Reference, in Vol- 
ume Five, X Toolkit Intrinsics Reference Manual. 

Table 7-1. Event Type Abbreviations in Translation Tables 

Event Type 

ButtonPress 

ButtonRelease 

KeyPress 

KeyRelease 
MotionNotify 

EnterNotify 

LeaveNotify 

FocusIn 
FocusOut 
KeymapNotify 
Expose 
GraphicsExpose 
NoExpose 
ColormapNotify 
PropertyNotlfy 
VislbilityNotlfy 
ResizeRequest 

Abbreviations 

BtnDown 
BtnlDown 
Btn2Down 
Btn3Down 
Btn4Down 
Btn5Down 
BtnUp 
BtnlUp 
Btn2Up 
Btn3Up 
Btn4Up 
Btn5Up 
Key 
KeyDown 
Ctrl 
Meta 
Shift 
KeyUp 
Motion 
PtrMoved 
MouseMoved 
BtnMotion 
BtnlMotion 
Btn2Motlon 
Btn3Motion 
Btn4Motion 
Btn5Motion 
Enter 
EnterWindow 
Leave 
LeaveWindow 
FocusIn 
FocusOut 
Keymap 
Expose 
GrExp 
NoExp 
Clrmap 
Prop 
Visible 
ResReq 

Description 

Any pointer button pressed 
Pointer button 1 pressed 
Pointer button 2 pressed 
Pointer button 3 pressed 
Pointer button 4 pressed 
Pointer button 5 pressed 
Any pointer button released 
Pointer button 1 released 
Pointer button 2 released 
Pointer button 3 released 
Pointer button 4 released 
Pointer button 5 released 
Key pressed 
Key pressed 
Keypress wi Ctfl modifier 
Keypress wi Meta modifier 
KeyPress with Shift modifier 

Key released 
Pointer moved 
Pointer moved 
Pointer moved 
Pointer moved 
Pointer moved 
Pointer moved 
Pointer moved 
Pointer moved 
Pointer 
Pointer 
Pointer 
Pointer 

with any button held down 
with button 1 held down 
with button 2 held down 
with button 3 held down 
with button 4 held down 

moved with button 5 held down 
entered window 
entered window 
left window 

Pointer left window 
This window is now keyboard focus 
This window lost keyboard focus 
Keyboard mappings changed 
Part of window needs redrawing 
Source of copy unavailable 
Source of copy available 
Window's colorrnap changed 
Property value changed 
Window has been obscured 
Redirect resize request to window manager 

196 X Toolkit Inttinsics Programming Manual 



T;,ble 7-I. Event Type Abbrevi;,tions in Tr;,nsl;,tion Tables (continued) 

Event Type 

CirculateNotify 
ConfigureNotify 
DestroyNotify 
GravityNotify 
MapNotify 
CreateNotify 
ReparentNotify 
UnmapNotify 
CirculateRequest 
ConfigureRequest 
MapRequest 
MappingNotify 
ClientMessage 
SelectionClear 
SelectionNotify 
SelectionRequest 

Abbreviations 

Circ 
Configure 
Destroy 
Gray 
Map 
Create 
Reparent 
Unmap 
CircRec 
ConfigureReq 
MapReq 
Mapping 
Message 
SelClr 
Select 
SelReq 

Description 

Stacking order modified 
Window resized or moved 
Window destroyed 
Window moved due to win gravity attribute 
Window mapped 
Window created 
Window reparented 
Window tmmapped 
Redirect stacking order change to window manager 
Redirect move or resize request to window manager 
Redirect window map request to window manager 
Keyboard mapping changed 
Client-dependent 
Current owner is losing selection 
Selection is ready for requestor 
Request for selection to current owner 

Many of these events are handled automatically by the Toolkit separately from the translation 
mechanism. For example, Expose events are automatically sent to the expose method of 
the appropriate widget. When there is also a translation for Expose events, the action is 
called in addition to the expose method. The only reason you would need a translation for 
Expose events is to add drawing to a Core widget. Because the Core widget doesn't have 
an expose method, there is rarely, if ever, a case where there is both an expose method 
and a translation for Expose events for the same widget. The point to remember is that any 
event can be specified in a translation, even when that event is also used in some other way 
by Xt. 
GraphicsExpose and NoExpose events are useful when your application copies from a 
visible window with XCopyArea or XCopyPlane. They notify the application when pan 
of the source of the cgpy is obscured. If you want GraphicsExpose and NoExpose 
events, you must explicidy elect them by setting the graphics_exposures GC compo- 
nent in the GC used for the copy. Then you can provide a translation for them, or if you are 
writing a widget you can have them sent to your expose method by setting the 
compress_exposure field of the Core structure to a special value, as described in Sec- 
tion 8.6.2. (While xbitmap and BitmapEdit use XCopyArea and XCopyPlane, they copy 
from an off-screen pixmap that cannot be obscured, and therefore GraphicsExpose and 
NoExpose events are not needed. For a description of these events, see Chapter 5, The 
Graphics Context, in Volume One, Xlib Programming Manual.) 
Several of the *Notify events are automatically handled by the Toolkit. Xt places this 
information in internal structures so that it can satisfy queries for widget positions and 
geometries without querying the server. MappingNotify events are automatically ha.n- 

Events, Translations, and Accelerators 1 7 



died; Xt gets the current keyboard mapping from the server. VisibilityNotify events 
are handled automatically if the visible interest field in the Core structure is set to 
TRUE (see Section 8.4.1). 
With the exception of SelectionRequest, the *Request events are intended for use 
only by window managers. The selection events are described in Chapter 10, lnterclient 
Communications. 
Whether or not they are already handled by Xt or in translations, events can also be selected 
explicitly by installing event handlers in a widget (as described in Chapter 8, More Input 
Techniques). 

Details in Keyboard Events 

As you've seen, Xt provides special event abbreviations to specify which pointer button was 
pressed or released. With key events, this approach would be a little impractical, since there 
are so many keys. Instead, the Translation Manager allows you to follow the event specifica- 
tion with an optional detail field. That is: 
<Key> : doit () 
means that you want the doit () action to be invoked when any key has been pressed, 
while: 
<Key>y : doit () 
means that you want the doit ( ) action to be invoked only if the y key has been pressed. 
What you actually specify as the detail field of a Key event is a keysym, as defined in the 
header file <Xll/keysymdef.h>.* Keysyms begin with an xK___ prefix, which is omitted when 
they are used in translations. 
Before we explain any further, we need to review X's keyboard model, which, like many 
things in X, is complicated by the design goal of allowing applications to run equally well on 
machines with very different hardware. 
The keyboard generates KeyPress events, and may or may not also generate Key- 
Release events. These events contain a server-dependent code that describes the key 
pressed, called a keycode. Modifier keys, such as Shift and Control, generate events just like 
every other key. In addition, all key events also contain information about which modifier 
keys and pointer buttons were held down at the time the event occurred. 
Xt provides a routine that translates keycode and modifier key information from an event into 
a portable symbolic constant called a keysym. A keysym represents the meaning of the key 
pressed, which is usually the symbol that appears on the cap of the key. For example, when 
the a key is pressed, the keysym is xK_a; when the same key is pressed while the Shift key is 
held down, the resulting keysym is XK_A (upper case). Note that even though both the a and 

*Note, however, that this file includes foreign language keysym sets that are not always available. Only the MIS- 
CELLANY, LATINI through LATIN4, and GREEK sets are always available. 

198 X Toolkit Intrinsics Programming Manual 



#define XK Aft R 0xFFEA 
-- _ 
#define XK_Super_L 0xFFEB 
#define XK_Super_R 0xFFEC 
#define XK_Hyper L 0xFFED 
-- 
#define XK_Hyper_R 0xFFEE 

/* Right alt */ 
/* Left super */ 
/* Right super */ 
/* Left hyper */ 
/* Right hyper */ 

There are two things you must learn before you can use these modifiers: 

1. Which physical key generates a given keysym, if it is not obvious from the name. 

2. Which modifiers are valid on your server. 

shift 
lock 
control 
modl 
mod2 
mod3 
mod4 
mod5 

The best way to find out what keysym a key generates is with the xev client, which prints 
detailed information about every event happening in its window. To find out a keysym, run 
xev, move the pointer into its window, and then press the key in question. 
On the Sun-3, there is only one control key, on the left side of the keyboard. It generates the 
keysym XK_Control_L. There are two shift keys, one on each side, which generate the 
keysyms xK.__Sh-i ft_L and XK__Shift_R. The Meta modifier is mapped to the keys 
labeled "Left" and "Right." Even though there is an Alternate keyboard key, which gener- 
ates the keysym XK_Alt_R, this key is not recognized as a modifier. There are no Super 
and Hyper keys. 
The list of valid modifiers can be displayed with the xmodmap client, as follows: 
isla% mmxmap 
xmodmap: up to 2 keys per modifier, (keycodes in parentheses): 
Shift L (0x6a), Shift R (0x75) 
-- 
-- 
Caps_Lock (0x7e) 
Control L (0x53) 
-- 
Meta L (0x7f), Meta R (0x81) 
-- 
-- 

That is, either of the two shift keys will be recognized as the Shift modifier, the Caps Lock 
key as the Lock modifier, and either the Left or Right keys as the Meta modifier. The Left 
and Right keys are also mapped to the Modl modifier. The Alt key is not recognized as a 
modifier. 

xmodmap also allows you to add keysyms to be recognized as the given modifier. For 
example, the following command would cause the F1 function key to be recognized as mod2: 

isla% xmxmap -e 'am2 = 

For more information on xmodmap and xev, see Chapter 11 of Volume Three, X Window 
System User's Guide (Second Edition). 

Events, Translations, and Accelerators 

203 



7.1.5.2 Default Interpretation of the Modifier List 

If no modifiers are specified in a translation, the state of the modifier keys and pointer buttons 
makes no difference to a translation. For example, the translation: 
<Key>q : quit ( ) 
will cause the quit action to be invoked when the q key is pressed, regardless of whether 
the Shift, Ctrl, Meta, or Lock key is also held, and regardless of the state of the pointer but- 
tons. 
Likewise, if a modifier is specified, there is nothing to prohibit other modifiers from being 
present as well. For example, the translation: 
Shift<Key>q: quit ( ) 
will take effect even if the Ctrl key is held down at the same time as the Shift key (and the q 
key). 
There are a number of special modifier symbols that can be used to change this forgiving 
state of affairs. These symbols are shown in Table 7-6. 

Table 7-6. Modifier Symbols 

Symbol 

None 

Description 

No modifiers may be present 
No modifiers except those explicitly specified may be present 
Apply shift (and lock) modifier to key event before comparing 
The modifier immediately following cannot be present 

7.1.5.3 

The syntax of these special modifiers symbols is somewhat inconsistent, and made clearest 
by example. 

Prohibiting a Modifier 

The tilde (-) is used to negate a modifier. It says that the specified modifier may not be 
presenL For example: 
Buttonl<Key> : doit ( ) 

204 X Toolkit Intrinsics Programming Manual 



7.1.5.4 

7.1.5.5 

says that doit () should be invoked by a press of any key when button 1 is being held 
down, while: 
Buttonl<Key> : doit ( ) 
says that doit ( ) should be invoked by a press of any key except when button l is being 
held down. 
A ~ applies only to the modifier that immediately follows it. For example: 
-Shift Ctrl<Key>: doit() 
says that doit () should be invoked when Ctrl is held down in conjunction with any key, 
except if Shift is depressed at the same time. 

Requiring an Exact Match 

An exclamation point at the start of a modifier list sms that only the modifiers in that list 
may be present, and must match the list exactly. For example, if the translation is specified 
as: 

!Shift<Key>q: quit () 
the translation will take effect only if the Shift key is the only modifier present; if Caps Lock 
were in effect, or if a pointer button were depressed at the same time, the translation would 
no longer work. 
The modifier None is the same as ! with no modifiers specified. That is: 
None<Key>q : quit ( ) 

or: 

! <Key>q: quit () 
will invoke quit only if no modifier keys at all are pressed. 

Paying Attention to the Case of Keysyms 

The : modifier, like !, goes at the beginning of the modifier list and affects the entire list. This 
one is really in a categbry by itself, since it applies only to Key events. 
Normally, the translations: 
<Key>a : doit () 
and: 
<Key>A : doit ( ) 
have identical results: both will match either a lower-case or an upper-case A. Ieceding 
the translation with a colon makes the case of the keysym significant. For example, to create 
commands like those in the UNIX vi editor, you might specify the following translations: 
: <Key>a : append ( ) \n\ 
: <Key>A : appendToEndOfLine ( ) 
In this case, a and A are distinct. You could achieve somewhat the same result by specifying: 

Events, Translations, and Accelerators 205 



7.1.6.1 

7.1.6.2 

<BtnlDown>, <BtnlUp>, <BtnlDown> : dolt ( ) 
while the second is equivalent to: 
<BtnlDown>, <BtnlUp>, <BtnlDown>, <BtnlUp> : dolt ( ) 
A plus (+) may appear immediately after the count inside the parentheses to indicate that any 
number of clicks greater than the specified count should trigger the action. 
The following translation detects two or more clicks: 
<BtnlDown>(2+) : dolt() 
The maximum count that can be specified is 9. 
In R3, the above click translations would be triggered even if you clicked once, went to 
lunch, and then clicked again when you returned. Xt uses a timing technique to solve this 
problem beginning in R4. The time is controlled by the XtNmultiClickTime applica- 
tion resource, which defaults to 200 milliseconds. If 200 milliseconds or more of idle time 
passes between clicks, Xt does not consider that a match. You can set this resource to differ- 
ent val ues for each display using x t S e t Mu 1 t i C 1 i c k T ime. 

Special Considerations Involving Motion Events 

Beware of interaction between pointer motion events and double clicking. If no motion 
events are specified in a translation table, these events are never selected, so there is no prob- 
lem if they occur between other events. This allows a double click to be detected even if the 
user inadvertently jiggled the pointer in the course of the click. However, if motion events 
are selected for anywhere in the table, they may interfere with the expansion of events speci- 
fied with the repeat notation. By definition, multiple clicks are detected only if there are no 
intervening events. Motion events would usually occur between the button presses and 
releases. 
Multiple motion events will match any single motion selected event in the translation. That 
is: 
<Motion> : dolt () 
will cause doit ( ) to be invoked many times, once for each motion event generated by the 
pointer movement, unless .the compress_motion event filter is turned on in the Core 
class structure. (This filter is described in Section 8.6.2.) 

Modifiers and Event Sequences 

A modifier list at the start of an event sequence applies to all events in the sequence. That is: 
Shi ft<BtnDown>, <BtnUp> : doit ( ) 
is equivalent to: 
Shift<BtnDown>, Shift<BtnUp> : dolt ( ) 
However, if modifiers and events are interspersed, the modifier applies only to the event 
immediately following. As an extreme case to demonstrate this behavior, consider the fol- 
lowing translation: 

Events, Translations, and Accelerators 207 



7.1.7.1 Translations In Multiple Resource Flies 

7.1.7.2 

Much more will be said about resource files and resource matching in Chapter 9, Resource 
Management and Type Conversion. However, in is important to make one point here. 

If several resource files contain translation tables for the same widget, only the one that takes 
priority according to file precedence and resource matching will have any effect even if all of 
them specify #augment or #override. This is because the translation table is the value 
of the resource, and only one resource value will override all other values. 

In other words, even if all the translation tables specify #augment or #override, a max- 
imum of two translation tables are merged by Xt: the widget's default translation table and 
the one translation table that takes priority as determined by the process of reading and merg- 
ing all the resource files (and the command line) and then the process of resource matching. 
If you call XtOverrideTranslations or XtAugmentTranslations in the appli- 
cation, this is a third level of merging, but it is unrelated to the resource files. 

Order of Translations 

The order of translations in a table is important, because the table is searched from the top 
when each event arrives, and the first match is taken. Therefore, more specific events must 
appear before more general ones. Otherwise, the more specific ones will never be reached. 

For example, consider a text entry widget that wants to close itself and dispatch a callback 
once the user presses the Return key, indicating that entry is complete. The widget's transla- 
tions might be: 
<Key>Return : gotData ( ) \n\ 
<Key> : insertChar ( ) 

If the translations we specified in the ver order: 
<Key>: insertChar() \n\ 
<Key>Return: gotData() 

insertChar () would be called in response to a press of the Return key, and got- 
Data ( ) would never be called. 

Keeping track of translation order is made more complicated when translations are merged. 
For example, if one of the above lines is in the default translations of a widget class, and the 
other is in a translation table in a resource file, in what order are the resulting translations? 
Though not documented in the Xt specification, it appears that the MIT implementation of Xt 
places the more specific translation first. 

Events, Translations, and Accelerators 209 



7.1.7.3 Event Sequences Sharing Initial Events 

7.1.7.4 

An exception to this rule of more specific translations being placed earlier in the translation 
table occurs with event sequences. One translation can contain an event or event sequence 
that appears in another translation. If the leading event or event sequence is in common, both 
will operate correctly. For example, the translations: 
<BtnlDown>, <BtnlOp> : actionB ( ) \n\ 
<BtnlDown> : actionA ( ) 
execute actionA ( ) when button 1 is pressed and actionB ( ) when it is then released. 
This is true regardless of which translation appears first in the table. 
This is the reason, alluded to in Chapter 2, Introduction to the X Toolkit, why it is not pos- 
sible to bind two different actions to a single and a double click of the same button in the 
same widgeL Specifying: 
<BtnlOp>(2) : quit() \n\ 
<BtnlDown>, <BtnlUp> : confirm ( ) 
will invoke the confirm() action on a single click and both the confirm() and 
quit: ( ) actions on a double click. 
This behavior was a design decision on the part of the X Consortium. Otherwise, the Intrin- 
sics could never dispatch the single-click action until the double-click interval had passed, 
since it would have no way of knowing if a second click was coming. Applications needing 
to have single and double clicks in the same widget must do so by designing the two actions 
appropriately, rather than relying on the Translation Manager to make the distinction. 

Event Sequences Sharing Noninitlal Events 

If a noninitial event sequence is common between two translations, each translation will 
match only event sequences where the preceding event does not match the other translation. 
Consider the translation: 
<BtnlDown>, <BtnlOp> : actionB () \n\ 
<BtnlUp> : actionA ( ) 
When a BtnlUp event occurs, it triggers actionA ( ) only if not preceded by BtnlDown. 
The way this works is that Xt keeps a history of recent events. When each event arrives, Xt 
compares this event and its immediate history to the event sequences in a translation table. 
An event in the sequence may have already triggered an action, but that is irrelevent. Any 
translation whose final event in the event sequence matches the current event and whose ear- 
lier event sequence matches the event history is matched. If there are two translations that 
can match a particular event sequence, then the translations are considered overlapping, the 
latter will override the former, and Xt will print a run-time warning message at startup (not 
waiting for the overlapping actions to be invoked). This is an exception to the rule stated 
earlier that the translation manager executes the first match. 

210 X Toolkit Intdnsics Programming Manual 



Figure 7-1. xboxl : two Command widgets in a Box 

To add accelerators requires a single line of code--a call to XtInstallAccelerators, 
as shown in Example 7-I. 

Examp 1. slling accera  an application 
main(argc, argv) 
int argc; 
char **argv; 
( 
XtAppContext app_context; 
Widget topLevel, box, quit; 

/* allow quit widget's actions to be invoked by events in box. */ 
XtInstallAccelerators(box, quit); 
XtAppMainLoop (app_context) ; 
) 
The actual value of the accelerator table is set tlough the resource mechanism. The Xt- 
Naccelerators resource is set for the widget whose actions a/e to be invoked from 
another widget Xt stores this accelerator table, in compiled form, in the widget's instance 
structure when the widget is created. When the application calls XtInstall- 
Accelerators, the accelerator table stoxl in the widget is merged with the translation 
table of the widget that will be capturing the events. (If XtRemoveAccelerators is 
called, the original translation table, prior to merging with the accelerators from the source 
widget, is restored.) 
Example 7-2 shows a possible application-defaults file. 

Example 7-2. Specifying the XtNaccelerators resource from the application-defaults file 
*quit. label : Quit 
*pressme. label: Press me 
*quit .accelerators : \n\ 
<KeyPress>q : set() notify() 
This resource setting will allow a q typed anywhere in the Box widget that comprises the 
xboxl application window to invoke the quit widget's notify ( ) action (which, as you may 

212 X Toolkit Int6nsics Programming Manual 



All of the Athena widgets inherit the Core widget's display_accelerators method 
by initializing the appropriate member of the class structure to XtInheritDisplay- 
Accelerators. This default method, as implemented in the MIT distribution, does noth- 
ing. 

Events, Translations, and Accelerators 

217 



8 

More Input Techniques 

This chapter describes how to handle events with event handlers, and how to 
use information from the event structure inside an event handler or action 
routine. It also describes how to get file, pipe or socket input, how to use 
timeouts to call a function after a delay or at particular intervals, and how to 
use work procedures to do background processing. Finally, ff discusses 
some low-level features of Xt for directly interacting with the event queue. 

In This Chapter: 

Event Handlers .................................................................................. 222 
Adding Event Handlers .................................................................. 224 
Adding Nonmaskable Event Handlers ............................................ 225 
Removing Event Handlers ............................................................. 226 
Adding Raw Event Handlers .......................................................... 227 
Writing Routines That Use Specific Event Data .................................. 227 
Event Types and Structure Names ................................................. 229 
File, Pipe, and Socket Input ............................................................... 230 
Getting File !npu_t ........................................................................... 231 
Getting Pipe Input .......................................................................... 233 
Timeouts ........................................................................................... 234 
Visibility Interest ............................................................................. 237 
Work Procedures ............................................................................... 239 
Low-level Management of the Event Queue ....................................... 241 
XtPending and XtPeekEvent .......................................................... 241 
Event Filters .................................................................................. 242 
Input Sensitivity ............................................................................. 243 



Table 8-1. Event Masks and Event Types 

Event Mask 

KeyPressMask 
KeyReleaseMask 
ButtonPressMask 
ButtonReleaseMask 
OwnerGrabButtonMask 
KeymapStateMask 
PointerMotionMask 
PointerMotionHintMask 
ButtonMotionMask 
ButtonlMotionMask 
Button2MotionMask 
Button3MotionMask 
Button4MotionMask 
Button5MotionMask 
EnterWindowMask 
LeaveWindowMask 
FocusChangeMask 

ExposureMask 
secd  GC by 
graphics_exposecomponent) 
ColormapChangeMask 
PropertyChangeMask 
VisibilityChangeMask 
ResizeRedirectMask 
StructureNotifyMask 

SubstructureNotifyMask 

SubstructureRedirectMask 

(always selec..ed) 

Event Type 

KeyPress 
KeyRelease 
ButtonPress 
ButtonRelease 
KeymapNotify 
MotionNotify 

EnterNotify 
LeaveNotify 
FocusIn 
FocusOut 
Expose 
GraphicsExpose 
NoExpose 
ColormapNotify 
PropertyNotify 
VisibilityNotify 
ResizeRequest 
CirculateNotify 
ConfigureNotify 
DestroyNotify 
GravityNotify 
MapNotify 
ReparentNotify 
UnmapNotify 
CirculateNotify 
ConfigureNotify 
CreateNotify 
DestroyNotify 
GravityNotify 
MapNotify 
ReparentNotify 
UnmapNotify 
CirculateRequest 
ConfigureRequest 
MapRequest 
MappingNotify 

More Input Techniques 

223 



Table 8-1. Event Masks and Event Types (continued) 

Event Mask 

(always selected) 
(always selected) 
(always selected) 
(always selected) 

Event Type 

ClientMessage 
SelectionClear 
SelectionNotify 
SelectionRequest 

The events that are always selected are called nonmaskable events. These can also be han- 
dled with an event handler, but not by specifying them in the event mask. An argument to the 
XtAddEventHandler call, non__maskable, is a Boolean value that, if TRUE, specifies 
that the event handler should be called for nonmaskable events. This event handler then must 
branch according to which of the seven types of nonmaskable events it is passed. A typical 
nonmaskable event handler is shown in Section 8.1.2. 

8.1.1 

Adding Event Handlers 

Event handlers are added with a call to XtAddEventHandler or XtInsertEvent- 
Handler. XtAddEventHandler takes five arguments: the widget for which the handler is 
being added, an event mask, a flag that specifies whether or not this handler is for nonmask- 
able events (see below), the name of the handler, and optional client data. XtInsert- 
Eventnandler takes these and one additional argument: the position, either XtListTail 
or XtListHead. 
A list of event handlers can be registered for the same event; but the same function will 
appear only once in the list with the same client_data. If the same function/client_ 
data pair is registered again with XtAddEventHandler, nothing will happen except that 
the event mask for that function may change. But if the same function/client_data pair is 
registered again with XtInsertEventHandler, the function will be moved to the begin- 
ning or the end of the function list. 
XtAddEventHandler or Xt InsertEventHandler may be called before or after a widget 
is realized. In application code, this means the call can appear anywhere before XtApp- 
MainLoop. In a widget, XtAddEventHandler or XtInsertEventHandler calls are 
placed in the initialize or realize methods. 
Example 8-1 shows the code from xterm that registers an event handler for FocusIn and 
FocusOut events, and a gutted version of the event handler itself. 

Example 8-1. Registering an event handler, and the handler function itself 
extern void HandleFocusChange(); 

static void VTInitialize (request, new) 
XtermWidget request, new; 
{ 

224 X Toolkit Intrinsics Programming Manual 



whenever they occur. MappingNotify is automatically handled by Xt, so it isn't passed 
to event handlers and you don't need to worry about it. The selection events are described in 
Chapter 10, Interclient Communications. 
Because there are several nonmaskable event types, a nonmaskable event handler must be 
sure to branch according to the type of event, and throw away any event types not handled. 
You need not have all the code to handle all the types in a single event handler. Instead, you 
can handle each type in a separate handler, each registered separately. However, each han- 
dler would still need to check the event type because the entire list of them would be called 
for every nonmaskable event. 
Example 8-2 shows the registration of a nonmaskable event handler and the handler itself, 
from xman. 

ExampM 8-2. Adding a nonmaskabM event handler 
static void 
Realize(w, valueMask, attributes) 
register Widget w; 
Mask *valueMask; 
XSetWindowAttributes *attributes; 
{ 

XtAddEventHandler(w, 0, TRUE, 
GExpose, NULL) ; /* Get Graphics Exposures */ 
} /* Realize */ 
/* ARGSUSED */ 
static void 
GExpose(w, client_data, event) 
Widget w; 
XtPointer client data; 
-- 
XEvent *event; 
{ 
if (event->type == GraphicsExpose) 
Redisplay(w, event, NULL); 
) 
This event handler is sometimes used because Xt does not normally call the expose method 
in response to GraphicsExpose events. But in R4, another way to accomplish this has 
been in[roduced. If the compress_exposure field in the Core structure is set to (Xt- 
ExposeCompressMultiple I XtExposeGraphicsExpose), Xt will call the 
expose method with these events. 

/*call the expose method directly*/ 

8.1.3 Removing Event Handlers 

XtRemoveEventHandler takes the same arguments as XtAddEventHandler; if 
there are parameter mismatches, the call is quietly ignored. For example, the client data 
argument may be used to distinguish between different event handlers; if the client data argu- 
ment does not match that which was passed in the XtAddEventHandler, then 

226 X Toolkit Intrinsics Programming Manual 



Many action routines are intentionally written not to depend on the detailed information 
inside any particular type of event, so that the user can specify translations to call the action 
in response to different types of events. For example, it is useful for an action routine nor- 
mally triggered by a pointer click to work when called in response to a key instead. Such an 
action should not depend on the event structure fields unique to buuon events. 
However, many other action routines, and most event handlers, do use the detailed informa- 
tion inside event structures. The first member, type, identifies which type of event this 
structure represents, and hence implies which other fields are present in the structure. 
To access event structure fields other than type you need to cast X.vent into the appropri- 
ate event structure type. If you are expecting only one type of event to trigger this action, 
then you can simply declare the argument as the appropriate type, as shown in Example 8-3. 

Examp 8-3. Casting e event structure by declaring action routine aumen 
/*ARGSUSED*/ 
static void 
ActionA(w, event, params, num_params) 
Widget w; 
XEvent *event; 
String *params; 
Cardinal *num_params; 
if ((event->type != ButtonPress) && 

(event->type != KeyPress)) { 
XtWarning("ActionA invoked by wrong event type."); 
/* possible exit here */ 

When an action routine or event handler depends on the fields in a particular event structure, 
it is a good practice to check the event type in that action unless you are sure that the user 
can't change the translation (and thus the events used to invoke the action). 

If you want the same code called for two event types, then you would do better to create two 
separate translations and two separate actions that each call a common routine. However, it 
is sometimes more convenient to have an action called by two different events. Example 8-4 
shows the ToggleCell action from the BitmapEdit widget, which is called in response to 
either NotionNotify or ButtonPress events. This action inverts a pixel in the bit- 
map either if the pointer is clicked on a cell in the widget, or if it is dragged across the cell 
with the pointer buttons held down. 

Examp 84. Handling muiple event pes  an action routine 
static void 
ToggleCell(w, event) 
Widget w; 
XEvent *event; 
{ 
BitmapEditWidget cw = (BitmapEditWidget) w; 
static int oldx = -I, oldy = -I; 
GC gc; 
int mode; 

228 X Toolkit Intrinsics Programming Manual 



Table 8-2. Event Types and Event Structures 

Event Type 

KeyPress 
KeyRelease 
ButtonPress 
ButtonRelease 
KeymapNotify 
MotionNotify 
EnterNotify 
LeaveNotify 
FocusIn 
FocusOut 
Expose 
GraphicsExpose 
NoExpose 
ColormapNotify 
PropertyNotify 
VisibilityNotify 
ResizeRequest 

CirculateNotify 
ConfigureNotify 
DestroyNotify 
GravityNotify 

MapNotify 
ReparentNotify 
UnmapNotify 
CirculateRequest 

ConfigureRequest 

MapRequest 

MappingNotify 
ClientMessage 
SelectionClear 
SelectionNotify 
SelectionRequest 

Structure 

XKeyPressedEvent 
XKeyReleasedEvent 
XButtonPressedEvent 
XButtonReleasedEvent 
XKeymapEvent 
XPointerMovedEvent 
XEnterWindowEvent 
XLeaveWindowEvent 
XFocusInEvent 
XFocusOutEvent 
XExposeEvent 
XGraphicsExposeEvent 
XNoExposeEvent 
XColormapEvent 
XPropertyEvent 
XVisibilityEvent 
XResizeRequestEvent 

XCirculateEvent 
XConfigureEvent 
XDestroyWindowEvent 
XGravityEvent 

XMapEvent 
XReparentEvent 
XUnmapEvent 
XCirculateRequestEvent 

XConfigureRequestEvent 

XMapRequestEvent 

XMappingEvent 
XClientMessageEvent 
XSetSelectClearEvent 
XSelectionEvent 
XSelectionRequestEvent 

Descfipdon 

Key pressed 
Key released 
Pointer button pressed 
Pointer button released 
State of all keys when pointer entered 
Pointer modon 
Pointer entered window 
Pointer left window 
This window is now keyboard focus 
This window was keyboard focus 
Part of window needs redrawing 
Source of copy unavailable 
Source of copy available 
Window's colormap changed 
Property value changed 
Window has been obscured 
Redirect resize request to window 
manager 
Stacking order modified 
Window resized or moved 
Window destroyed 
moved due to win gravity 

Window 
attribute 
Window mapped 
Window reparented 
Window unmapped 
Redirect stacking order change to 
window manager 
Redirect move or resize request to 
window manager 
Redirect window map request to win- 
dow manager 
Keyboard mapping changed 
Client-dependent 
Current owner is losing selection 
Selection is ready for requestor 
Request for selection to current owner 

230 X Toolkit Intrinsics Programming Manual 



8.3 File, Pipe, and Socket Input 

XtAppAddInput allows a program to obtain input from a file. This is not merely reading 
the file once, but monitoring it for further activity. Under UNIX this can be used to get input 
from pipes and sockets, since they are variations of files. We will demonstrate getting file 
and pipe input in this section. 
The XtAppAddInput routine takes four arguments: a file descriptor, a flag (see below), 
your function, and cl i en t da t a. 
XtAppAddInput returns an ID that uniquely identifies the XtAppAddInput request. 
You can use the ID to cancel the request later with XtRemoveInput. 
One argument of XtAppAddInput is a file descriptor (this file must be open before calling 
XtAppAddInput). Since implementation of files varies between operating systems, the 
actual contents of the parameter passed as the file descriptor argument to these routines is 
operating system-dependent. Therefore, this code is inherently nonpormble. 
Possible values for the mask and their meanings are as shown in Table 8-3. 

Table 8-3. Other Input Source Masks 

Mask 

XtInputReadMask 
XtInputWriteMask 
XtInputExceptMask 
XtInputNoneMask 

Descripdon 

File descriptor has dam available 
File descriptor available for wridng 
I/O errors have occurred (exceptions) 
Never call function registered 

Calling these argument values masks is something of a misnomer, since they cannot be ORed 
together. However, you can call XtAppAddTnput additional times to register a separate 
function (or the same function) for each of these masks on the same file descriptor. 

8.3.1 

Getting File Input 

In Example 8-5, a program called xJileinput reads new characters from a file whenever they 
appear. In other words, the program will initially print to the standard output the contents of 
the file specified on the command line, and it will print any characters that are later appended 
to that file. Try the program xJileinput as follows: 
echo "test string" > testfile 
xfileinput testfile & 
echo "more text" >> testfile 
A program such as this functions similarly to the UNIX command tail -f. It could be used to 
monitor system log files, or other similar files that grow. 

More Input Techniques 231 



The code shown in Example 8-5 opens the file and calls XtAppAddlnput in main. The 
get_file_input function registered with XtAppAddlnput reads and prints charac- 
ters from the file.* 

Example 8-5. Getting file input with XtAppAddlnput 
/* header files */ 

/* ARGSUSED */ 
get_file_input(client_data, fid, id) 
XtPointer client data; /* unused */ 
int *fid; 
XtInputId *id; 
char buf[BUFSIZ]; 
int nbytes; 
int i; 
if ((nbytes = read(*fid, buf, BUFSIZ)) == -I) 
perror ( "get_file_input" ) ; 
if (nbytes) 
for (i = 0; i < nbytes; i++) 
putchar(buf[i]) ; 
} 
main(argc, argv) 
int argc; 
char **argv; 
{ 
XtAppContext app_context; 
Widget topLevel, goodbye; 
FILE *fid; 
String filename; 
topLevel = XtVaAppInitialize(&app_context, "XFileInput", NULL, 
0, &argc, argv, NULL, NULL); 
if (argv[l] == NULL) { 
fprintf(stderr, "xfileinput: filename must be specified on\ 
command line.\n"); 
exit(l); 
} 

filename = argyll]; 

/* open file */ 
if ((fid = fopen(filename, "r")) == NULL) 
fprintf(stderr, "xfileinput: couldn't open input file.\n"); 
/* register function to handle that input, NULL arg 
* is client data */ 
-- 
*Ncatccodcropcningand adgfisispbaynportablctoomtingsystemsocranUNIX. 

232 X Toolkit Intrinsics Programming Manual 



mmmmm 

Figure 8-1. xtetris in play 

Every time a row is completely filled, it is removed and all the blocks above it move down 
one row. The window in which the blocks fall is a specialized widget. This game uses 
timeouts to time the falling of the blocks. 

Example 8-7 is an excerpt from a widget used by xtetris that adds the timeout. The timeout 
function itself is also shown. 

More Input Techniques 235 



8.4.1 

Example 8-8. xtetris : calling XtRemove TimeOut 
/*ARGSUSED*/ 
static void 
Drop(tw, tevent, params, num_params) 
Widget tw; 
XEvent *tevent ; 
String *params; 
Cardinal *num_params; 
{ 
TetrisWidget w = (TetrisWidget) tw; 
XButtonEvent *event = (XButtonEvent *) tevent; 
XtRemoveTimeOut (timer) ; 
while (CanMoveDown(w)) { 
DrawBlock(w, UNDRAW) ; 
w->bitmapEdit, cur_y++; 
DrawBlock(w, DRAW) ; 
CopyBlock (w) ; 
} 
UpdateCellArray (w) ; 
KillRows (w) ; 
score++; 
Score (w) ; 
w->bitmapEdit.delay-= 5; 
StartBlock (w) ; 
} 
Notice [hat [he timer ID returned from the calls to XtAppAddTimeOut is a global 
able. Xt calls [he timeout function with only one argument, and that argument passes in the 
widget instance pointer. We could have created a structure containing the widget instance 
pointer and the timer ID and passed its pointer to the timeout function. But this wouldn't 
help, because [he action routine in which we remove the timeout is passed with no 
client_data argument. (It has string parameters, but these are hardcoded in the actions 
table.) Therefore, we are forced to have a global variable for the timer ID. 
Note [hat between [he time when the timeout is registered and when it triggers, the applica- 
tion processes events in XtAppMainLoop. Therefore, all the widget's actions and 
expose method are in operation between the invocations of the timeout function. 

Visibility Interest 

Timeouts operate regardless of the visibility of the application. Since it is pointless for most 
games to continue operating while obscured, it makes sense to remove the game's timeouts 
when the game is partially or fully obscured (or iconified). To do this, you can set the vi s- 
ible interest field in the Core class structure to TRUE, and [hen check the visible 
field of [he Core instance structure periodically. When the application is fully obscured, you 
add a separate timeout to continue testing the visibility status. When the visibility status is 
satisfactory once again, the game can add its timeout again. All these changes are in the 
widget's .c file. First we set the visible_interest field to TRUE in the Core structure: 

More Input Techniques 237 



Examp 8-10. A woprocedure  crea apop-upwidget 
Widget pshell; 
/* work procedure */ 
Boolean 
create_popup(client _data) 
XtPointer client data; 
-- 
{ 
Widget parent = (Widget) client data; 
-- 
Widget dialog, dialogDone; 
pshell = XtCreatePopupShell( 
"pshell", 
transientShellWidgetClass, 
parent, 
NULL, 
0 
); 

dialog = XtCreateManagedWidget( 

"dialog", 
dialogWidgetClass, 
pshell, 
NULL, 
0 
); 

/* widget name */ 
/* widget class */ 
/* parent widget */ 
/* argument list */ 
/* arglist size */ 

dialogDone = XtCreateManagedWidget( 

"dialogDone", 
commandWidgetClass, 
dialog, 
NULL, 
0 
); 

/* widget name */ 
/* widget class */ 
/* parent widget */ 
/* argument list */ 
/* arglist size */ 

XtAddCallback(dialogDone, XtNcallback, DialogDone, dialog); 
return(True) ; /* makes Xt remove this work proc automatically */ 
Remember that Xt cannot interrupt a work procedure while it is running; the procedure must 
voluntarily give up control by returning, and it must do so quickly to avoid slowing user 
response. 
If your application has any big jobs that it must do, the only way to do them without resulting 
in long delays is to write the code that does the big job in a way that voluntarily interrupts 
itself and saves its state so that it can be restarted where it left off. One way to run such a 
task is as a work procedure, but this is only useful for tasks that need not be done before other 
application tasks can begin. If you want Expose processing to continue but no other appli- 
cation task to begin until your task is done, you would use the same type of code but place 
low-level event management routines in it, or make the rest of the application insensitive 
until the task is done. 

240 X Toolkit Intrinsics Programming Manual 



8.6 Low-level Management of the Event Queue 

As you know, an X Toolkit application simply calls XtAppMainLoop tO begin processing 
events. XtAppMainLoop itself is quite simple: it consists of an infinite loop calling two 
lower-level routines, XtAppNextEvent and XtDispatchEvent. XtAppNext- 
Event extracts the next event from the application's event queue; XtDispatchEvent 
actually uses the event to invoke the appropriate actions or event handlers. (The functions 
registered by XtAppAddInput and XtAppAddTimeOut are dispatched directly by Xt- 
AppNextEvent; if no events are available, XtAppNextEvent flushes the X ouqut buf- 
fer, and calls any work procedures registered by XtAppAddWorkP roc.) 

An application can provide its own version of this loop, as shown in Example 8-11. For 
example, it might test some application-dependent global flag or other termination condition 
before looping back and calling XtAppNextEvent. Or for fine-grained debugging, it 
might be worthwhile to insert a routine that prints out the type of each event dispatched. 

Example 8-11. Skeleton of a custom main loop 
void MyMainLoop (app_con) 
XtAppContext app_con; 
( 
XEvent event; 
for (;;) ( 
XtAppNextEvent(app_con, &event) ; 
XtDispatchEvent (&event) ; 
/* Do application-specific processing here */ 
} 
} 

8.6.1 

XtPending and XtPeekEvent 

All event sources depend on idle time in the application to return to XtAppMainLoop 
where Xt can check to see if input is available from any of the various sources. If an applica- 
tion has long calculations to make, the program may not return to XtAppMainLoop fre- 
quently enough to detect important input in a timely fashion. The application itself should, if 
possible, suspend lengthy calculations for a moment to check whether input is available. 
Then it can determine whether to process the input before continuing, or finish the calcula- 
tion. 
To detect whether input from any input source is available, you can call XtPending. This 
function returns a mask composed of a bitwise OR of the symbolic constants XtIMXEvent, 
XtIMTimer, and XtIMAlternateInput. These constants refer to X events, timer 
events, and alternate input events, respectively. 
To find out what the first event in the queue contains, you can call XtPeekEvent. This 
function returns an event structure without removing the event from Xlib's queue. 

More Input Techniques 241 



When ORed with any of the XtCompress* symbols, the XtExposeGraphicsExpose 
symbol causes Xt to call the expose method with any GraphicsExpose events that 
occur. Remember that you must set the graphics_exposures component to True in 
the GC used in XCopyArea or XCopyPlane in order to get GraphicsExpose events. 
XtExposeGraphicsExposeMerged, when ORed with an XtCompress* symbol, 
merges contiguous Expose and GraphicsExpose events together before calling the 
expose method. 

The XtExposeNoExpose symbol causes Xt to dispatch NoExpose events to the 
expose method. This doesn't make much sense; if you need NoExpose events it is better 
to add an event handler or translation to handle them. 

The remaining symbol is XtExposeCompressMaximal. This symbol is dangerous and 
should not be used: it merges non-continuous Expose events into one event before calling 
the expose method. This is unwise because the intervening events could be 
ConfigureNotify events that change the size of the window. When this happens, the 
application will redraw itself, then receive the ConfigureNotify, but then it will not 
redraw itself in the new size because the Expose event that would trigger the drawing has 
already been removed from the queue. 

Almost all widgets except those that display a large amount of text should set this filter to 
XtExposeCompressMultiple. Text widgets can very efficiently redraw only the 
needed pans of the window because each character is in a fixed location. (Characters are in 
fixed locations in the Text widget because it uses fixed-width fonts--this is not applicable to 
widgets that display proportional fonts.) Therefore, it can efficiently process all the Expose 
events one at a time. 

Input Sensitivity 

There are times when some widgets should be insensitive to events in which they are usually 
interested. For example, a Command widget should be insensitive when the command that it 
executes is already in operation. 

Widget sensitivity is inherited. For example, if a parent widget is insensitive, then its chil- 
dren are too. In other words, an entire box full of widgets can be set insensitive by simply 
setting the box widget insensitive. Note, however, that this process can be a little slow 
because all the widgets in the box that honor sensitivity will redraw themselves dimmed or 
grayed. A widget is made insensitive from an application by calling xtSetSensitive 
with the sensitive argument set to FALSE, or using XtVaSetValues on the Xt- 
Nsensitive resource (XtSetSensitive is slightly faster). 

Any widget that may need to be disabled for a time by the application should change its visi- 
ble appearance when insensitive. 
The widget that has one of the XtCallback* standard pop-up callback functions regis- 
tered on its callback list will automatically be set insensitive when the callback is triggered. 
If the XtCallbackPopdown callback function is registered on this widget it will auto- 
matically be set sensitive again when this callback is invoked. 

More Input Techniques 243 



9 

Resource Management 
and Type Conversion 

This chapter is a more thorough discussion of how resources work and how 
they should be used. This chapter describes in detail the resource file format 
and the rules that govern the precedence of resource settings. It also 
describes how to add your own type converter so that you can have applica- 
tion or widget-specific data set through resources. Finally, it describes 
subresources and how to use them. 

In This Chapter: 

Review of Resource Fundamentals .................................................... 248 
How the Resource Database Works ................................................... 251 
Form of Resource Specifications ................................................... 252 
Merging of Resource Files ............................................................. 253 
The Language String ..................................................................... 255 
Fallback Resources ....................................................................... 257 
Resource.Matching Algorithm ........................................................ 258 
Resource Precedence Rules ......................................................... 260 
Type Conversion ................................................................................ 263 
Conversions from XtRString ........................................................... 263 
Other Built-in Type Conversions ..................................................... 266 
Special Resource Defaults That Do Not Use Conversion ............... 267 
Registering Type Converters .......................................................... 269 
Passing Arguments to a Type Converter ...................................... 272 
Explicitly Invoking a Converter ....................................................... 274 
Writing a Type Converter ................................................................ 275 
Defining the Default Value ............................................................ 277 
Subparts and Subresources ............................................................... 278 
The Hook Methods ........................................................................ 279 
Managing Subresources ................................................................ 279 



9 
Resource Management 
and Type Conversion 

This chapter provides a thorough discussion of how resources work and how they should be 
used. First, we describe how to define resources, the complete syntax of resource files, and 
the rules that describe the precedence of one resource setting over another. For the sake of 
completeness, and to make sure that the ideas are presented in context, there is some repeti- 
tion of material that has been presented earlier. 
Next, the chapter describes the resource conversions performed automatically by Xt. As you 
may recall from the discussion in Chapter 2, Introduction to the X Toolkit, a value converter 
is invoked by Xt to convert a resource from the string form specified in resource files to the 
representation type actually used in the application or widget. For the representation types 
understood by Xt, simply listing the representation symbol (a constant beginning with x:r) 
in the resource list is enough to make Xt automatically perform the conversion. But if you 
create a representation type unknown to Xt, you need to write a type converter routine and 
register it with Xt before the automatic conversion can take place. We discuss both the stan- 
dard converters and how to write a new one. 
Finally, the chapter describes a mechanism Xt provides whereby widgets or applications may 
have subparts with separate sets of resources. Special routines are provided for setting and 
getting these resources. The R3 Athena Text widget used subparts to implement replaceable 
units that provide the data storage and display for text data. This allowed the same central 
code to edit a disk file or a string. But using subparts is now out of favor; the R4 Text widget 
uses objects to accorriplish the same modularity (see Chapter 13, Miscellaneous Toolkit Pro- 
gramming Techniques). 

Resource Management and Type Conversion 247 



upper case. For example, the resource name for a variable named border width would 
-- 
be borderWidth, and the defined constant used to refer to this name would be Xt- 
NborderWidth. 
As described previously, the name, class, and representation type of resources are speci- 
fied in the resource list (and elsewhere in Xt code, but not in user database files) using 
symbolic constants defined in <X11/StringDefs.h>, and consist of the actual name, class, 
or type preceded by the characters XtN, XtC, or XtR, respectively. Use of these con- 
stants provides compile-time checking of resource names, classes, and types. Without the 
constants, a misspelling would not be noticed by the compiler, since resource names, 
classes, and representation types are simply strings. The misspelling would be considered 
a real resource at run time. Nothing would happen if it were set from the application, 
because no widget would actually use it. If, on the other hand, the misspelling were in 
the widget resource list, the application's setting of the intended resource would have no 
effect. 
Newly-defined resources may use a name, class, or type constant defined in <Xll/String- 
Defs.h>, if an appropriate one exists. Otherwise, the constant is defined in the widget's 
public header file, or for application resources, in the application itself, or in the applica- 
tion header file, if any.) 
For many resources, the class name is simply the same as the resource name, except that 
the xtc prefix is used, and, by convention, the first letter of the name is capitalized. For 
example, the class name constant for the XtNbackgroundPixel resource is Xt- 
CBackgroundPixel. However, when appropriate, a single class can be used for a group 
of related resources. This allows a single setting in the resource database to control the 
value of multiple resources. 
For example, a widget can have several elements that use pixel values (i.e., colors) as 
resource settings: background, foreground, border, block cursor, pointer cursor, and so 
on. Typically, the background defaults to white and everything else to black. If the 
background resource has a class of Background, and all the other pixel resources a 
class of Foreground, then a resource file needs only two lines to change all background 
pixels to offwhite and all foreground pixels to darkblue: 
*Background : offwhite 
*Foreground : darkblue 

The representation type of the resource is specified by the resource_type field of the 
resource list, using a symbolic constant prefixed by XtR. Table 9-1 lists the correspon- 
dence between the XtR symbols defined by Xt, and actual C data types or X data types 
and structures. 

Resource Management and Type Conversion 249 



Table 9-1. Resource Type Strings 
Resource Type 

XtRAcceleratorTable 
XtRAtom 
XtRBitmap 
XtRBoolean 
XtRBool 
XtRCallback 
XtRCallProc 
XtRCardinal 
XtRColor 
XtRColormap 
XtRCursor 
XtRDimension 
XtRDisplay 
XtREnum 
XtRFile 
XtRFloat 
XtRFont 
XtRFontStruct 
XtRFunction 
XtRGeometry 

XtRImmediate 
XtRInitialState 
XtRInt 
XtRLongBoolean 
XtRObject 
XtRPixel 
XtRPixmap 
XtRPointer 
XtRPosition 
XtRScreen 
XtRShort 
XtRString 
XtRStringArray 
XtRStringTable 
XtRTranslationTable 
XtRUnsignedChar 
XtRVisual 
XtRWidget 
XtRWidgetClass 
XtRWidgetList 
XtRWindow 

Dam type 

XtAccelerators 
Atom 
Pixmap (of depth 
Boolean 
Bool 
XtCallbackList 
see fnal bullet bew 
Cardinal 

one) 

XColor 
Colormap 
Cursor 
Dimension 
Display * 
XtEnum 
FILE * 
float 
Font 
XFontStruct * 
(*) () 
String - rmat  defined by 
XParseGeometry 
see final bult below 
int 
int 
long 
Object 
Pixel 
Pixmap 
XtPointer 
Position 
Screen * 
short 
char * 
String * 
char ** 
XtTranslations 
unsigned char 
Visual * 
Widget 
WidgetClass 
WidgetList 
Window 

250 X Toolkit Intrinsics Programming Manual 



As we'll discuss in detail in Section 9.3, Xt automatically converts values in the resource 
database (which always have the type XtRString, since resource files are made up 
entirely of strings) into the target type defined by resource_type. 
The resource_size field is the size of the resource's actual representation in bytes; 
it should always be specified as si zeof (type) (where type is the C-language type 
of the resource) so that the compiler fills in the value. 
The resource_offset field is the offset in bytes of the field within the widget 
instance structure or application data structure. The xtOffsetOf macro is normally 
used to obtain this value. This macro takes as arguments the data structure type, and the 
name of the structure field to be set by the resource. 
If no value is found in the resource database, the value pointed to by the 
default_address field will be used instead. The type of this default value is given 
by the default_type field. If the default_type is different from the 
resource_type, a conversion will be performed automatically in this case as well. 
There are two special resource types that can be used only as the default_type. 
XtRImmediate means that the value in the default address field is to be used 
-- 
as the actual resource value, rather than as a pointer to it (or in the case of a string, the 
value is a pointer to a string, instead of a pointer to a pointer to a string). The other spe- 
cial resource type, XtRCallProc, is a pointer to a function that will supply the default 
value at run time. We'll demonstrate the use of these values in Section 9.3.3. 

9.2 How the Resource Database Works 

Xt's resource handling is based on the resource manager built into Xlib, but Xt adds a great 
deal. While using the resource manager from Xlib is cumbersome, from Xt it is easy: to use 
resources in existing widgets, all you have to do is write the application-defaults file. 

Xt's handling of resources occurs in two stages: 

When the application starts up, with a call to XtAppInitialize, Xt reads the appli- 
cation-defaults file, along with several other resource files, command line options, and the 
RESOURCE_MANAGER property stored in the server by the user with xrdb. (Any, all, or 
none of these may contain data.) It merges all these sources of data into one internal 
database that is used when each widget is created. 

. 

Whenever you create a widget, the call to XtVaCreateManagedWidget reads the 
resource database and automatically sets widget resources to the values in the database. 
In order to explain this stage more clearly, we further divide it into two separate steps in 
the sections that follow. First, Xt compares the settings in the database to the widget's 
class and instance hierarchy, to find which settings apply to the widget being created. 
Second, Xt decides which of the (possibly conflicting) settings that apply to that widget 
should actually be used. 

Resource Management and Type Conversion 251 



Figure 9-1 shows where Xt looks for resource files and in what order, on most UNIX-based 
systems. The exact directories are operating system and implementation dependent. 
Remember that the app-defaults file is written by the application writer, and all the rest of the 
resource sources are for the user. In practice, few users use more than one or two of these 
sources of resource settings. 

/usr/lib/$LANG/app-defaults/class 
else /usr/lib/app-defaults/class 

else 
else 
else 
else 

$XUSERFILESEARCHPATH/class 
$XAPPLRESDIR/$LANG/class 
$XAPPLRESDIR/class 
$HOME/$LANG/class 
$HOME/class 

RESOURCE MANAGER propey (rdb) 
-- 
else $HOME/.Xdefaults 

$XENVIRONMENT 
else $HOME/.xdefaults-hostname 

Command line options 

Figure 9-1. Suggested resource setting search path on UNIX-based systems 

The Language String 
In R4, Xt's resource handling was modified to support resource files for different languages. 
The goal is to have all the language dependencies of an application in files, so that just by 

Resource Management and Type Conversion 255 



Note that there is Iso a separate function, XtAppSetFallbackResources, that can be 
used to set the fallback resources separately from the XtAppInitialize call. 

Resource Matching Algorithm 

When a widget is created, its expanded instance hierarchy and class hierarchy together with 
its resource names and classes are compared to each entry in the merged resource database. 
To demonslrate how matches are made, we'll look at a sample widget hierarchy and follow 
the process of finding the value for one resource of one widget from the merged resource 
database. Figure 9-2 shows the widget instance hierarchy for the quit widget in the xbox 
application shown in Chapter 3, More Techniques for Using Widgets. The figure also shows 
the corresponding fully specified instance and class names for the quit widget. This sec- 
tion describes how this widget's resources are set by the resource manager.* 
We know that quit is a Command class widget and therefore that Xt will be searching the 
resource database for each resource in Command's resource list (and the resources in its 
superclasses' resource lists). It will search for one resource at a time. To demonstrate the 
conflicts that can occur, we'll use the Core resource XtNbackground, which is common to 
all widgets. It will appear in the resource database as background. 
The matching process can be thought of as a process of elimination. Let's assume the 
merged resource database is as shown in Example 9-4. 

Example 9-4. A sample merged resource database 

*box.background: 
*background: 
*quit.background: 
*quit.label: 
*Command.background: 
*Box.Command.background: 
*box*background: 
xbox.background: 

blue (entry 1) 
red (entry 2) 
green (entry 3) 
Quit (entry 4) 
yellow (entry 5) 
violet (entry 6) 
pink (entry 7) 
orange (entry 8) 

Only resource, database entries that specify background as the last element before the colon 
are possible matches. That eliminates entry 4. The fully specified instance and class hierar- 
chies are then compared with each possible match, beginning with the first component in 
each hierarchy. 

*The actual algorithm used by Xt differs slightly from that described here, because there are shortcuts that the re- 
source manager takes that are hard to follow even ff you have the source code. However, the algorithm described 
here gives the same result, with more clarity. 

258 X Too/k# Intrinsics Programming Manual 



From here on, we will determine not only which one of these five will take effect, but the 
actual precedence of the five. In other words, once the one with highest precedence is deter- 
mined, we'll see which would take effect if that one was commented out, and so on. 

The precedence rules are applied in order to determine the order of the finalist entries. 

1. Rule 1 specifies that a specification that contains higher components in the instance or 
class hierarchy takes precedence over one that contains only lower ones. The highest 
components that appear in our example are box and Box in entries 6 and 7. Therefore, 
these two have higher priority than any others. 

2. To choose between these two, we continue to Rule 2. Instance names (box) take prece- 
dence over class names (Box). Therefore, entry 7 has the highest precedence, followed 
by entry 6. Note that the precedence comparison of two finalists proceeds in the same 
manner as the original matching--from left to right in the entry, one component at a 
time. 

3. To determine the precedence of the remaining three entries, 2, 3, and 5, we begin again 
with Rule 1. However, Rule 1 does not apply because no two entries here specify differ- 
ent levels in the hierarchy. Entries 3 and 5 contain the quit level and entry 2 nothing 
(an asterisk does not count for Rule 1 because it is not a specified level--it is any level). 
Rule 2 specifies that the instance name quit takes precedence over the class name 
Command, and therefore entry 3 has higher priority than entry 5. Rule 3 does not apply, 
because no two entries are identical except for binding. Because of Rule 4 we know that 
both entries 3 and 5 are higher priority than entry 2, because 3 and 5 state a name or class 
that is omitted in 2. 

Therefore, the final precedence is as shown here: 

I. *box*background: 
2. *Box. Command.background: 
3. *quit.background: 
4. *Command.background: 
5. *background: 

pink (emry7) 
violet (emry6) 
green (emry3) 
yellow (emry5) 
red (emry2) 

Rules 2, 3, and 4 are fairly easy to understand and apply, but many people forget or are con- 
fused by Rule 1. People get used to the fact that they can set the resources of all the children 
of box with something like entry 7, but then are shocked to find that nothing happens when 
they attempt to override entry 7 with entry 3--entry 3 seems more specific to them. Even the 
following entry (using a class name) takes precedence over entry 3 because the rule about 
being higher in the widget hierarchy carries more weight than the rule that instance names 
take precedence over class names: 
*Box*background : pink (en/ry 7) 
The moral of this story is that there is only one way to be sure you are setting a particular 
resource of a particular widget in such a way as to override all other settings that might apply 
to that resource: you must specify all the levels in the instance hierarchy, with tight bindings 
between each component. (But of course, this will not work when another resource file that 
is merged later also specifies the same resource and all components of the same widget with 
the instance hierarchy separated by tight bindings.) Since there are no messages telling you 
which resource specifications are actually being used, you can be tricked into thinking that 

262 X Toolkit Intrinsics Programming Manual 



you have set resources that you actually haven't. Using only tight bindings in the applica- 
tion-defaults file, while more trouble initially, is probably wise in the long run. 
A useful tool for figuring out the priority of resource files is the appres utility. You specify 
the class name of the application on the command line, and appres shows you what resource 
settings that application will see when run. Note, however, that this does not tell you how 
these resource settings will actually apply to the widgets in the application, since appres has 
no knowledge of the widget instance hierarchy in your application. 
Another tactic in tracing resource settings is to build a routine into your application that gets 
and prints all the critical resources of a widget. Using XtGetResourceList yOU can get 
the list of resources supported by a widget class. Then you can query each of those resources 
and print most of them out. Remember that certain resources are compiled into internal 
forms, so you can't print out translation tables, accelerator tables, or callback lists. It may 
also be difficult to interpret other values, since many of them will have already been con- 
vetted from the string form in the resource file into the most convenient internal form. For 
example, colors will have been changed from strings such as "red" into a pixel value (a num- 
ber which could change each time the application is run). 
Figure 9-3 illustlates the entire process of resource matching. 

9.3 Type Conversion 

You already know that Xt is capable of converting resource values from the string representa- 
tion specified in resource files to the actual type required in code. In fact, Xt does so auto- 
matically if the resource list is properly written. This section describes this process in more 
detail, and tells you how to create converters for converting your own data types. 

In R4, a new set of interfaces for type converters was introduced. The new interfaces support 
display-specific conversions and better control of converted-value caching. This section 
describes these new interfaces, but does not describe the older ones. Be aware that many 
existing widgets and applications still use the older interfaces. 

9.3.1 

Conversions from XtRString 

The primary purpose of converters is to allow resource files to contain string values for non- 
string program variables. (They are also used internally to convert default values that cannot 
be specified easily in the desired data type.) Secondly, converters confine the details of data 
conversion to a single routine that is registered with Xt. This is a big benefit because users of 
the converted types need not know the details of how the conversion takes place, or the inter- 
nal definition of the target type. 
Xt provides converters from Xt:RSt:rirc3 tO the representation types listed in Table 9-2. You 
can use these representation types as target types in resource lists in applications or widgets, 
without having to register them, if you want the user to be able to specify the resource in a 
resource file. 

Resource Management and Type Conversion 263 



Table 9-2. Built-in Type Converters from XtRString 

Target Type 

XtRAcceleratorTable 

XtRAtom 
XtRBoolean 

XtRBool 
XtRCursor 
XtRDimension 
XtRDisplay 

XtRFile 
XtRFloat 
XtRFont 

XtRFontStruct 

XtRGeometry 

XtRInitialState 

XtRInt 
XtRPixel 

XtRPosition 
XtRShort 
XtRTranslationTable 

XtRUnsignedChar 
XtRVisual 

Description of Converter 

Compiles a string accelerator table into internal accelerator 
format (no need to call XtParseAcceleratorTable). 
Converts a string property name into the corresponding Atom. 
Converts strings "true," "false," "yes," "no," "on," "off" to cor- 
responding Boolean value (case insensitive). 
Same as for XtRBoolean. 
Given a standard X cursor name, returns a cursor ID. 
Converts a width or height value to a Dimension. 
Given a display name, opens the display and returns a Dis- 
play structure. 
Given a filename, opens the file and returns the file descriptor. 
Converts a numeric string to floating point 
Given a font name, loads the font (if it is not already loaded), 
and returns the font ID. See Appendix B, Specifying Fonts 
and Colors, for more information on legal values. The value 
XtDefaultFont will return the default font for the screen. 
Given a font name, loads the font (if it is not already loaded), 
and returns a pointer to the FontStruct containing font 
metrics. The value XtDefaultFont will return the default 
font for the screen. 
Given a standard geometry string, this converter simply 
copies a pointer to the string and calls it a new resource type. 
Converts strings "Normal" or "Iconic" into the symbols No r- 
malState or IconicState. 
Converts a numeric string to an integer. 
Converts a color name string (e.g., "red" or "#FF0000") into 
the pixel value that will produce the closest color possible on 
the hardware. See Appendix B, Specifying Fonts and Colors, 
for more information on legal values. The two values XtDe- 
faultBackground and XtDefaultForeground are 
always guaranteed to exist, and to contrast, on any server. 
Converts an x or y value to a Position. 
Converts a numeric string to a short integer. 
Compiles string translation table into internal translation table 
format (no need to call XtParseTranslationTable). 
Converts a string to an unsigned char. 
Converts a string specifying a visual class to a pointer to a 
supported visual structure of that class. 

If there is no converter from XtRString to a particular resource type, it may not be possible 
to specify that resource type in a resource file. For example, there is no converter for Xt- 
RCallback since it would be meaningless to specify a function in a resource file. The 

Resource Management and Type Conversion 265 



For example, the Core resource XtNborderPixmap has its default value set as shown in 
Example 9-8. 

Example 9-8. A resource definition converting an int to a pixmap 
static XtResource resources[] = { 

XtNborderPixmap, 
XtCPixmap, 
XtRPixmap, 
sizeof(Pixmap), 
XtOffsetOf(CoreRec, core.border_pixmap), 
XtRImmediate, 
(XtPointer) XtUnspecifiedPixmap 
}, 

} 
The specified default value XtUnspecifiedPixmap is an integer defined to have a value 
that does not equal the constant CopyFromParent or any valid Pixmap ID. The initial- 
ize method for the Core widget class checks for this value, and does not set the back- 
ground window attribute unless the application or a resource file has set the XtNborder- 
P ixmap resource to some value other than the default. 

9.3.3 Special Resource Defaults That Do Not Use Conversion 

There are two special values, XtRImmediate and XtRCallProc that can be used only in 
the default_type field of a resource definition. These values require no type conversion. 
The value provided in the default_address field must be of the correct type. 
The type XtRImmediate means that the value in the default_address field is the default 
value itself, not its address. For a string, this means that the default_address field is a 
pointer to the string, aot a pointer to a pointer. 
In Example 9-9, the value in the default_address field of the XtNheight resource defi- 
nition is the actual default--in this case, zero. 

Example 9-9. A resource definition using XtRImmediate 
static XtResource resources[] = { 

{ 
XtNheight, 
XtCHeight, 
XtRDimension, 
sizeof(Dimension), 
XtOffsetOf(RectObjRec, rectangle.height), 

Resource Management and Type Conversion 267 



Example 9-9. A resource definition using XtRImmediate (continued) 
XtRImmediate, 
(XtPointer) 0 
), 

}; 
The type XtRCallProc means that the value in the default_address field is a pointer to 
a function. This function is of type XtResourceDefaultProc, and it is expected to 
retrieve the desired default value at run time. When the widget instance is created, the func- 
tion is automatically invoked with these parameters: the widget ID, the resource offset, and a 
pointer to the XrmValve in which to store the result. The function should fill in the addr 
field of the XrmValue with a pointer to the default data in its correct type. 
In Example 9-10, the value in the default_address field of the XtNscreen resource defi- 
nition is the name of a function that will retrieve the screen on which the widget is displayed. 

Example 9-10. A resource definition using XtROallProc 
static XtResource resources[] = { 

{ 
XtNscreen, 
XtCScreen, 
XtRPointer, 
sizeof (int) , 
XtOffsetOf(CoreRec, core.screen), 
XtRCa IIP roc, 
(XtPointer) XtCopyScreen 
l, 

Example 9-11 shows an example of an XtResourceDefaultProc. 

Examp 9-11. An examp of an XtResourceDeuPmc 
/*ARGSUSED*/ 
void XtCopyScreen(widget, offset, value) 
Widget widget; 
int offset; 
XrmValue *value; 
( 
value->addr = (XtPointer) (&widget->core.screen); 
} 

268 X Toolkit Intrinsics Programming Manual 



9.3.4 Registering Type Converters 

As noted earlier, not every resource type symbol defined in StringDefs.h is supported by a 
built-in converter, though the Xmu library does provide some of the most important conver- 
ters that are missing in Xt. In addition, you can define your own resource types, and write 
converter routines to convert from a string representation in a resource file to the appropriate 
data type. (You can write converters from any type to any other type, but converters from 
String are by far the most useful.) 

Table 9-4 lists the converters from XtRString provided by the Xmu library. 

Table 9-4. Xmu Converters 

From 

XtRString 

XtRBackingStore 

XtRBitmap 

XtRCursor 

XtRJustify 

XtRLong 
XtROrientation 

XtRShapeStyle 

Description of Converter 

The XmuCvtStr ingToBackingStore converter 
converts the strings "NotUseful," "WhenMapped," and 
"Always" (in any case) into the corresponding con- 
stants (in proper case) for use in setting the back- 
ing_store window attribute. (See Volume 
One, Xlib Programming Manual, for details on back- 
ing store.) 
The XmuCvtStringToBitmap converter takes the 
s/ng filename of a file in standard Xll bitmap format 
and creates a one-plane pixmap containing that bitmap 
data. 
The XmuCvtStringToCursor converter converts 
one of the standard cursor names (from <Xll/cursor- 
font.h), a font name and glyph index of the form 
"FONT fonmame index [[font] index]", or a bitmap 
file name as in XtRPixmap below, and converts it to 
an X Cursor. 
The XmuCvtStringToJustify converter con- 
verts the s'ags "right, .... left," or "center," in any case, 
to an enumeration constant suitable for use by a justify 
resource. This converter is used by the Athena Label 
widget. 
Converts a s'ag to a long integer. 
The XmuCvtStringToOrientation converter 
converts the strings "horizontal," or "vertical," in any 
case, to an enumeration constant suitable for use by an 
orientation resource. This converter is used by the 
Athena Scrollbar widget. 
Converts the strings ShapeRectangle, ShapeO- 
val, ShapeEllipse, and ShapeRoundedRec- 
tangle in shape style constants, for use in making 
Xmu calls that access the Shape extension. 

Resource Management and Type Conversion 269 



Example 9-15 shows the converter added by the Athena Form widget (changed to the R4 in- 
terface) to convert the "edge type" values for its XtNright, XtNleft, and XtNtop re- 
sources. 
This is a good example of the type of converter you are most likely to write. It allows the le- 
gal values for the desired constants to be provided in either case, and uses the Xlib quark 
mechanism to speed string comparison. Type converters (and the Xt and Xlib resource man- 
agement facilities in general) use quarks extensively to speed string comparisons. A quark is 
a unique ID for a string, of type XrmQuark (defined by Xlib). A call to the Xlib routine 
XrmStringToQuark returns the quark for a string. See Volume Two, Xlib Reference 
Manual, for details. When a nonstandard type converter that uses quarks is defined and reg- 
istered in widget code, the XrmStringToQuark calls are normally placed in the 
class_initiali ze method just before the XtSetTypeConverter call. 
Note that Xt manages the cache of convened values: convener routines are not responsible 
for caching their own returned data. 

Examp 9-1 An R4 XtRString  XtREdge Type type conveer 
/* This macro or something like it used by many resource converters 
#define done(address, type) \ 
{ toVal->size = sizeof(type); \ 
toVal->addr = (XtPointer) address; \ 
return; \ 
} 

,/ 

/* Quarks used to speed string comparisons */ 

static XrmQuark XtQChainLeft, XtQChainRight, XtQChainTop, 
XtQChainBottom, XtQRubber; 

/* The converter itself */ 
/*ARGSUSED*/ 
static void _CvtStringToEdgeType(display, args, num_args, 
fromVal, toVal, destructor data) 
-- 
Display *display; /* unused */ 
XrmValuePtr args; /* unused */ 
Cardinal *num_args; /* unused */ 
XrmValuePtr fromVal; 
XrmValuePtr toVal; 
XtPointer *destructor data; /* unused */ 
-- 

static XtEdgeType edgeType; 
XrmQuark q; 
char lowerName[1000]; 

/* make lower case copy */ 
XmuCopyISOLatinlLowered (lowerName, (char*)fromVal->addr); 

q = XrmStringToQuark(lowerName); 

if (q == XtQChainLeft) { 
edgeType = XtChainLeft; 
done(&edgeType, XtEdgeType); 
} 

276 X Toolkit Intrinsics Programming Manual 



9.3.6.1 

Example 9-15. An R4 XtRString to XtREdge Type type converter (continued) 
if (q == XtQChainRight) { 
edgeType = XtChainRight; 
done(&edgeType, XtEdgeType) ; 
) 
if (q == XtQChainTop) { 
edgeType = XtChainTop; 
done(&edgeType, XtEdgeType) ; 
) 
if (q == XtQChainBottom) { 
edgeType = XtChainBottom; 
done(&edgeType, XtEdgeType) ; 
) 
if (q == XtQRubber) { 
edgeType = XtRubber; 
done(&edgeType, XtEdgeType) ; 
) 
XtDisplayStringConversionWarning(display, fromVal->addr, 
"XtREdgeType" ) ; 
toVal->addr = NULL; 
toVal->size = 0; 
) 
Notice that the XrmValuePtr arguments passed into the converter are pointers to structures, 
not values. The XrmValue structure contains an address field and a size field. 
XtDisplayStringConversionWarning takes as arguments a pointer to the Display 
structure, the string that could not be converted, and the type to which it could not be con- 
verted. It issues a warning message with name conversionError, type string, class Xt- 
ToolkitError, and the default message string "Cannot convert "src" to type 
dst_type.'" (See Chapter 13, Miscellaneous Toolkit Programming Techniques, for more 
information on error and warning messages.) 

Defining the Default Value 

When performing conversions, such as from strings to fonts or colors, for which there is no 
string representation that all server implementations will necessarily recognize, a type con- 
vener should define some set of conversion values that the converter is guaranteed to succeed 
on, so that these can be used as resource defaults. 
For example, the default string-to-pixel converter recognizes the symbols XtDefault- 
Foreground and XtDefaultBackground. AS part of its conversion, it tests for these val- 
ues, and establishes the appropriate value based on the string value. The code is shown in 
Example 9-16. 

Resource Management and Type Conversion 277 



Example 9-16. Testing for a special-case default value 
/* 
* CompareISOLatinl is an undocumented Xt function, allowed since 
* this converter is within Xt. In your converters, you would use 
* XmuCompareI SOLatin I. 
*/ 
if (CompareISOLatinl(str, XtDefaultBackground) == O) { 
*destructor data = FALSE; 
-- 
if (pd->rv) 
done(Pixel, BlackPixelOfScreen(screen)) 
else 
done(Pixel, WhitePixelOfScreen(screen)) ; 
} 
if (CompareISOLatinl(str, XtDefaultForeground) == O) { 
*destructor data = FALSE; 
-- 
if (pd->rv) 
done(Pixel, WhitePixelOfScreen(screen)) 
else 
done(Pixel, BlackPixelOfScreen(screen)) ; 
} 

9.4 Subparts and Subresources 

A subpart is a section of a widget that is replaceable but that cannot operate independently. 
It is just a further subdivision of the widget into smaller pieces. This section is provided only 
for completeness; gadgets and objects provide a more elegant way to do this. 
Subresources allow subparts of a widget to have separate sets of resources. Since the Athena 
Text widget was the only example of the use of subresources in MIT's Release 3 Core distri- 
bution, we'll describe how Text uses subparts and subresources so you can understand the 
motivation behind them. You can then compare this concept with the R4 Text widget which 
is implemented using objects. 
The R3 Text widget has three parts: the source, the sink, and the coordinator widget. The 
source manages the storage of data and the sink manages how it is displayed. The coordina- 
tor is the central widget that manages the communication between the source and the sink, 
and is inoperable without them. Both the source and the sink are replaceable pieces of code. 
Xaw provides only one source, which edits a string or disk file, and only one sink, which 
displays text in one color and in one font. The idea of providing the subparts in the first place 
is that they would allow enhancements to be made without changing the basic editor func- 
tionality that is in the coordinator. For example, only the source and sink would need replac- 
ing in order to implement a multifont and/or multicolor text widget. 
Each subpart has its own resource list so that it truly can be replaced without any modifica- 
tions to the central widget. These are the subresources. 

278 X Too&# Intrinsics Programming Manual 



Like widgets, the resources of subpans can be queried and set manually. XtVaGet- 
Subvalues or XtGetSubvalues queries the values, and XtVaSetSubvalues or XtSet- 
Subvalues sets them. However, because subvalues are not part of any widget, these calls 
cannot identify what object is being queried or set simply by passing the widget ID. These 
calls have different arguments than xtsetValues and XtGetValues. Instead of the widget 
ID, you pass the pointer to the data structure, the resource list, and the number of resources. 
Therefore, XtSetSubvalues and XtGetSubvalues can be invoked only from within the 
widget or subpart. Actually, all these routine do is set or get the value in the specified struc- 
ture. 
Any application using the widget will set or get subresources using xtsetValues and Xt- 
GetValues as for normal resources, specifying only the coordinating widget as the first ar- 
gument. These calls are translated into XtSetSubvalues and XtGetSubvalues calls by 
the set_values and get_values_hook methods. These methods are passed the argu- 
ments from the xtsetValues or XtGetValues calls and translate them into XtSet- 
Subvalues or XtGetSubvalues calls by adding the data structure and resource list argu- 
ments. But in addition, the set_values method is responsible for validating the resource 
settings passed in before it calls XtSetSubvalues, and for changing any nonresource sub- 
part structure fields like GCs that depend on resources. 

280 X Toolkit Intrinsics Programming Manual 



10 

Interclient Communications 

This chapter discusses communication through the X server between an 
application and the window manager, and between two applications. The 
application-window manager communication is performed by code in the 
Shell widget. The application sets shell resources to control this communica- 
tion with the window manager. Application-application communication is 
usually done with a process called selections. This form of communication is 
already implemented in most widgets that display text, but you may want to 
implement it in your own custom widgets. Selections can also pass other 
kinds of data such as graphics. 

In This Chapter: 

Window Manager Interactions ............................................................ 284 
Shell Subclasses ........................................................................... 284 
Setting Shell Resources ................................................................. 285 
Screen Space ................................................................................ 287 
Input Model .................................................................................... 288 
Colormaps-. ..... -- .............................................................................. 290 
Icons ............................................................................................. 292 
Window Manager Decorations ....................................................... 293 
Selections: Widget-To-Widget Communication .................................. 294 
How Atomic Selection Works ......................................................... 295 
Highlighting the Selected Data (Owner) .......................................... 298 
Making the Selection with XtOwnSelection (Owner) ....................... 303 
Requesting the Selection (Requestor) ............................................ 304 
Possible Target Type Atoms ......................................................... 305 
The Paste Action from BitmapEdit ............................................... 307 
Converting the Selection (Owner) .................................................. 307 
Finally Pasting the Selection (Requestor) ....................................... 310 
If the Selection is Lost (Owner) ...................................................... 312 



When the Selection Transfer is Complete (Owner) ......................... 312 
ICCCM Compliance ........................................................................ 312 
Xmu Atom Caching ...................................................................... 314 
Converting the Standard Selections ............................................. 315 
The Clipboard Selection ............................................................... 316 
How Incremental Selection Works .................................................. 317 
Miscellaneous Selection Routines .................................................. 318 



10 
Interclient Communications 

Applications share the server with other clients. Server resources, such as screen space and 
colormaps, must be used in a responsible, consistent manner so that applications can work 
effectively together. In most window systems, the window system itself embodies a set of 
rules for application interaction. However, the X Protocol, Xlib, and Xt were all specifically 
designed to avoid arbiary conventions, so that they provide "mechanism, not policy." 
Instead, the conventions covering interclient communication are described in a separate doc- 
ument, adopted as an X Consortium standard in July, 1989, called the Inter-Client Commu- 
nication Conventions Manual (ICCCM). This chapter will not fully describe the ICCCM, 
because the job of implementing its rules is given over to a special client called the window 
manager and a special widget class called Shell and its subclasses.* As a result the details of 
the ICCCM are, for the most pan, irrelevant to the application writer's needs. 
In X Toolkit programs, the Shell widget returned by XtAppInitialize and used as the 
top-level window of the application automatically handles most of the required interactions 
with the window manager. However, the Shell widget needs additional information in certain 
areas. For example, the application needs to provide an icon pixmap so that the window 
manager can iconify it properly. The first section in this chapter describes how to set Shell 
resources to conol how an application interacts with the window manager. This portion of 
the chapter is for application writers, regardless of whether you need to write widgets for 
your application. 
In X Toolkit applications, .widgets can communicate with other widgets using a mechanism 
called selections, which in turn is based on an X mechanism for common storage called pro- 
perties. Whether the widgets involved in transferring selections are pan of the same applica- 
tion or different applications is irrelevant. The communication between widgets takes place 
without input from the application. However, it can be used as a means of communication 
between applications. The second major section in this chapter will describe these concepts 
and how to implement selections between your own custom widgets. Only if your applica- 
tion requires a custom widget that must communicate with other widgets should you actually 
have to write this code. Thus, this pan of the chapter is primarily for widget writers. 
*If you do need to look up certain details of the ICCCM. see Appendix L. Inter-Client Communication Conventions, 
in a version of Volume Zero, X Protocol Reference Manual, printed on or after June, 1990 (the conventions have 
changed since the version of the ICCCM printed in earlier editions of Volume One). The ICCCM is also included in 
troffsource form in the standard X distribution from M]T. 

Interclient Communications 283 



10.1 Window Manager Interactions 

The window manager was introduced in Chapter 1, Introduction to the X Window System, 
but little mention of it has been made since then. You may recall that the window manager is 
just another client running on a server, except that it is given special authority to manage 
screen space and other limited server resources like colormaps.* To let the window manager 
do a better job of mediating competing demands of the various clients, each client gives the 
window manager information called window manager hints. These hints specify what 
resources each client would like to have, but they are only hints; the window manager is not 
obligated to honor them, and the client must not depend on them being honored. 
Application code has little to do to interact properly with the window manager. The Shell 
widget returned by XtAppInitialize takes care of setting the essential window manager 
hints. However, there are a number of optional window manager hints that the application 
may wish to have passed to the window manager. This is done mainly by setting resources of 
the Shell widget. Also, there are variations in window managers and it takes some effort to 
make some applications work equally well under all of them. 
The next few sections describe the various resources of the Shell widget, including how and 
when they should be set. Because the Shell widget is part of the Xt standard, these resources 
are present when writing applications with any widget set. 

10.1.1 

Shell Subclasses 

There are several types of Shell widgets. The Shell widget class itself, specified by the class 
structure pointer shellWidgetClass, is never instantiated directly in applications. Only 
ts subclasses are used. You have seen two subclasses of the Shell widget used earlier in this 
books: the one used for the application's top-level widget and the one used for pop ups. The 
application's top-level widget is created by passing the class structure pointer 
applicationShellWidgetClass as the widget class argument to XtAppCreateShell; 
this call is also made internally by XtAppInitialize. Pop-up shells for dialog boxes are 
created by passing transientShellWidgetClass as the widget class argument to Xt- 
CreatePopupShell. There are two other subclasses of Shell that are commonly used in 
applications. One is the OverrideShellWidgetClass, passed to XtCreatePopupShell 
when the shell is used for pop-up menus. The convention is this: the shell should be an 
OverrideShell when the pointer is grabbed to prevent other windows from getting input while 
the pop up is up, and the shell should be TransientShell for other pop ups. This will be dis- 
cussed further in Chapter 12, Menus, Gadgets, and Cascaded Pop Ups. 

The other additional subclass of Shell is topLevelShellWidgetClass, which is used to 
create additional, non-pop-up, top-level shells. Some applications have multiple permanent 
top-level windows. One of the top-level shells would be of the applicationShell- 
WidgetClass, and the rest would be of the topLevelShellWidgetClass. Each would 
have a separate icon. 

*Note that we are using the term resources here in a general sense, rather than implying its Xt-specific meaning. 

284 X Toolkit Intrinsics Programming Manual 



10.1.2 Setting Shell Resources 

Shell resources are primarily a way for the user and the application to send in data to be com- 
municated to the window manager. These window manager hints control several major areas 
of window manager activity: they manage screen space, icons, and keyboard input. We'll 
discuss these areas one at a time in the following sections. Table 10-1 lists the Shell widget's 
resources with a brief description of what they control, and whether the application, the user, 
or Xt normally sets them. 

As indicated in Column 3 of the table, some Shell resources are intended to be set only once. 
These set-once resources can be left to their default values, set in the application-defaults 
file, or they can be set in the code before the Shell widget is realized; but they should not be 
set with XtSetValues after realization. 

Table 10-1. Shell Resources 

Resource 

ually set by Xt or Shell e 
depending on the subclass: 
XtNargc 
XtNargv 
XtNoverrideRedirect 

Command-line args count 
Command-line args 
Set for pop-up shells not to be decorated 

When Settable 

XtNtransient 
XtNwaitForWm 
XtNwindowGroup 
XtNwmTimeout 
ually set by er : 
XtNiconX 
XtNiconY 
XtNiconic 
XtNgeometry 
XtNtitle 
ually set by application: 
XtNallowShellResize- 

Set for pop-up shells 
Whether to wait at all 
Links pop ups to main window 
Waiting time for slow wm 

Icon position 
Icon position 
Sets XtNinitialState to iconic 
Initial size and position 
String for title bar 

Does shell ask wm for size change? 

Before realization 
Before realization 
Before realization 
Before realization 
Anytime 

Anytime 

XtNbaseHeight 
XtNbasewidth 
XtNheightInc 
XtNwidthInc 
XtNiconMask 
XtNiconName 
XtNiconPixmap 
XtNiconWindow 
XtNinitialState 
XtNinput 
XtNmaxAspectX 
XtNmaxAspectY 
XtNmaxHeight 

Height of fixed components 
Width of fixed components 
Desired height increment 
Desired width increment 
Mask used with icon pixmap 
String for icon 
Picture for icon 
Window for icon 
Whether normal or iconic 
Keyboard input model 
Maximum aspect ratio x/y 
Maximum aspect ratio x/y 
Maximum acceptable height 

Anytime 
Anytime 
Anytime 
Anytime 
Before realization 
Before realization 
Before realization 
Before realization 
Before realizauon 
Before realization 
Anytime 
Anytime 
Anytime 

Interclient Communications 285 



-geometry [ width { x } hei gh t][{ +- } xposi t i on { +-}yposi t i on] 
(Either the size or position portion of the geometry string may be omitted, as indicated by the 
square brackets. In specifying the x or y position, a positive value, indicated by a plus sign, is 
relative to the top or left side of the reference window, while a negadve value, indicated by a 
minus sign, is relative to the bottom or right side.) 
The -iconic command-line option, if present, sets the XtNiconic resource, indicating to the 
window manager that the application should start up as an icon. 
The XtNicon_x and XtNicon_y icon position hints are best left to be specified by the user. 
Icons" positions are determined by the window manager based on these hints or on an icon- 
positioning policy. An application with several top-level windows could set the icon position 
hints in its application-defaults file so that the icons for each top-level window appear 
side-by-side. 
We will discuss the remaining resotu'ces in related groups. Section 10.1.3 discusses the ones 
related to the size of the application's main window and other screen space issues. Section 
10.1.4 describes the keyboard input model hint. Section 10.1.5 describes how applications 
should handle colormaps to cooperate with the window manager. Section 10.1.6 describes 
the ones that apply to the application's icon. 

10.1.3 

Screen Space - 

The Shell widgets of each application have windows that are children of the root window. 
These are called top-level windows. The window manager directly controls the size and 
position of the top-level windows of each application. The window manager does not control 
the geometry of other widgets that are the descendants of the Shells, except indirectly 
through the geometry management mechanism described in Chapter 11, Geometry Manage- 
ment. 
The most basic size hint, the one that specifies simply the desired initial height and width, is 
automatically set by Xt based on the size of the child of the Shell widget. This hint is used 
by most window managers to display the outline of your application when it first appears on 
the screen, ready for the user to place and/or size the application. If your application does 
not have specific size needs, you need not set any additional resources. 
The additional size hints specify the application's range of desired sizes, desired increments 
of sizes, and desired range of aspect ratios. These are set by the XtNbaseHeight, Xt- 
NbaseWidth, XtNminWidth, XtNminHeight, XtNmaxWidth, XtNmaxHeight, Xt- 
NwidthInc, XtNheightInc, XtNminAspectX, XtNminAspectY, XtNmaxAspectX, and 
XtNmaxAspectY resources. 
Size increment hints are useful for applications that prefer to be in units of a particular num- 
ber of pixels. Window managers that listen for this hint always resize the window to the base 
size (for each dimension), plus or minus an integral multiple of the size increment hint for 
that dimension. If the base size resource has not been set, the minimum size is used as the 
base. For example, xterm uses the font width and font height as width and height incre- 
ment hints, because it prefers not to have partial characters or dead space around the edges. 
The bitmap editor application described in Chapter 4, An Example Application, should 

Interclient Communications 287 



Examp 10-1. Seing e XtNinputresourceofa Shefl widget 
main(argc, argv) 
int argc; 
char *argv[]; 
{ 

/* create the Shell widget, setting resource */ 
topLevel = XtVaAppInitialize(&app_context, "Xmh", table, 
XtNumber(table), 
&argc, argv, NULL, 
XtNinput, (XtArgVal)TRUE, 
NULL); 

} 
Note that the XtNinput resource should always be hardcoded, since the application may 
fail if the user is allowed to change the expected style of keyboard focus. 
For a further discussion of the keyboard focus, see Section 13.3. 

10.1.5 

Colormaps 

On most color systems, the display uses one or more hardware registers called colormaps to 
store the mapping between pixel values and actual colors, which are specified as relative 
intensities of red, green, and blue primaries (RGB values). 
X allows virtual colormaps to be created by applications. Some high-performance systems 
even allow all virtual colormaps to be installed in hardware colormaps and used at the same 
time, even to the level of one colormap per window. Far more commonly, though, there is 
only one hardware colormap, and virtual colormaps have to be copied into the hardware 
colormap one at a time as needed. Copying a virtual colormap into the hardware colormap is 
called installing the colormap, and the reverse process where the default colormap is 
installed is called uninstalling. The window manager is responsible for installing and unin- 
stalling colormaps. 
If your application has standard color needs (decoration only), then you do not have to worry 
about the effects of colormaps being installed and uninstalled. Your application should use 
the standard XtRString to XtRPixel convener to translate color names into pixel val- 
ues. If the colormap is full, or becomes full at any of the color allocations in the convener, 
the warning messages place the burden on the user to kill some applications in order to free 
some colormap cells. (If the convener cannot allocate the desired color, it prints a warning 
message, and the default for that resource is used. If the default is not XtDefault- 
Foreground or XtDefaultBackground, it also must be convened and Otis may also 
fail. If both allocations fail, the color will default to black. If this is not acceptable, then you 
will need to write your own type convener.) 

290 X Toolkit Intrinsics Programming Manual 



If your application absolutely requires accurate colors, a certain number of distinguishable 
colors, or dynamically changeable colors, you will need to write your own converter to allo- 
cate colors. For example, if a color allocation for a known correct color name string fails, it 
means that all the colormap entries have already been allocated and no entry for that color is 
available. In this case, your converter might call the Xlib call XCopyColormapAndFree 
tO copy the allocations your application has already made into a new colormap. Then the 
converter would allocate the color (and all subsequent colors) from the new colormap. 
See Chapter 7, Color, in Volume One, Xlib Programming Manual, for details of various 
color allocation techniques. 
The window manager is responsible for installing and uninstalling colormaps according to its 
own policy. Typically, the policy is to install the colormap of the application that has the 
keyboard focus or that contains the pointer. When an application has created a new colormap 
on a system that supports only one hardware colormap, and that colormap is installed, all 
applications that were using the other colormap will be displayed using the new colormap. 
Since the pixel values from the old colormap have not been allocated in the new colormap, 
all applications that use the old colormap will be displayed with false colors. This is known 
as "going technicolor." 
The window manager may also create standard colormaps to facilitate the sharing of colors 
between applications. A standard colormap is a colormap allocated with a publicly known 
arrangement of colors. The Xlib roudne XGetStandardColormap allows an applica- 
tion to determine whether the window manager has created a specific standard colormap, and 
it gets a structure describing the colormap. Xmu provides numerous utilities for creating and 
using standard colormaps--see Volumes One and Two for a description. 
If your application requires more than one colormap, each installed at the same time in a dif- 
ferent window, you need to tell the window manager about this so that these colormaps can 
be properly installed when the application is active. You do this by calling XtSet- 
WMC o i o rmapWi ndow s, specifying the ApplicationShell widget as the first argument, a list 
of widgets that need certain colormaps as the second argument, and the length of the list as 
the third argument. This instructs the window manager to read the colormap window attri- 
bute of each of the listed widgets, and to install that colormap in each widget (if possible) 
whenever the application is active. (Of course, any application that depends on the existence 
of multiple simultaneous colormaps is doomed to run on only a small percentage of existing 
systems.) 
The col o rmap window attribute of a window is an unchangeable characteristic of that win- 
dow, assigned when the window was created (when the widget was realized). The Core 
reali ze method sets it based on the XtNcolormap Core resource of the widget. There- 
fore, if a widget must have a certain colormap, you must set its XtNcolormap resource 
while creating the widget. Attempting to set XtNcolormap after a widget is created will 
have no effect on its colormap window attribute. 

Interclient Communications 291 



10.1.6 Icons 

The window manager always manages the icons for each application. Depending on the win- 
dow manager, these icons may simply contain a text string called the icon name, or they may 
contain a pattern that identifies the application, called the icon pixmap. 

Figure 10-1 shows the icon, under the uwm window manager, for an application with a cus- 
tom icon pixmap (xcalc) and for one without (xterm). 

Figure 10-1. An icon with and without an icon pixmap 

An application may supply an icon name by setting the XtNiconName resource; if it does 
not, the window manager will usually use the application name or the value of the XtNtitle 
resource. 
The application should supply the pattern for the icon, in the form of a single-plane pixmap, 
as the XtNiconPixmap resource. There are two basic ways to do this: one is by including 
bitmap data, and the other is by reading it in at run-time. The former is easy to do with an 
Xlib call; the code that needs to be added is shown in Example 10-2. The latter technique, 
because it involves building a filename and looking in a number of locations for the file, is 
better done with a converter defined by the Xmu library. This converter technique is more 
complicated because the converter has to be registered and called with the proper arguments. 
The example using a converter is provided in the example source code for this book (xicon2), 
but is not shown here. See Chapter 9, Resource Mangement and Type Conversion, for more 
information on invoking converters. 

Example 10-2. Creating an icon pixmap, and setting XtNiconPixmap 

/* both R3 and R4 (part of Xt) 
#include <Xll/Shell.h> 
#include "icon" 
main(argc, argv) 
int argc; 
char **argv; 
{ 
Pixmap icon_pixmap; 

./ 

292 X Toolkit Intrinsics Programming Manual 



Example 10-3. BitmapEdit: actions that highlight selection 
static char defaultTranslations[] = 
"Shift<BtnlDown> : StartHighlight () \n\ 
Shift<BtnlMotion> : ExtendHighlight () \n\ 
Shift<BtnlUp> : MakeSelection () \n\ 
Shift<Btn2Down> : PasteSelection () \n\ 
-Shift<BtnlDown> : DoCell () \n\ 
-Shift<Btn2Down> : UndoCell () \n\ 
-Shift<Btn3Down> : ToggleCell () \n\ 
-Shift<BtnlMotion>: DoCell() \n\ 
-Shift<Btn2Motion>: UndoCell() \n\ 
-Shift<Btn3Motion>: ToggleCell()"; 

static XtActionsRec actions[] = { 
{"DoCell", DoCell}, 
{"UndoCell", UndoCell}, 
{"ToggleCell", ToggleCell}, 
{"StartHighlight", StartHighlight}, 
{"ExtendHighlight", ExtendHighlight}, 
{"MakeSelection", MakeSelection}, 
{"PasteSelection", PasteSelection}, 

}; 

* User presses first button (by default), starting highlighting. 
*/ 
static void 
StartHighlight(w, event) 
Widget w; 
XButtonEvent *event; 
{ 
BitmapEditWidget cw = (BitmapEditWidget) w; 
cw->bitmapEdit.first box = False; 
-- 
cw->bitmapEdit.select start x = (cw->bitmapEdit.cur x + event->x) 
-- -- _ 
/ cw->bitmapEdit.cell_size_in_pixels; 
cw->bitmapEdit.select_start_y = (cw->bitmapEdit.cur_y + event->y) 
/ cw->bitmapEdit.cell_size_in_pixels; 
/* clear old selection */ 
Redisplay(cw, NULL); 
} 
/, 
* MakeSelection is call when the first button is released (by 
* default). This finishes the user's highlighting, and means 
* triggers ownership of the PRIMARY selection. 
*/ 
static void 
MakeSelection(w, event) 
Widget w; 
XButtonEvent *event; 
{ 
BitmapEditWidget cw = (BitmapEditWidget) w; 
int temp; 
cw->bitmapEdit.select_end_x = (cw->bitmapEdit.cur_x + event->x) 

Interclient Communications 299 



Examp l O-& B#mapEd#: actions nat hhlight section ontinue 
/ cw->bitmapEdit.cell_size_in_pixels; 
cw->bitmapEdit.select_end_y = (cw->bitmapEdit.cur_y + event->y) 
/ cw->bitmapEdit.cell_size_in_pixels; 
if ((cw->bitmapEdit.select end x == cw->bitmapEdit.select start x) 
&& (cw->bitmapEdit?selct_end_y -- -- -- 
cw->bitmapEdit.select_start_y)) { 
Redisplay(cw, NULL); 
return; /* no selection */ 
) 
/* swap start and end if end is greater than start */ 
if (cw->bitmapEdit.select end x < cw->bitmapEdit.select start x) { 
temp = cw->bitmapEdit.select end x; 
-- -- 
cw->bitmapEdit.select end x = cw->bitmapEdit.select start x; 
cw->bitmapEdit.select start x = temp; 
-- -- 
) 
if (cw->bitmapEdit.select_end_y 
< cw->bitmapEdit.select start_y) { 
temp = cw->bitmapEdit.selec_end_y; 
cw->bitmapEdit.select_end_y = 
cw->bitmapEdit.select_start_y; 
cw->bitmapEdit.select_start_y = temp; 
) 
if (XtOwnSelection(cw, XA_PRIMARY, event->time, convert_proc, 
lose_ownership_proc, transfer_done_proc) == 
False) { 
XtWarning("bitmapEdit: failed attempting to become 
selection owner; make a new selection.\n"); 
/* Clear old selection, because lose_ownership_proc 
* isn't registered. */ 
Redisplay(cw, NULL); 

) 
/. 
* ExtendHighlight is called when the mouse is being dragged with 
* the first button down (by default). During this time, the 
* bitmap cells that are selected (by crosses) are dynamically 
* changed as the mouse moves. 
*/ 
static void 
ExtendHighlight(w, event) 
Widget w; 
XMotionEvent *event; 
BitmapEditWidget cw = (BitmapEditWidget) w; 
static int last_drawn_x, last_drawn_y; 
int event_cell_x, event_cell_y; 
event cell x = cw->bitmapEdit.cur x + (event->x / 
-- cw>bitmapEdit.cell_size_n_pixels); 
event_cell_y = cw->bitmapEdit.cur_y + (event->y / 
cw->bitmapEdit.cell_size_in_pixels); 
if ((event cell x == last drawn x) && (event cell_y 
last_drawn_y)) 

300 X Toolkit Intrinsics Programming Manual 



Examp 10-3. BitmapEdit: actions at hhlht sectbn (continue 
return; 
if (cw->bitmapEdit.first box) { 
-- 
DrawBoxOfXs(cw, last_drawn_x, last_drawn_y, False); 
DrawBoxOfXs(cw, event_cell_x, event_cell_y, True); 
} 
else { 
DrawBoxOfXs(cw, event_cell_x, event_cell_y, True); 
cw->bitmapEdit.first box = True; 
-- 
} 
last drawn x = event cell x; 
-- _ _ 
-- 
last_drawn_y = event_cell_y; 
} 
/* 
* DrawBoxOfXs fills a rectangular set of bitmap cells with 
* crosses, or erases them. 
*/ 
static void 
DrawBoxOfXs(w, x, y, draw) 
Widget w; 
Position x, y; 
Bool draw; 
{ 
BitmapEditWidget cw = (BitmapEditWidget) w; 
Position start_pos_x, start_pos_y; 
Dimension width, height; 
GC gc; 
int i, 9; 
start_pos_x = cw->bitmapEdit.cur_x + cw->bitmapEdit.select start x; 
-- _ 
start_pos_y = cw->bitmapEdit.cur_x + cw->bitmapEdit.select_start_y; 
/* swap start and end if end is greater than start */ 
if (x < start_pos_x) { 
width = start_pos_x - x; 
start_pos_x = x; 
} 
else { 
width = x - start_pos_x; 
} 
if (y < start_pos_y) { 
height = start_pos_y - y; 
start_pos_y = y; 
} 
else { 
height = y - start_pos_y; 
} 
for (i=start_pos_x;i < start_pos_x + width;i++) 
for (j=start_pos_y;j < start_pos_y + height;j++) 
DrawX(cw, i, j, draw); 
} 
/* 
* DrawX draws an X in a bitmap cell, in white if a black cell, and 
* in black if a white cell. 

Interclient Communications 301 



Example 10-3. BitmapEdit: actions that highlight selection (continued) 
*/ 
DrawX(cw, x, y, draw) 
BitmapEditWidget cw; 
Position x, y; 
Bool draw; 
( 
GC gc; 
if (cw->bitmapEdit.cell[x + y * cw->bitmapEdit.pixmap_width_in_cells] 
== DRAWN) 
if (draw) 
gc = cw->bitmapEdit.deep_undraw_gc; 
else 
gc = cw->bitmapEdit.deep_draw_gc; 
else 
if (draw) 
gc = cw->bitmapEdit.deep_draw_gc; 
else 
gc = cw->bitmapEdit, deep._undraw_gc; 
XDrawLine(XtDisplay(cw), XtWindow(cw), gc, 
x * cw->bitmapEdit.cell size in pixels, 
-- 
y * cw->bitmapEdit.cell size in pixels, 
-- 
(x + I) * cw->bitmapEdit.cell size in pixels, 
-- 
(y + I) * cw->bitmapEdit.cell size in pixels); 
-- 
XDrawLine(XtDisplay(cw), XtWindow(cw), gc, 
x * cw->bitmapEdit.cell size in pixels, 
(y + I) * cw->bitmapEdi.cell_size_in_pixels, 
(x + I) * cw->bitmapEdit.cell_size_in_pixels, 
y * cw->bitmapEdit.cell size in pixels); 
-- 
} 
The actions shown in Example 10-3 reference some new instance part fields we have added 
to BitmapEditP.h to store the state of the selection. Four of these variables are the x and y 
coordinates in cells of the top-left and bottom-right comers of the highlighted area: 
select_start_x, select_start_y, select_end_x, and select_end_y. 
These coordinates will be used throughout the owner code. (Because these fields are in units 
of bitmap cells, not pixels, their type is int rather than Position.) 
The StartH'ighl "ight action is quite simple. It sets the upper-left comer instance part 
fields based on the button press position in the triggering event. It also clears the highlight- 
ing of the old selection, if one exists, and sets a flag to indicate that this is the beginning of a 
new selection. The first__box flag is added as an instance part field because it will be 
needed in the ExtendHighlight tion. 
ExtendHighlight is responsible for drawing Xs dynamically on the selected cells, much 
as the window manager draws the outline of a window while it is being moved. Xs are drawn 
on each cell in a rectangle of bitmap cells beginning from the cell selected in the Start- 
Highlight action and ending at the cell the pointer button was released in. Extend- 
H'ighl "ight is triggered by pointer motion events that occur while the first button is held 
down. It calculates which bitmap cell the pointer is in, and if the cell is not the same as the 
cell the pointer was in the last time ExtendHigh'l ight was called, it erases the previous 
Xs and draws new ones. This is done using two different GCsmone for drawing in black and 
the other in white, so the color that contrasts with the current state of each cell can be used. 

302 X Too&# Intrinsics Programming Manual 



To support the possibility of having to convert the data to any one of several targets, the code 
branches according to the value of the target passed in, and does its conversions accordingly. 
In the version of BitmapEdit's convert_proc shown here, only one target type is 
handled. Secdon 10.2.9.2 describes how to add more target types, including some that are 
required by the ICCCM such as TARGETS. 
Once the conversion is made, the procedure sets the val ue_ret urn argument passed in to 
a pointer to a block of memory, and length_return to the size of the block. This block 
of memory will be set into a property by Xt and passed to the requestor's callback in the 
same form--as a pointer to a block of memory and a length. This puts constraints on the for- 
mats that can be used for the data. 
For text selections, the data is usually a simple character string. The convert_proc sim- 
ply needs to set *value_return to a pointer to the string, and length_return to the 
length of the string. For BitmapEdit, however, the required data is a string (of bitmap cell 
states) plus width and height values. Since C provides easy ways to put numeric values into 
strings and to get them out again at the other end, we've chosen to handle this data by con- 
vening the numbers to characters and tacking them on to the beginning of the string. 
If your selection is composed of a number of numeric values, you can create a structure con- 
taining the values and then pass a pointer to the structure. However, the structure cannot 
contain pointers, because the data pointed to by these pointers will not be set into the selec- 
tion property. For example, BitmapEdit cannot pass a pointer to a structure containing a 
string pointer field and width and height fields because the block of memory pointed to by the 
string pointer will not be copied. 
In this case, the type_return can simply be the target atom that was passed in, indicating 
that the data is of the requested type. 
The format_return is the size in bits of each element in the array. Since we are passing 
a compound string, this value is 8. If we were passing a structure, l ength_ret urn would 
be 1 and * format return would be 8 times the size of the structure in bytes. 
-- 
Example 10-6 shows BitmapEdit's convert_proc. 

Examp 10-6. B#mapEdit: conve#ing e section vae 
static Boolean 
convert_proc(w, selection, target, type_return, value_return, 
length_return, format_return) 
Widget w; 
Atom *selection; 
Atom *target; 
Atom *type_return; 
XtPointer *value return; 
unsigned long *lngth_return; 
int *format return; 
-- 
l 
BitmapEditWidget cw = (BitmapEditWidget) w; 
int x, y; 
int width, height; 

/* handle all required atoms, and the one that we use */ 
/* Xt already handles MULTIPLE, no branch necessary */ 
if (*target == XA TARGETS(XtDisplay(cw))) { 
-- 

308 X Too&# Intrinsics Programming Manual 



10.2.6 Finally Pasting the Selection (Requestor) 

When the owner's convert_proc returns, Xt sends a SelectionNotify event to the 
requestor. The Xt code on the requestor side then invokes the callback routine the requestor 
registered with the call to XtGetSelectionValue. 

The requestor_callback function is passed all the same arguments that the owner 
received in the convert_proc, plus the values that the owner returned through the argu- 
ment of convert_proc. In the BitmapEdit widget, it sets instance pan fields to paste the 
data. 

Example 10-7 shows the requestor callback function from BitmapEdit. 

Examp I O- Z BitmapEdit: pastg sectbn  reques callback Unction 
/* ARGSUSED */ 
static void 
requestor_callback(w, client_data, selection, type,value,length, format) 

Widget w; 
XtPointer client data; 
Atom *selection;- 
Atom *type; 
XtPointer value; 
unsigned long *length; 
int *format; 

/* cast to XButtonEvent below */ 

BitmapEditWidget cw = (BitmapEditWidget) w; 
if ((*value == NULL) && (*length == 0)) { 
XBell(XtDisplay(cw), I00); 
XtWarning("bitmapEdit: no selection or selection timed out:\ 
try again\n"); 
) 
else { 
XButtonEvent *event = (XButtonEvent *) client data; 
-- 
int width, height; 
int x, y; 
int dst_offset_x, dst_offset_y; 
char *ptr; 

dst offset x = (cw->bitmapEdit.cur x + event->x) / 
-- -- -- 
cw->bitmapEdit.cell size in pixels; 
-- 
dst_offset_y = (cw->bitmapEdit.cur_y + event->y) / 
cw->bitmapEdit.cell size in pixels; 
-- 

printf("dst offset is %d, %d\n", dst_offset_x, dst_offset_y); 

ptr = (char *) value; 
width = atoi(ptr) ; 
ptr = index(ptr, '@') ; 
ptr++; 
height = atoi(ptr) ; 
ptr = &value [8]; 

for (x = 0; x < width; x++) { 
for (y = 0; y < height; y++) 
/* range checking */ 
if (((dst offset x + x) > 
_ -- 

310 X Toolkit Intrinsics Programming Manual 



Table 10-2. Target Types Suggested in ICCCM 

Atom 

TARGETS 
MULTIPLE 
TIMESTAMP 
STRING 
TEXT 
LIST_LENGTH 
PIXMAP 
DRAWABLE 
FOREGROUND 
BACKGROUND 
COLORMAP 
ODIF 
OWNER_OS 
FILE_NAME 
HOST_NAME 
CHARACTER_POSITION 
LINE_NUMBER 
COLUMN_NUMBER 
LENGTH 
USER 
PROCEDURE 
MODULE 
PROCESS 
TASK 
CLASS 
NAME 
CLIENT_WINIX)W 
DELETE 
INSERT_SELECTION 
INSERT_PROPERTY - 

Type 

ATOM 
ATOM_PAIR 
INTEGER 
STRING 
TEXT 
INTEGER 
DRAWABLE 
DRAWABLE 
BITMAP 
PIXEL 
PIXEL 
COLORMAP 
TEXT 
TEXT 
TEXT 
TEXT 
SPAN 
SPAN 
SPAN 
INTEGER 
TEXT 
TEXT 
TEXT 
INTEGER, TEXT 
INTEGER, TEXT 
TEXT 
TEXT 
WINDOW 
NULL 
NULL 
NULL 

Meaning 

List of valid target atoms 
Look in the ConvertSelection property 
Timestamp used to acquire selection 
ISO Latin 1 (+TAB+NEWLINE) text 
Text in owner's encoding 
Number of disjoint parts of selection 
Pixmap ID 
Drawable ID 
Bitmap ID 
Pixel value 
Pixel value 
Colormap ID 
ISO Office Document Interchange Format 
Operating system of owner 
Full path name of a file 
See WM_CLIENT_MACHINE 
Start and end of selection in bytes 
Start and end line numbers 
Start and end column numbers 
Number of bytes in selection 
Name of user running owner 
Name of selected procedure 
Name of selected module 
Process ID of owner 
Task ID of owner 
Class of owner--see WM_CLASS 
Name of owner--see WM_NAME 
Top-level window of owner 
TRUE if owner deleted selection 
Insert specified selection 
Insert specified property 

Because not every widget will support every possible target type, the ICCCM specifies a tar- 
get type of xn_TnRG.TS, tO which the owner is required to respond by returning a list of the 
target types into which it is capable of converting data. 
Normally, a requestor would first call XtGetSelectionValue for XA_TARGETS, and 
then in the callback determine which target it wants to request from the list, and then call 
XtGetSelectionValue again for the desired target with a separate callback to process 
the actual data. This is really two separate selection transfers. 

Interclient Communications 313 



10.2.9.2 Converting the Standard Selections 

The Xmu routine XmuConvertStandardSelection can be used to respond to a TAR- 
GETS selection request, as well as to other standard targets defined by Xmu. 
Example 10-10 shows the portion of the convert_proc for BitmapEdit that handles the 
standard targets. 
This code is adapted from the standard client xclipboard, and can be copied almost directly 
into your widget. 

Examp 10-10. BitmapEdit: conveaingstandarde  econvea_pc 
static Boolean 
convert_proc(w, selection, target, type_return, value_return, 
length_return, format_return) 
Widget w; 
Atom *selection; 
Atom *target; 
Atom *type_return; 
XtPointer *value return; 
-- 
unsigned long *length_return; 
int *format return; 
-- 
{ 
BitmapEditWidget cw = (BitmapEditWidget) w; 
int x, y; 
int width, height; 
XSelectionRequestEvent* req = XtGetSelectionRequest(w, 
*selection, (XtRequestId) NULL); 

/* handle all required atoms, and the one that we use */ 
if (*target == XA TARGETS(XtDisplay(cw))) 
/* TARGETS handling copied from xclipboard.c */ 
Atom* targetP; 
Atom* std_targets; 
unsigned long std_length; 
XmuConvertStandardSelection(cw, req->time, selection, 
target, type_return, 
(XtPointer*)&std_targets, 
&std_length, format_return); 
*value return = XtMalloc(sizeof(Atom)*(std_length + I)); 
-- 
targetP = *{Atom**)value_return; 
*length_return = std_length + I; 
*targetP++ = cw->bitmapEdit.target_atom; 
bcopy((char*)std_targets, (char*)targetP, sizeof(Atom)*std_length); 
XtFree((char*)std_targets); 
*type_return = XA_ATOM; 
*format return = sizeof(Atom) * 8; 
-- 
return (True) ; 
} 
/* Xt already handles MULTIPLE, no branch necessary */ 
else if (*target == cw->bitmapEdit.target_atom) { 
/* handle normal selection - code shown in Example 10-6 */ 

Interclient Communications 315 



10.2.9.3 

Example 10-10. BitmapEdit: converting standard targets in the convert_proc (continued) 

else { 
if (XmuConvertStandardSelection(cw, CurrentTime, selection, 
target, type_return, value_return, 
length_return, format_return)) 
return True; 
else { 
XtWarning("bitmapEdit: requestor is requesting\ 
unsupported selection target type.\n"); 
return(False); 

} 
} 
} 

Overall, this code handles the TARGETS atom in the first branch, the normal selection target 
in the second, and any remaining standard atoms and any unknown atoms as two cases in the 
third branch. For ICCCM-compliant code, you can copy this entire function into your widget 
and then write just the second branch. Note that branches that successfully provide the 
requested data return TRUE, and those branches that don't return FALSE.* 
In the first branch you will also need to change the reference to the instance part field that 
stores the target atom used for selections, bitmapEdit, target_atom. If your widget 
uses a predefined atom or one supported by the Xmu facility, you would reference that atom 
here instead of the instance part field. If you called XTnternAtom in initialize and 
stored the result in an instance part field, you specify that here. 
Note that XtGetSelectionRequest is used to get the time from the Selection- 
Request event that the owner received before Xt called the convert_proc function. 
XtGetSelectionRequest was introduced in R4 for this specific reason; it needs to 
meet the current ICCCM and work around the fact that the convert_proc is defined with- 
out an event argument. (The convert_proc definition could not be changed because of 
the required backwards compatibility with R3.) 

The Clipboard Selection 

According to the ICCCM, if a widget or application allows the user to delete a selection, the 
selection owner code should place the deleted data on the CLIPBOARD selection.t The wid- 
get should be prepared to respond to a request for the contents of the CLIPBOARD, much as it 
does for the PRIMARY selection. The only client that requests data in this way will be xclip- 
board. 

Except when a widget asserts ownership of the CLIPBOARD with XtOwnSelection in 
order to place newly deleted data on it, the xclipboard client is the owner of this property. 
When it starts up, xclipboard asserts ownership of the CLIPBOARD selection. If it loses the 

*The ICCCM also specifies that functions implementing selections must be able to respond to a MULTIPLE target val- 
ue, which is used to handle selections too large to fit into a single property. However, the necessary handling is done 
by the Intrinsics. Your procedures do not need to worry about responding to the MULTIPLE target value; a selection 
request with this target type will be transparently transformed into a series of smaller transfers. 
tAs mentioned earlier, XA_CLIPBOARD is not a predcfined atom, and must be handled via the Xmu atom caching 
mechanism or equivalent code. 

316 X Toolkit Intrinsics Programming Manual 



requestor while it is still engaged in transferring segments to one requestor. The 
convert_proc is called with a request_id argument that identifies the request. 
You write the convert_roc to maintain a record of which segments have been 
delivered for each request_id. One easy way to do this is to use the Xlib context 
manager. 
When each segment is converted, Xt calls the requestor_proc (once for each seg- 
ment), which extracts the data for the requestor and actually pastes it. This function may 
paste the data chunk-by-chunk or wait until the entire transfer is complete and then paste 
the entire selection. 
A zero-length segment terminates the transfer and results in Xt calling the 
t ransfer_doneproc. 

This was the process of a successful transfer. All the remaining callback functions registered 
are for less common occurrences or unsuccessful transfers. The cancel callback is 
-- 
called by Xt on timeout. This means that the transfer is considered complete even though it 
failed. In this process the owner frees memory allocated for the transfer. 

Calls of the l ose_ownership_proc do not indicate completion of in-progress 
transfers--these transfers should continue. It just means that the owner lost ownership of the 
selection, so that the owner should unhighlight what the user selected. 

If transfer_done_proc is specified, the owner allocates and frees storage. If 
transfer_done_proc is NULL, convert_proc must allocate storage using Xt- 
Malloc, XtCalloc or XtRealloc, but Xt will free that memory. The owner may use 
XtDisownSelection to relinquish ownership. (This is the same routine used to relin- 
quish ownership of an atomic selection.) 

10.2.11 

Miscellaneous Selection Routines 

If the user deletes the information selected, the owner should call XtDisownSelection. 
XtSetSelectionTimeout sets the time within which widgets must respond to one an- 
othen This is initially set by the XtNselectionTimeout resource, and defaults to 5 sec- 
on(Is. The selection timeout prevents hanging when the user pastes but the current owner is 
slow or hung. XtGetSelectionTimeout reads the current selection timeout value. 
Widgets should not normally require these two calls, since the selection timeout should re- 
main under the user's control. 
If the requestor can request more than one target type, such as TARGETS and its normal selec- 
tion target, it normally does so using separate actions. (Both actions can be invoked by the 
same triggering event, if desired.) Each action specifies a different target type and a different 
requestor callback. That way, each requestor callback handles only one type of target. 
Beware: there is a danger in this approach. The selection owner might change between the 
repeated XtGetSelectionValue calls. XtGetSelectionValues (plural) can be 
used instead if the requestor would like to receive the data in more than one representation. 
The requestor's single callback function would then be called once for each representation. 
(The owner's convert_roc would also be called once per representation.) 

318 X Toolkit Intrinsics Programming Manual 



11 

Geometry Management 

This chapter discusses how composite and constraint widgets manage the 
layout of widgets, and how to write your own simple composite and constraint 
widgets. 

In This Chapter: 

How Composite Management Works ................................................. 322 
Initial Geometry Negotiation ........................................................... 324 
Basic Core Methods in Composite Widgets .................................... 328 
Laying Out Child Widgets ............................................................... 330 
The change_managed Method ....................................................... 332 
XtQueryGeometry and the query_geometry Method ...................... 332 
XtMakeGeometryRequest and the geometry_manager Method ..... 333 
The insert_child and delete_child Methods ..................................... 335 
How Constraint Management Works .................................................. 336 
Writing a Constraint Widget ................................................................ 336 
The Core Resource List ................................................................. 336 
The Constraint Resource List ......................................................... 337 
Class Structure Initialization ........................................................... 339 
The Constraint irfitialize Method ..................................................... 341 
The class_part_init Method ............................................................ 342 
The geometry_manager Method .................................................... 343 
The resize Method ......................................................................... 347 
The Core and Constraint set_values Methods ................................ 349 
The change_managed Method ....................................................... 349 
The query_geometry Method ......................................................... 350 
Delaying Geometry Recalculation .................................................. 351 
Compound Widgets ........................................................................... 351 
Stacking Order ................................................................................... 352 



11 
Geometry Management 

Composite and constraint widgets lay out the widgets in your application according to certain 
rules. You cannot hardcode the position of widgets in an application because X applications 
can be resized and they must reposition their widgets to take advantage of the available 
space. Because of the window manager, even the initial size of the application may not be 
the application's preferred size. 
Chapter 3, More Techniques for Using Widgets, demonstrated how you can use existing 
composite and constraint widgets in the application. You can control widget layout rules 
with resources. However, you may find that no existing composite or constraint widget can 
be configured with resources to have the layout rules you need. In this case, you will need to 
write your own composite or constraint widget or modify an existing one. However, before 
embarking on writing one of these widgets, you should realize that composite and constraint 
widgets are complex. First investigate the alternatives! Perhaps you can find a composite or 
constraint widget from another widget set that has the layout characteristics you need. If you 
determine that you have no alternative but to write your own composite or constraint widget, 
you should keep it as simple as possible. It is much easier to write a special-purpose widget 
that handles a limited layout situation than it is to write a general-purpose composite or con- 
straint widget like Box or Form. And even Box and Form are simple as composite and con- 
straint widgets go! 
A composite widget is defined as any widget that is a subclass of the Xt-defined class Com- 
posite. A constraint widget is any widget that is a subclass of the Xt-defined class Con- 
straint. Constraint is/ subclass of Composite. As you may recall, a composite widget is the 
simplest kind of geometry-managing widget; it handles all its children equally, or handles 
each child in a fixed way. For example, the Box widget handles all of its children equally. 
As an example of a special-purpose composite widget, Section 11.2 describes a composite 
widget called ScrollBox that manages two scrollbars and a main window. This widget 
requires that it have exactly three children added in a particular order. 
A constraint widget has all the characteristics of composite widgets but maintains configur- 
able data about each child so that it can cater to the needs of each child. By setting the con- 
straint resources of a child of a constraint widget, you configure the constraint widget's lay- 
out policy for that child. Constraint widgets are inherently more powerful than composite 
widgets, but are also more complicated to write. A constraint widget requires all the code of a 
composite widget, plus code to handle the constraints of each child. Because of this com- 
plexity, you should hesitate even further before attempting to write a constraint widget. As 

Geometry Management 321 



Figure 11-3 shows the continued process of initial geometry negotiation if the user has speci- 
fied the top-level geometry through resources rather than accepting the application's built-in 
defaults. 

Shell 

Form 

Box 

Command 

Command 

Xt 
lntrinsics 
routines 

If user specifies shell geometry, resize methods called from top down 

t __ 
Figure 11-3. Initial geometry negotiation, if resizing is necessary 

Note that this process and the methods involved are more complicated Therefore, we do not 
nd a geometry_manager method. 

A ScrollBox widget is shown managing BitmapEdit and two scrollbars in Figure 11-4.* 

The Athena Viewlx)rt widget does scrollbar management in a more general way than does 
ScrollBox. It is a subclass of Form that takes any main window as a child and creates 
scrollbars. It shows only a small portion of the main window and uses the scrollbars to deter- 
mine which portion of the main window is shown. But Viewport doesn't work well with 
BitmapEdit because BitmapEdit has a built-in ability to display in a smaller window that 
conflicts with Viewlx)rt's efforts. Besides, Viewport is several times larger and more compli- 
cated than ScrollBox, because it includes the scrollbar callback functions and because it hon- 
ors a child's geometry preferences. ScrollBox is a modest widget that manages the geometry 

*ScrollBox widens the borders of its children, for an unknown reason. It might as well be admitted that there is prob- 
ably a bug in it somewhere! 

326 X Toolkit Intrinsics Programming Manual 



common routine called by the set_values, resize, and change_managedvalues. 
This is followed by further discussion of the change_managed and query_geometry 
methods. Then, we go on to discuss the methods not used by ScrollBox, but that would be 
used in more complicated composite widgets, in particular geomet ry_manager. Finally, 
we briefly discuss the methods available in composite widgets but rarely needed: 
set_values_almost, insert_child, and delete_child. 

11.1.2 

Basic Core Methods in Composite Widgets 

Both composite and constraint widgets are subclasses of Core. Therefore, they have all the 
Core methods described in Chapters 5 and 6. However, since composite and constraint widg- 
ets usually have no input and output semantics, the expose method is set to NULL and the 
widget has no default translation table or actions. As a result, all the event-oriented fields in 
the Core class structure become irrelevant to composite and constraint widgets. 
But composite and constraint widgets do use the Core initialize, realize, and 
set_values methods. These methods have the same roles as for simple widgets. The 
ini t i a 1 i z e method initializes instance part variables and checks initial resource values. 
The realize method sets window attribute values and then creates a window for the 
widget. The set_values method updates any instance part fields that depend on 
resources. Since composite and constraint widgets don't need GCs, initialize and 
set_values don't contain code to create and change GCs as in simple widgets. 
These three methods for ScrollBox are absolutely minimal, and call a common routine called 
DoLayout when any actual sizing or positioning of widgets is required. The initial- 
ize method simply sets the widget's default width and height, the realize method is 
inherited, and the set_values method changes the layout of children when either of 
ScrollBox's two resources is changed. These resources control the vertical and horizontal 
distance in pixels that will be left between the Scrollbar widgets and the main widget, and 
between each of these widgets and the borders of ScrollBox. Example 11-1 shows the 
set values method of ScrollBox. 
-- 

Examp 11-1. ScmllBox: e se vaes meod 
/* ARGSUSED */ 
static Boolean SetValues(current, request, new, args, num_args) 
Widget current, request, new; 
ArgList args; 
Cardinal *num_args; 
{ 
ScrollBoxWidget sbwcurrent = (ScrollBoxWidget) current; 
ScrollBoxWidget sbwnew = (ScrollBoxWidget) new; 

/* need to relayout if h_space or v_space change */ 
if ((sbwnew->scrollBox.h_space != sbwcurrent->scrollBox.h_space) 
(sbwnew->scrollBox.v_space != 
sbwcurrent->scrollBox.v_space)) 
DoLayout(sbwnew); 

return False; 

II 

328 X Toolkit Intrinsics Programming Manual 



Two more Core methods are used in composite widgets: re s i z e and que ry_geomet ry. 
The res i ze method changes the layout of its children and is shown in Example 11-2. 

Examp 11-2. ScmllBox: He resize meod 
static void Resize(w) 
Widget w; 
{ 
ScrollBoxWidget sbw = (ScrollBoxWidget) w; 

DoLayout (sbw) ; 

The query_geometry method answers the parent's inquiry about a size change for this 
composite widget and is shown in Example 11-3. 

Examp 11-3. ScrollBox: He que_geometry method 
/* ARGSUSED */ 
static XtGeometryResult QueryGeometry(w, request, reply_return) 
Widget w; 
XtWidgetGeometry *request, *reply_return; 
{ 
XtGeometryResult result; 
request->request_mode &= CWWidth I CWHeight; 
if (request->request mode == 0) 
/* parent isn't goin to change w or h, so nothing to 
* re-compute */ 
return XtGeometryYes; 
/* if proposed size is large enough, accept it. Otherwise, 
* suggest our arbitrary initial size. */ 
if (request->request_mode & CWHeight) { 
if (request->height < INITIAL_HEIGHT) { 
result = XtGeometryAlmost; 
reply_return->height = INITIAL_HEIGHT; 
reply_return->request_mode &= CWHeight; 
} 
else 
result = XtGeometryYes; 
} 
if (request->request_mode & CWWidth) { 
if (request->width < INITIAL_WIDTH) { 
result = XtGeometryAlmost; 
reply_return->width = INITIAL_WIDTH; 
reply_return->request_mode &= CWWidth; 
} 
else 
result = XtGeometryYes; 

return (result) ; 

Geometry Management 329 



Although the query_geometry method has the same role in all widgets, composite and 
simple, a composite widget's size preference depends on its children. Normally this means 
the query_geometry method will query its children and try different layouts until it 
arrives at the geometry, or some approximation of it, suggested by its parent This calcula- 
tion is complicated because the widget may have any kind of child, and their responses to 
geometry suggestions are unpredictable. ScrollBox ignores this complexity because it knows 
exactly what kinds of children it will have and what their characteristics are. Therefore, its 
query_geometry method is basically the me as the query_geometry method of a 
simple widget 

To be more precise, what this query._geometry method does is accept any size suggested 
by the parent which is larger than the minimum useful size of the application. When the sug- 
gested size is too small, the query_geometry method uses the minimum useful size as a 
compromise. Note, however, that this is really hardcoding the characteristics of the child into 
our composite widget It would be better to add resources to control the minimum useful 
size. 

11.1.3 

Laying Out Child Widgets 

Composite widgets need to calculate a layout and manipulate their child widgets from 
set_values, from resi ze, and from change_managed. Therefore, in most compos- 
ite widgets this common code is placed in a single routine called DoLayout. Example 11-4 
shows the DoLayout routine from ScrollBox. 

Examp 11-4. ScrollBox: priva routine layoutchildwidge 
/* ARGSUSED */ 
static DoLayout(w) 
Widget w; 
{ 

ScrollBoxWidget sbw = (ScrollBoxWidget) w; 
Widget main, vscroll, hscroll; 
Widget child; 
Dimension mw, mh; /* main window */ 
Dimension vh; /* vertical scrollbar length (height) */ 
Dimension hw; /* horizontal scrollbar length (width) */ 
Position vx; 
Position hy; 
int i; 
if (sbw->composite.num children != 3) 
XtAppError(XtWidgetToApplicationContext(sbw), 
"ScrollBox: must manage exactly three widgets."); 
for (i = 0; i < sbw->composite.num children; i++) { 
child = sbw->composite.children[i]; 
if (!XtIsManaged(child)) { 
XtAppError(XtWidgetToApplicationContext(sbw), 
"ScrollBox: all three widgets must be managed."); 
} 

330 X Toolkit Intrinsics Programming Manual 



Examp 11-4. ScrollBox: priva routine  lay out child widge ontinue 
/* Child one is the main window, two is the vertical scrollbar, 
* and three is the horizontal scrollbar. */ 
main = sbw->composite.children[0]; 
vscroll = sbw->composite.children[l]; 
hscroll = sbw->composite.children[2]; 
/* Size all three widgets so that space is fully utilized. */ 
mw = sbw->core.width - (2 * sbw->scrollBox.h_space) - 
vscroll->core.width - (2 * vscroll->core.border width) - 
-- 
(2 * main->core.border width); 
-- 
mh = sbw->core.height - (2 * sbw->scrollBox.v_space) - 
hscroll->core.height - (2 * hscroll->core.border width) - 
-- 
(2 * main->core.border width); 
-- 
vx = main->core.x + mw + sbw->scrollBox.h_space + 
main->core.border width + vscroll->core.border width; 
-- _ 
hy = main->core.y + mh + sbw->scrollBox.v_space + 
main->core.border width + hscroll->core.border width; 
-- _ 
vh = mh; /* scrollbars are always same length as main window */ 
hw = mw; 
XtResizeWidget(main, mw, mh); 
XtResizeWidget(vscroll, vscroll->core.width, vh); 
XtMoveWidget(vscroll, vx, vscroll->core.y); 
XtResizeWidget(hscroll, hw, hscroll->core.height); 
XtMoveWidget(hscroll, hscroll->core.x, hy); 

In general, DoLayout moves and resizes the child widgets according to its layout policy. 
This routine may query the children with XtQueryGeometry before making decisions, 
but it is not required to. In this case, there is no need to because ScrollBox handles only two 
types of widgets with no size preferences. 

DoLayout is passed only one argument, ScrollBox's own widget ID (a pointer to its widget 
instance structure). But the composite children field in ScrollBox's instance structure is 
an array of the IDs of all the children, and hum_children is the number of children.* 
. 
When each child is added to a composite widget, its ID is added to the children field of 
the composite part of the instance structure, and the hum_children field is incremented. 
Therefore, the code to lay out the children is usually a loop that treats each child one at a 
time. This often takes two passes, since the routine needs to know which children are man- 
aged before it can determine their final geometries. All children, even unmanaged ones, are 
listed in the children and hum children fields. 
-- 

This particular DoLayout procedure makes sure that there are exactly three children and 
that they are all managed. Then, it calculates the positions and sizes for all the children so 
that they will fill all the available space in ScrollBox's own window. Finally, it calls 

*Incidentally, the chi ldren and num_chi ldren fields are resources. However, they are read-only from outside 
the widget code; the application should never set them with X t Se t Va 1 ue s. 

Geometry Management 331 



Composite and constraint widgets play the role of both parent and child. When you write a 
composite widget, you may call XtQueryGeometry in several places to get the child's 
response to your proposed size. You will also need to write a query_geometry method 
so that your composite can respond to its parent's XtQueryGeomet ry request. 

A query_geometry method in a composite widget should base its response on the size 
preferences of its children. It should calculate a new layout based on the proposed geometry 
passed in, and then query its children to get their opinions of their new geometry. If any of 
the children is a composite widget, they may query their children, and so on. Therefore, 
these requests tend to trickle down to the lowest widget in the hierarchy. ScrollBox took the 
biggest shortcuts in its query_geometry method. Not only didn't it query its children, 
but it hardcoded its response based on the characteristics of the kind of main window it 
expected. This would be the first place to begin improving ScrollBox. 

Note, however, that a composite widget is allowed to be authoritarian and not ask its children 
whether they like the sizes they are about to be given. However, this kind of composite 
widget will not be suitable as a parent of a widget that really needs certain size preferences. 

In R4 and later, a parent must specify a complete proposed geometry when calling xt- 
Que ryGeomet ry, not just the changes it intends to make as was specified in R3. 

11.1.6 

XtMakeGeometryRequest and the geometry_manager Method 

XtHakeGeometryRequest calls are made for two reasons. First, when a composite 
widget honors its children's size preferences, it may find that its current size is inadequate to 
lay out its children. In this case, it should ask its parent to be resized by calling XtHake- 
GeometryRequest. Second, Xt calls XtHakeGeometryRequest for a widget when 
the application has changed a resource that affects geometry. 
As mentioned above, XtMakeGeometryRequest calls the parent's geometry_ 
manager method. The parent's geometry_manager has the job of deciding whether 
the size proposed by the child is acceptable. A subclass of Composite must either define a 
geomet ry_manager method, or set this field in the class structure to NULL, because there 
is no default method to inherit. The XtInheritGeometryManager symbol can be 
used only in subclasses of a class that defines a geometry_manager method. Any com- 
posite widget allowin its Children to suggest resizing will require a geomet ry_manager 
method of its own. 
The way the arguments and returned values are passed between XtMakeGeometry- 
Request and the parent's geometry_manager method is almost exactly parallel to the 
way XtQueryGeometry calls the child's query_geometry method. Both calls take 
pointers to two structures of the same types where one is used for a returned compromise. 
Both take no more arguments other than the widget ID. Both return an enum value of type 
XtGeometryResult. The returned value of the geometry_manager method is, gen- 
erally speaking, passed through as the returned value of XtMakeGeometryRequest. 
Review Section 6.6 so that these structures, their fields and values, and the returned values 
are fresh in your mind. 

Geometry Management 333 



One difference between the way the query_geometry and geometry_manager 
methods are invoked is that the geometry_manager method can return a fourth enum 
value, XtGeomet ryDone (in addition to XtGeomet ryYes, XtGeomet ryNo, and Xt- 
Geomet ryAlmost). The return codes of the geometry_manager method are summa- 
rized in Table I I-I. set_values almost is to accept the compromise geometry pro- 
-- 
posed by the parent or to propose a different geometry to the parent. Once a new geometry is 
proposed by the set_values_almost method, Xt calls the parent's geometry_man- 
ager method again, and the cycle repeats until the geometry_manager returns Xt- 
GeometryYes or XtGeometryDone, or until the child gives up trying to change size. 
Figure 11-5 illustrates this process. 

Xt calls parent 
geomet ry_manage r again. 

Parent's 
geometry_manager 
analyses child suggestion and 
returns value and possibly a 
compromise. Must make 
sure this is not an infinite 
loop. XtGeomet ryYes 
means compromise accepted. 

Child 

i 

If returned value is XtGeometryNo Child's set values almost method 
-- _ 
or XtGeometryAlmost, Xt calls proposes a new geometry based on 
child's set values almost information passed in, or gives up. If new 
method, geometry back to 

Figure 11-5. Geometry negotiation by the set_values_almost method 

Most widgets inherit this method from the Core widget by specifying XtInheritSet- 
ValuesAlmost in the Core class part initialization. This inherited method always ap- 
proves the suggestion made by the parent geometry__manager method. If your widget 
really depends on being certain sizes, however, you will need to write a set_values_ 
almost method. You should never specify a NULL set_values_almost method be- 
cause Xt will print a warning message when set values almost would have been 
-- -- 
called, and continue as if it had been called and had returned XtGeometryYes. 

334 X Toolkit Intrinsics Programming Manual 



The set values almost method is passed pointers to two XtWidgetGeometry 
__ -- 
structures: request and reply. The request structure contains the child's original re- 
quest and reply includes the geometry_manager method's compromise geometry if 
geometry_manager returned XtGeometryAlmost. To accept the compromise, the 
procedure must copy the contents of the reply geometry into the request geometry; to attempt 
an alternate geometry, the procedure may modify any pan of the request argument; to termi- 
nate the geometry negotiation and retain the original geometry, the procedure must set 
request->request_mode to zero. 

If geometry_manager returned XtGeometryNo, it will not have generated a compro- 
mise. In this case, the set values almost method may suggest a new geometry, but it 
__ -- 
is probably not worth it since the method has no information upon which to base its changes 
to its previous suggestion. The set__values_almost method at this point should usually 
just set request->request_mode to zero to terminate the geometry negotiation. 

11.1.7 

The insert child and delete child Methods 

The Composite class has an instance part structure that contains an array of all the widget's 
children (even those not currently managed), the current number of children, and the total 
number of child slots available. The insert child method inserts the ID of a child into 
-- 
this array. It is called when the child is created by a call to XtCreateWidget or Xt- 
CreateManagedWidget. Most widgets inherit the insert_child method from the 
Composite class by specifying the symbolic constant XtInheritInsertChild in the 
class structure initialization. A class would replace the default insert_child method to 
control the position of each child added, or to limit the number or classes of widgets that can 
be added. 
A composite widget can control the position of each child added by calling a function whose 
pointer is stored in the instance pan field insert_position. The function should return 
the number of widgets before the widget. The XtNinsertPosition resource sets this 
function pointer. The default insert_position function returns the current number of 
children. Of course, because this resource's value is a function pointer, it can be specified in 
the application only at run time, never through the resource files or command line. 
The delete chil-d method removes the ID of a child from the child array and is called 
-- 
when the application calls XtDestroyWidget. This method is almost always inherited 
from Composite by specifying the symbolic constant XtInheritDeleteChild in the 
class structure initialization. 

Geometry Management 335 



11.2 How Constraint Management Works 

The first thing to realize about constraint widgets is that everything said about composite 
widgets is still true. Because Constraint is a subclass of Composite, all the methods de- 
scribed above are still present and have the same tasks. However, constraint widgets also 
maintain a structure full of data attached to each child, set through resources. Every time it 
lays out the children, the constraint widget reads this data to determine how to handle that 
child. Of course, it still may query each children to get its opinion of a new size. The con- 
straint information adds another level of complexity to the situation. 

Like composite widgets, constraint widgets can be drastically simplified by reducing flexibil- 
ity and features. The Athena Form widget, for example, never queries its children for their 
geometry input and never asks its parent for a size change. Furthermore, its constraints for 
each child are quite limited. This makes Form quite short and simple, but also means that it 
doesn't always do the right thing. 

11.3 Writing a Constraint Widget 

The following sections describe the portions of the Athena Form widget that relate to geome- 
try management. This will give you a birds-eye view of constraints in action. 

11.3.1 

The Core Resource List 

The Form widget has only one resource of its own, XtNdefaultDistance, as shown in 
Example 11-5. This resource is used only as the default for two of the Constraint resources, 
XtNhorizDistance and XtNvertDistance. XtNdefaultDistance is used to 
set the instance field default_spacing, which is used in only one place in the widget, in 
the Constraint initialize method described in Section 11.4.4. 

Examp 11-5. Form: He Coreresource t 
#define Offset(field) XtOffsetOf(FormRec, form.field) 
static XtResource resources[] = { 
XtNdefaultDistance, 
XtCThickness, 
XtRInt, 
sizeof(int), 
Offset(default_spacing), 
XtRImmediate, 
(XtPointer)4 
l 
l; 
#undef Offset 

336 X Toolkit Intrinsics Programming Manual 



11.3.2 The Constraint Resource List 

The Form widget has three groups of constraint resources. XtNhorizDistance, Xt- 
NfromHori z, XtNvertDistance, and XtNfromVert together control the initial po- 
sition of a child. XtNtop, XtNleft, XtNbottom, and XtNright govern reposifioning 
of the child when Form is resized. The XtNresizable resource controls whether the 
geometry_manager of this widget will honor requests to change the geometry of this 
child. Note that XtNresi zable does not control whether tiffs constraint widget can resize 
a child--only whether or not it will do so becau of a request from the child.* 

For more details about how the constraint resources work, read about them on the reference 
page for the Form widget in Volume Five, X Toolkit Intrinsics Reference Manual. 

Constraint resources are also called simply constraints, particularly because they are stood 
in a Con instance field called constraints. Example 11-6 shows Form's constraint re- 
source list. 

Examp 11-& Form: constratresoue t 
static XtEdgeType defEdge = XtRubber; 
#define Offset(field) XtOffsetOf(FormConstraintsRec, form.field) 
static XtResource formConstraintResources[] = { 
{ 
XtNhorizDistance, 
XtCThickness, 
XtRInt, 
sizeof(int), 
Offset(dx), 
XtRImmediate, 
(XtPointer)DEFAULTVALUE 
), 
{XtNfromHoriz, XtCWidget, XtRWidget, sizeof(Widget), 
Offset(horiz base), XtRWidget, (XtPointer)NULL}, 
-- 
{XtNvertDistance, XtCThickness, XtRInt, sizeof(int), 
Offset(dy), XtRImmediate, (XtPointer)DEFAULTVALUE}, 
{XtNfromVert, XtCWidget, XtRWidget, sizeof(Widget), 
Offset(vert base), XtRWidget, (XtPointer)NULL}, 
-- 
{XtNtop, XtCEdge, XtREdgeType, sizeof(XtEdgeType), 
Offset(top), XtREdgeType, (XtPointer)&defEdge}, 
{XtNbottom, XtCEdge, XtREdgeType, sizeof(XtEdgeType), 
Offset(bottom), XtREdgeType, (XtPointer)&defEdge}, 
{XtNleft, XtCEdge, XtREdgeType, sizeof(XtEdgeType), 
Offset(left), XtREdgeType, (XtPointer)&defEdge}, 
{XtNright, XtCEdge, XtREdgeType, sizeof(XtEdgeType), 
Offset(right), XtREdgeType, (XtPointer)&defEdge}, 

{XtNresizable, XtCBoolean, XtRBoolean, sizeof(Boolean), 
Offset(allow resize), XtRImmediate, (XtPointer)FALSE}, 
-- 
}; 
#undef Offset 

*The fact that Form does not provide individual control over the resizability of each child is a major weakness. 

Geometry Management 337 



11.3.3 Class Structure Initialization 

The Form class is a subclass of Constraint. Therefore, its class structure contains class parts 
for Core, Composite, Constraint, and Form. Example 11-8 shows the class structure initiali- 
zation of Form. Several methods referenced here have not been discussed so far in this book. 
They are the Core methods class_initialize and class_part_init, and the 
Constraint methods initialize and set_values. These and all the geomey man- 
agement-related methods of Form will be discussed in Section 11.4.6. 

Example 11-8. Form: class structure initialization 

FormClassRec formClassRec = { 
{ /* Core class fields */ 
/* superclass */ 
/* class name */ 
-- 
/* widget_size */ 
/* class initialize */ 
-- 
/* class_part_init */ 
/* class inited */ 
-- 
/* initialize */ 
/* initialize hook */ 
-- 
/* realize */ 
/* actions */ 
/* num actions */ 
-- 
/* resources */ 
/* num resources */ 
-- 
/* xrm class */ 
-- 
/* compress_motion */ 
/* compress_exposure */ 
/* compress_enterleave*/ 
/* visible interest */ 
-- 
/* destroy */ 
/* resize */ 
/* expose */ 
/* set values */ 
-- 
/* set values hook */ 
-- -- 
/* set values almost */ 
-- -- 
/* get_values_hook */ 
/* accept_focus */ 
/* version */ 
/* callback_private */ 
/* tm table */ 
-- 
/* query_geometry */ 
/* display_accelerator / 
/* extension */ 
1, 
{ /* 
/* 
/* 
/* 
/* 
/* 
1, 
{ /* 
/* 
/* 

(WidgetClass) &constraintClassRec, 
"Form", 
sizeof(FormRec), 
ClassInitialize, 
ClassPartInitialize, 
FALSE, 
Initialize, 
NULL, 
XtInheritRealize, 
NULL, 
0, 
resources, 
XtNumber(resources), 
NULLQUARK, 
TRUE, 
TRUE, 
TRUE, 
FALSE, 
NULL, 
Resize, 
XtInheritExpose, 
SetValues, 
NULL, 
XtInheritSetValuesAlmost, 
NULL, 
NULL, 
XtVersion, 
NULL, 
NULL, 
PreferredGeometry, 
XtInheritDisplayAccelerator, 
NULL 

Composite class fields */ 
geometry_manager */ GeometryManager, 
change_managed */ ChangeManaged, 
insert child */ XtInheritInsertChild, 
-- 
delete child */ XtInheritDeleteChild, 
-- 
extension */ NULL 

Constraint class fields */ 
subresourses */ formConstraintResources, 
subresource count */ XtNumber(formConstraintResources), 
-- 

Geometry Management 339 



Example 11-8. Form: class structure initialization (continued) 

/* 
I* 
I* 
I* 
I* 
}, 
{ /* 
/* 
} 
}; 

constraint size */ sizeof(FormConstraintsRec), 
-- 
initialize */ ConstraintInitialize, 
destroy */ NULL, 
set values */ ConstraintSetValues, 
-- 
extension */ NULL 

Form class fields */ 
layout */ Layout 

WidgetClass formWidgetClass = (WidgetClass)&formClassRec; 
Note that the Form class is the first widget we have shown that defines a class part field--a 
method of its own, called layout. Since this method is not known to Xt, Xt will never call 
it. The widget must invoke this method itself at the appropriate times (you will see this invo- 
cation in the methods below). This code is made into a method instead of just a private func- 
tion only to make it possible for subclasses of this widget to inherit or replace the method. 
Having such a method requires that the widget have a classart_init method to 
handle the inheritance if a subclass specifies the layout method with the symbolic constant 
xt r nhe ri t Layout (also defined in this class's private header file). 
Section 11.2.1 described which Core and Composite methods are required for composite 
widgets, and how to initialize the other Core and Composite fields for a composite widget. 
The same is true for constraint widgets. 
However, the Conslxaint part is probably new to you. The ConstraintClassPart 
structure contains seven fields. The first three fields are where the constraint resource list, the 
number of resources, and the size of the constraint instance structure are entered. This re- 
source list and instance structure were described in the last section. These fields are analo- 
gous to the resources, hum_resources, and widget_si ze fields in the Core class 
part. 
The three next fields, initialize, destroy, and set values are methods defined 
-- 
by the Consaint class. These methods have the same field names as methods of Core, but 
are fields of a different structure, and contain pointers to different functions that you may 
need to write. To differentiate Conslxaint methods from the Core methods, we will precede 
the names of Conslxaint fields with the word "Constraint" and the names of Core fields with 
the word "Core" throughout this chapter. 
Two of the three Conslxaint methods will be described where they fit in below. We'll de- 
scribe one of them, Conslxaint destroy, now, because it is not used in Form and is less 
likely to be needed in the conslxaint widgets you may write. The Conslxaint destroy 
method is called when a child is deslxoyed, just before the Core destroy method of the 
child. It is responsible for freeing any memory allocated by the conslxaint widget that was 
used to manage that child. However, like the Core destroy method, it does not need to 
free memory allocated by Xt, such as the constraint data structure for the child. 

340 X Toolkit Intrinsics Programming Manual 



Usually, only the class that defines a particular new method resolves the inheritance by 
checking for the value of that field in its class_part_init method. There is no point in 
a subclass also checking for an Xtrnherlt value, since the downward chaining means that 
the superclass will have already processed and replaced the XtXnherit value before the 
subclass c 1 a s s_.pa rt_ini t method is called. 

11.3.6 

The geometry_manager Method 

geomet ry__manager methods handle requests from the children to be resized. Therefore, 
they typically use the proposed geometry passed in from the child to calculate a new experi- 
mental layout, and actually move and resize the children if the new layout is acceptable. 
However, when the request is just a query, the method should be able to return the same val- 
ues without actually moving or resizing anything. 
The Form geometry_manager method is shown in Example 11-11. Note that Form uses 
the allow resize field (the XtNresizable resource) to determine whether to even 
-- 
consider the resize request. Then, if the request specifies a width and height, Form will ac- 
cept the change by returning XtGeometryYes. The XtMakeGeometryRequest call 
that invoked the geometry_manager will actually make the geometry change before re- 
turning to the child's code. If the request specifies any other geometry change (border width, 
position, or stacking order), Form will deny the request. Finally, if the request was not a 
query, Form actually does the new layout. Note that Form never returns XtGeometry- 
Done since it never makes the geometry changes itself. Instead it returns XtGeometry- 
Ye s when it agrees with the changes, and lets Xt make the changes. 
Note that the allowed structure in this routine could be replaced by individual width and 
height variables. Also note that the reply structure is never filled; it is used only when 
the geomet ry_manage r method wants to suggest a compromise. 

Examp 11-11. Form: e geomet_manager meod 
/* ARGSUSED */ 
static XtGeometryResult GeometryManager(w, request, reply) 
Widget w; 
XtWidgetGeomgtr  *request; 
XtWidgetGeometry *reply; /* RETURN */ 
l 
FormConstraints form = (FormConstraints)w->core.constraints; 
XtWidgetGeometry allowed; 
if ((request->request mode & -(XtCWQueryOnly I 
-- 
CWWidth I CWHeight)) II 
!form->form.allow resize) 
-- 
return XtGeometryNo; 
if (request->request_mode & CWWidth) 
allowed.width = request->width; 
else 
allowed.width = w->core.width; 
if (request->request_mode & CWHeight) 
allowed.height = request->height; 
else 

Geometry Management 343 



Example 11-11. Form: the geometry_manager method (continued) 
allowed.height = w->core.height; 
if (allowed.width == w->core.width && allowed.height == 
w->core, he ight ) 
return XtGeometryNo; 
if (! (request->request_mode & XtCWQueryOnly)) { 
/* reset virtual width and height. */ 
form->form.virtual width = w->core.width = allowed.width; 
-- 
form->form.virtual_height = w->core.height = allowed.height; 
RefigureLocations((FormWidget)w->core.parent) ; 
) 
return XtGeometryYes ; 
} 
The RefigureLocations called from the geometry_manager method is a pdva 
function analogous to the DoLayout routine used in ScrolIBox, except that Refigure- 
Locations calls Form's layout method that conns the actual layout code so that the 
method can be inherited or replaced by subclasses. The layout method calculates a layout 
and moves and resizes the children. RefigureLocations is also called from the 
change_managed method, as described in Section 11.4.9. Example 11-12 shows the 
RefigureLocations function and Form's layout method, which it calls. (The if 
statement that branches depending on the value of the no refigure field allows an appli- 
-- 
cation to turn relayout on and off, as described in Section 11.4.11.) 

Examp 11-12. Form: pdva nctions: RefigureLocations and the layout meod 
static void RefigureLocations(w) 
FormWidget w; 
( 
/* no_refigure supports the relayout recalculation 
delay described later in this chapter */ 
if (w->form.no_refigure) { 
w->form.needs_relayout = True; 
} 
else { 
(*((FormWidgetClass)w->core.widget_class)->form_class.layout) 
( w, w->core.width, w->core.height ); 
w->form.needs_relayout = False; 
} 
} 
/* ARGSUSED */ 
static Boolean Layout(fw, width, height) 
FormWidget fw; 
Dimension width, height; 
( 
int hum children = fw->composite.num children; 
-- -- 
WidgetList children = fw->composite.children; 
Widget *childP; 
Position maxx, maxy; 
static void LayoutChild(); 
Boolean ret val; 
-- 
for (childP = children; childP - children < hum children; 
-- 
childP++) { 

344 X Toolkit Intrinsics Programming Manual 



knows how big to be to fit all the children. Finally, it requests of its parent that it be just big 
enough to fit its children. If the parent denies the request, the code makes no attempt to make 
another request. If the parent offers a compromise, it is accepted. The Form widget, in either 
case, may be too big or too small to fit its children. If it is too small, some of its children will 
be clipped. 
The LayoutChild routine is shown in Example 11-13. What it does is simple, although it 
is a little hard to follow because it is called recursively. It moves the child according to the 
XtNf romHori z and XtNf romVe rt constraint resources.* These resources specify that 
a child be placed to the right of or below another particular child. 

Examp 11-13. Form: e LayoutChiid priva nction 
static void LayoutChild(w) 
Widget w; 
{ 
FormConstraints form = (FormConstraints)w->core.constraints; 
Position x, y; 
Widget ref; 
switch (form->form.layout_state) { 
case LayoutPending: 
form->form.layout_state = LayoutInProgress; 
break; 
case LayoutDone: 
return; 
case LayoutInProgress: 
String subs[2]; 
Cardinal hum subs = 2; 
-- 
subs[0] = w->core.name; 
subs[l] = w->core.parent->core.name; 
XtAppWarningMsg(XtWidgetToApplicationContext(w), 
"constraintLoop","xawFormLayout","XawToolkitError", 
"constraint loop detected while laying out child\ 
'%s' in FormWidget '%s'", 
subs, &hum subs); 
-- 
return; 
} 
x = form->form.dx; 
y = form->form.dy; 
if ((ref = form->form.horiz base) != (Widget)NULL) { 
-- 
LayoutChild (ref) ; 
x += ref->core.x + ref->core.width + 
(ref->core.border width 
-- 
<< i); 
} 
if ((ref = form->form.vert base) != (Widget)NULL) { 
-- 
LayoutChild(ref); 
y += ref->core.y + ref->core.height + 
(ref->core.border width 
-- 

*Form resizes children only when it is resized--never during normal layout. 

346 X Toolkit Intrinsics Programming Manual 



You can control the initial stacking order of a group of children by creating them in the de- 
sired order. The most recently created widget appears on the bottom. (This is the opposite of 
what you might expect if you know that newly created X windows appears on top of their 
siblings. The difference is due to the way a composite widget maintains its list of children.) 

Geometry Management 353 



12 

Menus, Gadgets, 
and Cascaded Pop Ups 

This chapter describes how menus work, and several ways to create menu 
widgets. One of these ways involves the use of windowless widgets, or gad- 
gets. This chapter also describes how to use more advanced features of the 
Xt pop up mechanism, including modal cascades, to implement cascading 
pop up menus. 

In This Chapter: 

Menu Styles and Implementation ....................................................... 359 
How Menus are Popped Up ........................................................... 360 
Menu Panes .................................................................................. 361 
Several Ways to Create and Use Menus ............................................ 363 
A Spring-Loaded Menu: Pointer Grabbing ..................................... 363 
A Drop-Down Menu ....................................................................... 371 
Cascaded Menus ........................................................................... 374 
Using the R4 SJmpleMenu Widget .................................................. 379 
Delayed Popup Creation ................................................................ 383 
About Dialog Boxes ........................................................................... 384 
Gadgets ............................................................................................. 385 
Inside a Gadget ............................................................................. 388 
Private Header File ........................................................................ 389 
The Gadget Source File ................................................................. 390 
The Public Header File ................................................................... 391 
The Gadget Parent ........................................................................ 391 



12 
Menus, Gadgets, 
and Cascaded Pop Ups 

In Chapter 2, Introduction to the X Toolkit, we show a simple example that pops up a dialog 
box. This chapter is much more thorough in describing the Xt facilities for managing pop 
ups, including both pop-up menus and dialog boxes. 
Although the menus provided by various widget sets vary greatly in the way they look and in 
the way they are used in the application, the underlying Xt facilities for managing them are 
the same. This chapter presents a series of examples based on R4 Athena widgets that imple- 
ment menus in different ways. While some of the techniques shown may be hidden within 
the menu widgets provided in commercial widget sets, it will help you understand menus bet- 
ter to see the underlying techniques fully exposed and explored. 
This chapter also discusses cascaded pop ups--pop ups that call other pop ups--and the 
event management necessary to have pop ups that shut out other input elsewhere in the appli- 
cation and system. 
Finally, this chapter discusses windowless widgets called gadgets, which have been designed 
to reduce window system overhead. Their most important use is to implement the panes in 
menu widgets. Gadgets were originally developed by Digital as a part of DECWindows, and 
were carried over into the version of Xt shipped with Motif 1.0. The MIT X Consortium 
Inu'insics support gadgets beginning in Release 4 (R4). As mentioned earlier, Motif 1.0 sup- 
plies its own version of the Intrinsics that is not compatible with the MIT X Consortium 
Inu'insics. However, Motif 1.1 adopts the standard R4 Intrinsics. As an example of a widget 
that manages gadgets, we will show the R4 Athena SimpleMenu widget and its gadget chil- 
dren. 
Also introduced in R4 is the object, which is another kind of windowless widget even simpler 
than a gadget. Objects are not usually used in menus, so we will reserve discussion of them 
until Chapter 13, Miscellaneous Toolkit Programming Techniques. 
In this chapter, we are using the term menu broadly, to refer to any user-interface element 
that lists many options and allows the user to select one or more. A menu might consist of a 
list of commands, only one of which can be selected at a time, a list of nonexclusive Boolean 
settings that can be turned on or off, or a list of exclusive choices (such as the colors or pat- 
terns for a paint palette). A menu that invokes commands will start in the same state each 

Menus, Gadgets, and Cascaded Pop Ups 357 



time, while the other two types may have different contents in any particular invocation, 
showing the settings invoked the previous time or all previous times, or a modified list of 
choices. 

Menus are one of the most important user-interface elements in window-based applications. 
They offer the same feature as Command buttons--a way for the user to invoke application 
functions or set parameters--but in a more organized and more easily accessible fashion 
when there are more than a few buttons. 

Figure 12-1 compares a menu to a box full of buttons. 

IVie,., Next I Vie. Previoos Delete 

MIN MENU 
Vie. Next 
Vie. Previous 
Delete 
Move 
Copg 
Unmark 
Vie. In 
Reply 
For.ord 
Use s Comp 

Figure 12-1. Command widgets in a button box, and the same commands as a menu 

The menu takes up less space because only its title is visible until it is called up.* As a result, 
you can have more menus than you could have permanent button boxes. Commands can be 
presented in smaller, more closely related groups. The user will spend less time searching for 
the desired command. 

The commands in the menu are also easier to read because they are arranged one per row. 
The commands in the menu may even be easier to invoke because it is more natural to drag 
the mouse up and down than from side to side. And last but not least, menus avoid the worst 
problem with button boxes: when the application is resized, button boxes may place each 
command widget in a different position, making it more difficult for the user to find com- 
mands.l 

*Under some widget sets and window managers, menus don't even display a tide--they simply pop up at the pointer 
position in response to a particular pointer button/keypress combination. This is the behavior of the menus provided 
by xterra and uwra. However, this is not very desirable behavior from a user-interface point of view, since it gives the 
user no visual feedback that a menu is available or how to invoke it. The user needs the manual--something graphi- 
cal user interfaces are designed to avoid. 
l'To be fail there is something to be said for the fact that all the available commands are always visible in an applica- 
tion that uses button boxes. You can invoke a button in a box with just a button click, while in a menu it requires a 
press, a drag, and a release. When there are only a small number of commands, putting the command widgets in a 
box is probably better than using a menu. 

358 X Toolkit Intrinsics Programming Manual 



In this chapter, though, we will focus on the two styles of menu you are most likely to 
encounter in X applications: the drop-down menu and the pure spring-loaded pop-up menu. 
The difference between spring-loaded and drop-down menus is primarily in the method by 
which the user invokes the menu and in where the menu is placed; one menu widget class can 
usually work in either style. 
The Xt specification makes the distinction between modeless pop ups, modal pop ups, and 
spring-loaded pop ups. 
Modeless pop ups are windows that, once popped up, are subject to window manager control, 
and for all intents and purposes act like regular applications in themselves. A help window 
that stayed up, and could be moved and resized like a regular window once popped up, is an 
example of this type of pop up. It is referred to as "modeless" because it doesn't put the 
application into a special mode, in which only input to the pop up is allowed. 
A modal pop up may or may not be visible to the window manager, but it always disables 
user-event processing by the application, except in the pop up itself. A dialog box that 
requires the user to enter data or click on a button is an example of a modal pop up. Input 
may still be possible to other applications. 
A spring-loaded pop up, as defined by Xt, is invisible to the window manager, and disables 
user input to all windows in all applications, except to the pop up itself. The most important 
thing about spring-loaded pop ups is that they are invoked with a key or pointer button press, 
whereas another type of pop up might be invoked as a routine part of application processing, 
or just because the pointer entered a particular window. 
However, due to a lack of appropriate terminology, throughout this chapter we use the term 
"spring-loaded pop up" to refer to menus that pop up at the pointer position when a mouse 
button is pressed, such as that used by xterrn, as opposed to drop-down or pull-down 
menus. 

12.1.1 

How Menus are Popped Up 

How you create menus in an application differs according to the class of menu widget and 
whether it will be drop-down or spring-loaded. Commercial widget sets are designed to 
make it quite easy to create menus that fit into their user-interface conventions. As usual, the 
examples in this chapter use the Athena widgets to implement various types of menus. 
Although the procedure for creating menus under the widget set you plan to use may be dif- 
ferent, many of the underlying issues are the same. 

In Section 3.3, a dialog pop up was created by first creating a pop-up shell, and then creating 
the widget to be popped up as a child of the pop-up shell. This procedure is used for some 
menu widgets, but most menu widgets are themselves subclasses of Shell, and therefore no 
separate shell needs to be created. You just create an instance of the menu widget itself, 
using XtVaCreatePopupShell instead of XtVaCreateManagedWidget. 

To have a spring-loaded pop up, your application usually adds an action that places the 
widget in the application main window. (Xt has a standard action for popping up a widget, 
but by default it places the widget at the top-left corner of the screen. As a result, you must 

360 X Too&# Intrinsics Programming Manual 



 mr'e 

New I 
Save  
Save As 

File I Edit 
New ....... ^N 
Open ...... ^O I 
Save ...... ^S 
Save As .... ^A 
Exit ....... ^E 
....... 
ii 

View Options Help (F1) 

Figure 12-2. Menus from the OPEN LOOK and Motif widget sets 

The Athena SimpleMenu widget has rectangular panes that display an identifying string, and 
an optional bitmap before and/or after the string. For example, the bitmap can be used to 
place a checkmark to the left of the label (indicating that an option has been selected and is 
in effect), or an arrow to the right, indicating that selecting this pane will produce a cascad- 
ing submenu. When an item is selected, it is displayed in inverse video. 
Motif menu panes are rectangular. The currently-selected pane is highlighted with a simu- 
lated 3-D shadow. Panes may contain either a string or a bitmap. 
OPEN LOOK menus come with several types of panes, depending on the type of menu item. 
Commands, whether available from menus, or in other control areas, are represented by 
oblong buttons with rounded ends. (Buttons that generate menus or submenus follow their 
label with an arrowhead pointing in the direction where the submenu will appear.) Exclusive 
options are shown as adjacent rectangles, with the one currently chosen highlighted by a dark 
border. Nonexclusive options are displayed in rectangles with a small separation between 
each one. Panes may contain a string or a bitmap, or both. 
However, what all menu widgets have in common is that the application programmer can set 
the label of each pane and the function it invokes. Exactly how to do this varies according to 
the widget set you use. 

362 X Toolkit Intrinsics Programming Manual 



See Appendix A, OPEN LOOK and Mottf, for more information on how Motif and OPEN 
LOOK implement menus. 

12.2 Several Ways to Create and Use Menus 

You already know how to create a pop-up shell, create a Box as its child, fill it with Com- 
mand widgets, label the Command widgets, and register a callback function for each one. By 
doing this you can create a basic menu. Its performance may be rather sluggish since it 
unnecessarily consumes resources, but it looks and works like a menu. 
This section describes how to use the menu made from a box full of buttons in two different 
menu styles: spring-loaded and drop-down. The purpose of this exercise is to expose some 
of the issues involved in event-management of pop ups. Some of these issues may be hidden 
in the widgets or facilities provided by some commercial widget sets, but seeing how to do 
the event management explicitly should help you to use pop ups more effectively. 
The challenge of creating a pop up with Box and Command buttons is to make it pop up and 
down at the right times, and to control its event handling to fit the menu style. We will also 
experiment with creating a cascaded menu, in which one menu pane in a main menu invokes 
a submenu. 
Finally, this section describes how to create a menu using the R4 Athena SimpleMenu widget 
and its gadget children. 

12.2.1 

A Spring-Loaded Menu: Pointer Grabbing 

A spring-loaded menu should pop up when a button press occurs in a particular widget; 
usually the application's main window. The menu should stay visible as long as the user 
holds down that button, and disappear when the button is released. If the button is released in 
a menu pane, the function registered for that pane should be invoked. If the button is 
released outside the menu, no function should be invoked but the menu should still be 
popped down. 
The only tricky part of implementing a spring-loaded menu is getting the menu to pop down 
when the button is released outside the menu. Since this occurs outside the menu and possi- 
bly outside the application, the X server will not send the button release event to the applica- 
tion unless a grab is in effect. Normally, user events are sent to the window that contains the 
pointer. But after an application makes a grab, the X server sends all events of particular 
types to the window that made the grab, even if the pointer is no longer in the window. 
The X server defines several types of grab: keyboard grabs, pointer grabs, and server grabs. 
Keyboard and pointer grabs control only input from the indicated device, while server grabs 
make the server act on requests from one application exclusively. (Server grabs are mainly 
used by window managers.) Pointer grabs are used for controlling events in pop ups when a 
pointer button pops up the pop up, and keyboard grabs are used when a key press pops up the 
pop up. We will discuss pointer grabs since keyboard grabs are analogous (and keyboard- 
triggered pop ups are less common). 

Menus, Gadgets, and Cascaded Pop Ups 363 



There are two types of pointer grabs: passive grabs and active grabs. An active grab is 
invoked directly with the Xt function XtGrabPo_nter. This function tells the server that 
you want the grab to begin right away and to continue until specifically released with Xt- 
UngrabPoS.nter. Active grabs are not normally used for pop ups.* 
A passive grab tells the server that you want a grab to begin when a certain key or button 
combination is pressed in a certain window (the combination that is to pop up the pop up). 
The grab continues until the button in the combination is released. This is perfect for menus 
because we need the grab only until the button is released. (Also, as you'll see in the section 
on drop-down menus, you can register several passive grabs for the same key-button combi- 
nation as long as each grab is initiated by a press in a different window. This technique lets 
you have as many drop-down menus as you want. Since spring-loaded pop ups are generally 
invoked by a press in the same window--the application main window--you will need to 
use a different key-button combination for each different menu.) 
Passive grabs of a key or button and active grabs of the pointer or the keyboard we will call 
global grabs, since they affect not only this application but prevent distribution of the 
grabbed events to other applications running on the same server. This terminology is to dis- 
tinguish the global grab from the effects of Xt's local grab mode, which simulates a global 
grab but requires no call to the server and affects only the distribution of events within the 
application. The Xt grab mode cannot commandeer events that occur outside the application 
like a global grab can. When an Xt grab is in effect, Xt redirects user events to the pop ups 
even if they occur somewhere else in the application. (Non-user events continue to be 
dispatched to widgets so that they can redraw themselves). 
The Xt grab mode can be either exclusive or nonexclusive. Exclusive and nonexclusive Xt 
grabs differ only when a pop up has popped up another pop up--a so-called cascaded pop 
up. An exclusive Xt grab redirects all user events that occur within the application to the 
latest pop up in the cascade. A nonexclusive Xt grab redirects events to whichever pop up 
the pointer is in, or the latest pop up if the pointer is outside all the pop ups (but still in the 
application). 
Here are examples of the two kinds of Xt grab modes. Consider an application that pops up a 
dialog box to get a filename from the user. The application wants to read the file. If the file 
can't be opened, the application pops up another dialog telling this to the user. This error pop 
up takes no input, so input is still desired in the filename entry pop up. This situation calls for 
a nonexclusive grab. By contrast, consider an application that uses the same filename entry 
pop up to save a file. If the file exists, it would pop up a dialog that would ask whether the 
existing file should be overwritten. This pop up must be answered before a new filename is 
chosen. This situation would call for an exclusive grab. In brief, an exclusive grab con- 
strains input to the the latest widget in the cascade, while a nonexclusive grab allows input to 
any widget in the cascade. We'll talk more about the Xtgrab mode in Section 12.2.3, when 
we talk about pop-up cascades. 

*One reason that XtGrabPointer is rarely used for pop ups is that it requires that the window that will receive 
the grabbed events be visible. This is often not the case. In a menu, for example, the window that you want to grab 
the events may be hidden by the menu panes even when the menu is popped up. Another reason is that you need to 
call X t Ungr abP o i nt e r to release the grab when finished. Passive grabs match the task better. 

364 X Toolkit Intrinsics Programming Manual 



MotionNotify. All other events (most notably Expose events) occur and are delivered 
normnlly.) 

With that background, let's take a look at an application that provides a spring-loaded menu. 
The xmenul application's permanent appearance is a variation of xbox; it displays a large 
Label widget that we are using to simulate an application's main window and a Command 
widget for quitting. Pressing any button in the Label widget calls up the menu, which oper- 
ates as described at the beginning of this section, xmenul is shown in Figure 12-3. As usual, 
we suggest you compile and run this example now. 

,, , 
[] II "-]1 l 
is a Pretend Main I,lindc 
-- 

MAIN MENU 

View Next 
Vlew Previous 
Delete 
Move 
Copy 
Unmark 
View In New 
Reply 
Forward 
Use As Comp 

Figure 12-3. xmenu 1: application with spring-loaded pop-up menu 

The relevant code in xmenul consists of an action routine to place the pop up, code to add the 
action, a callback routine to handle when a menu item has been chosen, and code to create 
the Box populated with Command widgets that will act as the menu. Example 12-1 shows 
the complete code. 

Example 12-1. xmenul: complete code 
/. 
* xmenul.c - simple spring-loaded menu 
./ 

#include <stdio. h> 

* 
* Standard Toolkit include files: 
./ 
#include <Xll/Intrinsic.h> 
#include <Xll/StringDefs.h> 
#include <Xll/Shell.h> 

* 
* Public include files for widgets used in this file. 
./ 

366 X Toolkit Intrinsics Programming Manual 



Examp 12-1. xmenul: comp code (continue 
#include <Xll/Xaw/Command.h> 
#include <Xll/Xaw/Box.h> 
#include <Xll/Xaw/Label.h> 
/* 
* The popup shell ID is global because both dialog and pshell 
* are needed in the dialogDone callback, and both can't be 
* passed in without creating a structure. 
*/ 
Widget pshell; 
/*ARGSUSED*/ 
void PlaceMenu(w, event) 
Widget w; 
XButtonEvent *event; 
{ 
/* should make sure coordinates allow menu to fit on screen */ 

/* move submenu shell to slightly left and above button 
* press position */ 
XtVaSetValues(pshell, 
XtNx, event->x root - i0, 
-- 
XtNy, event->y_root - i0, 
NULL); 
) 
/* 
* quit button callback function 
*/ 
/*ARGSUSED*/ 
void Quit(w, client data, call data) 
Widget w; 
XtPointer client_data, call_data; 
{ 
exit(0); 
) 
/* 
* menu pane button callback function 
*/ 
/*ARGSUSED*/ 
void PaneChoseniw, client_data, call_data) 
Widget w; 
XtPointer client_data; /* cast to pane_number */ 
XtPointer call data; 
{ 
int pane_number = (int) client_data; 
printf("Pane %d chosen.\n", pane_number) ; 
XtPopdown (pshell) ; 
) 
main(argc, argv) 
int argc; 
char **argv; 
{ 
XtAppContext app_context; 
Widget topLevel, box, quit, label, menulabel, menubox, menupane[10]; 
int i; 

Menus, Gadgets, and Cascaded Pop Ups 367 



Examp 12-1. xmenul: compte code ontinue 
String buf[50]; 
static XtActionsRec trial actions[] = { 
-- 
{"placeMenu", PlaceMenu), 
}; 
topLevel = XtVaAppInitialize( 
&app_context, /* Application context */ 
"XMenul", /* application class name */ 
NULL, 0, /* command line option list */ 
&argc, argv, /* command line args */ 
NULL, /* for missing app-defaults file */ 
NULL); /* terminate varargs list */ 

box = XtCreateManagedWidget( 

"box", 
boxWidgetClass, 
topLevel, 
NULL, 
0 
); 

/* widget name */ 
/* widget class */ 
/* parent widget*/ 
/* argument list*/ 
/* arglist size */ 

label = XtCreateManagedWidget( 

"label", 
labelWidgetClass, 
box, 
NULL, 
0 
); 

/* widget name */ 
/* widget class */ 
/* parent widget*/ 
/* argument list*/ 
/* arglist size */ 

quit = XtCreateManagedWidget( 
"quit", /* widget name */ 
commandWidgetClass, /* widget class */ 
box, /* parent widget*/ 
NULL, /* argument list*/ 
0 /* arglist size */ 
); 
pshell = XtCreatePopupShell( 
"pshell", 
transientShellWidgetClass, 
topLevel, 
NULL, 
0 
); 
menubox = XtCreateManagedWidget( 
"menubox", /* widget name */ 
boxWidgetClass, /* widget class */ 
pshell, /* parent widget*/ 
NULL, /* argument list*/ 
0 /* arglist size */ 
); 

menulabel = XtCreateManagedWidget( 
"menulabel", /* widget name */ 
labelWidgetClass, /* widget class */ 
menubox, /* parent widget*/ 
NULL, /* argument list*/ 

368 X Toolkit Intrinsics Programming Manual 



Example 12-1. xmenul: complete code (continued) 
0 /* arglist size */ 
); 
for (i = 0; i < i0; i++) { 
sprintf(buf, "menupane%d", i) ; 
menupane[i] = XtCreateManagedWidget (buf, /* widget name */ 
commandWidgetClass, menubox, NULL, 0); 
XtAddCallback(menupane[i], XtNcallback, PaneChosen, i) ; 
) 
XtAppAddActions(app_context, trial_actions, XtNumber(trial_actions)) ; 
XtAddCallback(quit, XtNcallback, Quit, 0) ; 
XtRealizeWidget (topLevel) ; 
XtAppMainLoop (app_context) ; 
) 
The PlacePopup action just places the pop up slightly to the left and above the position 
where the pointer button that popped it up was clicked, using the coordinates reported in the 
button event. The offset of ten pixels from the pointer position simply helps to make sure 
that the pointer is inside the menu.* Remember that the window created by a pop-up shell 
widget is a child of the root window and therefore is placed relative to the root window. The 
But t onP re s s event pointer coordinates relative to the root window are used. 
The PaneChosen callback function is a stub function used in this example as the notify 
callback for all the menu panes. In this example, it simply prints the name of the chosen pane 
to stdout and then pops down the menu using XtPopdown. In a real application, a different 
callback function would probably be registered for each pane. 
Instead of calling XtPopdown in each of these separate callback functions, you could write 
a single additional callback function that calls XtPopdown, and then add it to the callback 
list for the Command widget that makes up each menu pane. 
As usual, the pop up is created by first creating a pop-up shell, then a Box widget as its child, 
and then a series of Label and Command widgets as children of Box. The pop-up shell and 
the box are invisible. As with all menus, what you actually see is the array of children. 
Note that this prograth does not include any code that would pop up the menu. We've done 
that from the application-defaults file shown in Example 12-2. The translations we have 
defined for the Label widget invoke Xt's built-in XtMenuPopup action. 

Example 12-2. XMenul: eapplication-deusfile 
! Appearance Resources 
*quit.label: Quit 

*It is important to provide a consistent user interface, so you should use the same offset in all menus. Menus in com- 
mercial widget sets such as the OPEN LOOK widgets have carefully designed and documented policies about pop-up 
window placement. This allows the user's "pointer reflexes" to be trained, so that using menus becomes as automatic 
and easy as possible. 

Menus, Gadgets, and Cascaded Pop Ups 369 



popped up the menu occurred in the application main window). We are replacing their trans- 
lations to get rid of the translation for ButtonPress (which would still be present if we 
used the #auc!ment directive, and we would have to create an action that did nothing in 
order to replace it with #override). The translation for ButtonRelease (abbreviated 
BtnUp in the translation table) calls all the actions that usually occur in Command widgets 
with both press and release. 

Perhaps least obvious is the translation we have added to pop down the menu when the 
pointer button is released outside the menu. As mentioned earlier, Xt makes a passive global 
pointer grab on the pop-up shell (psheZ1) in the XtMenuPopup action. When the pointer 
is inside the menu, the Command widgets intercept these grabbed events, because they are 
descendants of pahell and they have a translation for ButtonReleaae events. This 
invokes the actions in the selected Command widget. But when the pointer is outside the 
menu, the grabbed events are sent directly to the widget that was specified in the grab call, 
namely pahe11. Therefore, the translation to pop down the menu on button release must be 
added to paheZZ. (Again, this translation table is simply replaced because the pop-up shell 
normally has no translations.) 

12.2.2 

A Drop-Down Menu 

What are the desired characteristics of a drop-down menu? There is a Command widget or 
the like permanently visible in the application, with a label indicating some common charac- 
teristic of the items in the menu. When a button is pressed in this widget, the menu should 
pop up on or just below the button. Dragging the pointer down through the menu with the 
buuon still held should highlight the entry that is pointed to. Releasing the button in an entry 
should invoke or set that entry and pop down the menu. Moving out of the menu should not 
change this behavior, except that if the button is released anywhere outside of a menu pane, 
the menu should pop down without executing any entry. 
If you compile and run xmenu2 you can try out this style of menu. The appearance of this 
application is shown in Figure 12-4. 
Invoking a menu as a drop-down is a simple enhancement of the spring-loaded invocation 
method just shown..We can do everything exactly the same as in the spring-loaded example, 
except that a drop-down menu should appear just below the presame widget, not at the 
pointer position. Therefore, all we need to change is the placement code. However, since the 
coordinates in the event are not necessary for placing the pop ups, we can use a callback 
function instead of an action to place the pop up. (In general, it is better to use an existing 
callback than to add an action to do the same thing.) 
Pop-up shell widgets have XtNpop upCallback and XtNpopdownCallback call- 
back resources; the functions on these callback lists are called whenever the pop up is 
popped up or down using any of the Xt mechanisms. 
In the last example we created an action called PlaceMenu, to move the pop-up shell 
before it was actually popped up. We included it in a translation along with the standard 
action XtMenuPopup, which was actually used to pop up the widgeL xmenu2 also uses the 
standard action XtMenuPopup to pop up the widget, but it uses the XtNpopup- 
Callback resource to provide the code to place the widget. Using the callback saves 

Menus, Gadgets, and Cascaded Pop Ups 371 



MAIN MENU 
View Next 
, 
IView Previous 

Delete 

Move 
Copy 
Unmark 
I 
View In New 
Reply 
Forward 
Use As Comp 

Figure 12-4. xmenu2: a drop-down menu 

having to reference the placement action in the translation table. This is preferable, since 
the placement code should almost always be hardcoded rather than user-configurable. 
Another advantage of the pop-up and pop-down callbacks is that you may arrange for a pop 
up to be popped up or down in more than one way, and it may be convenient to have certain 
code called automatically in all cases. 
(You can also use the XtNpopupCallback resource to specify a callback function to cre- 
ate a pop-up widget the first time it is popped up, instead of at application startup. The one 
problem is that the functions on the callback list are invoked every time the widget is popped 
up. To make sure that your function callback creates the pop up only once (the first time), the 
callback function should remove itself from the callback list by calling XtRemove- 
Callback.) 
There is not enough difference between xmenul and xmenu2 to merit showing the complete 
code. All we have done is changed the PlaceMenu function from an action into a callback 
and changed its placement logic to place the pop-up relative to the invoking Command 
widget. We have then modified the application-defaults file accordingly. 
Example 12-3 shows the PlaceMenu routine (now a callback, not an action) and the code 
to register it as a callback. 

Example 12-3. xmenu2: code to place drop-down menu 

/*ARGSUSED*/ 
void PlaceMenu(w, client data, call data) 
-- _ 
Widget w; 
XtPointer client data; 
-- 
XtPointer call data; 
-- 
{ 
Position x, y; 

372 X Toolkit Intrinsics Programming Manual 



Example 12-4 shows the translation portion of the application-defaults file. 

Example 12-4. XMenu2: translation portion of the application-defaults file 
' Translation resources 
*pressme. translations : \ 
<EnterWindow> : highlight ( ) \n\ 
<LeaveWindow> : reset ( ) \n\ 
<BtnDown>: set() XtMenuPopup(pshell) reset() 
, 
*pshell. translations : \ 
<BtnUp> : XtMenuPopdown (pshell) 
*menubox. Command.translations : \ 
<EnterWindow> : set () \n\ 
<LeaveWindow> : unset ( ) \n\ 
<BtnUp>: notify() unset() 
These translations are different from those for xmenuf only in that pressme is a Command 
widget, which already has its own translation table, rather than a widget without existing 
translations such as Label (which we used as a fake main window). We have modified the 
translations of pressme to be suitable for this use. Note that the translation no longer calls 
PlaceMenu as an action because it is now a callback. 
The translations for the menu pane Command widgets are also somewhat different from 
xmenul, but only for cosmetic reasons. This iteration of the xmenu example uses the set 
and unset actions instead of highlight and reset or unhighlight to make the 
Command widgets highlight their entire box instead of just an area near the border. 
(Although this modification makes the menu look more like a typical menu, it also seems to 
make it slower.) 
To create several menus you simply need to replicate the code shown here, changing the vari- 
able names for each menu. The passive global grabs invoked by Xt for each menu do not 
interfere with each other even if they specify the same key/button combination, because they 
specify different windows in which the key/button combination will begin the grab. 
It is sometimes useful to be able to get a list of children in a menu, especially if you add and 
subtract menu entries. You can do this by querying the XtNchildren and XtNnumChildren 
resources of the parent. The value of XtNchildren is a list of the widget ID's of the children. 
This technique allows you to eliminate maintaining global variables for every pane of every 
menu. 

12.2.3 

Cascaded Menus 

A cascaded menu is a menu in which one or more panes do not invoke functions but instead 
bring up additional menus. 

The techniques used to bring up cascaded menus can also be used to have dialog boxes bring 
up other dialog boxes. However, cascaded menus are more challenging because they rely on 

374 X Toolkit Intrinsics Programming Manual 



the passive global pointer grab to receive the ButtonRelease event that occurs outside 
the menu and application. 
You can implement a cascaded menu the same way for both spring-loaded and drop-down 
menus, simply by adding to the code we've already written to implement a single menu. 
We'll show you xmenu5, the spring-loaded version, since it is slightly shorter. (xmenu4 is the 
equivalent drop-down version.) Both are included in the example source code. In this 
example, only one menu pane will be used to invoke a submenu. However, this technique 
can be generalized to have additional panes bring up additional submenus. 
First, let's describe exactly how we expect the cascaded menu to work. Figure 12-5 shows 
both menus popped up. (Compile the program and try it.) 

MglN MENU 
View Next 
View Previous 
Delete 
Move 
Unmark 
Cop Io ==> 
View In New 
Repl 
Forward 
Use gs Comp 

SUB MENU 
Knews folder 
Xt folder 
(lib folder 
Xconsortium f 
Xaw folder 
Drafts folder 
Misc folder 
Personal fold 
Xprotocol fol 
Io Do List 

i 
'Figure 12-5. xmenu5: cascaded spring-loaded menus 

The main menu works as described above. However, one of the panes--the one that brings 
up the submenu--has an arrow pointing to the right after its label. This pane does not high- 
light itself when the pointer moves inside (telling the user that this pane is different). 
Instead, when the user moves the pointer out through the right edge of the pane, the submenu 
pops up. The submenu operates just like the main menu. When the button is released inside 
either menu, the callback function associated with the chosen pane will be invoked. When 
the button is released outside of either menu, both menus pop down. If the pointer is moved 
back out of the submenu into the main menu, only the submenu pops down. 

Menus, Gadgets, and Cascaded Pop Ups 375 



To create the submenu, we create a new pop-up shell, Box widget, and a set of Command 
widgets, and add callbacks for each function the submenu panes will invoke (in this example, 
one common callback). Then we write three actions: P]_aceMenu (which you have already 
seen), CheckRightAndPopupSubmenu (which places and pops up the submenu if the 
pointer leaves the main menu pane through its right side), and PopdownSubmenu (which 
pops down the submenu if the pointer leaves the submenu). These actions are shown in 
Example 12-5. 

Examp 12-5. xmenu5: actions at pce, pop up, and pop down ma menus and sub- 
menus 
/*ARGSUSED*/ 
void PlaceMenu(w, event, params, num_params) 
Widget w; 
XEvent *event; 
String *params; 
Cardinal *num_params; 
XButtonEvent *bevent = (XButtonEvent *) event; 
/* should make sure coordinates allow menu to fit on screen */ 
/* move submenu shell to slightly left and above button 
* press position */ 
XtVaSetValues(pshell, 
XtNx, bevent->x root - I0, 
-- 
XtNy, bevent->y_root - I0, 
NULL); 
/*ARGSUSED*/ 
void CheckRightAndPopupSubmenu(w, event, params, num_params) 
Widget w; 
XEvent *event; 
String *params; 
Cardinal *num_params; 
! 
XLeaveWindowEvent *leave event = (XLeaveWindowEvent *) event; 
-- 
Dimension height, width; 
XtVaGetValues(w, 
XtNheight, &height, 
XtNwidth, &width, 
NULL); 
if ((leave_event->x > width) && (leave_event->y > 0) 
&& (leave_event->y < height)) 
/* move submenu shell to start just right of pane, 
* using an arbitrary offset to place pointer in 
* first item. */ 
XtVaSetValues(subshell, 
XtNx, leave_event->x_root, 
XtNy, leave_event->y_root - 12, 
NULL); 
XtPopup(subshell, XtGrabNonexclusive); 

/*ARGSUSED*/ 

376 X Toolkit Intrinsics Programming Manual 



As an additional enhancement, the menu marks or unmarks each item when it is selected in 
addition to calling a callback function. This iteration marks entries with the X logo, which is 
available as a standard bitmap in lusrlincludelX111bitmaps (on UNIX systems). 

Figure 12-6 shows the appearance of the program. 

Click here for menu 

uit 
ow Scrollbar 
Enable Reverse Video 
Enable Bell 

Repb' 
Forward 
Print 

Figure 12-6. xmenu7: a menu using the Athena SimpleMenu widget 

Example 12-7. xmenu7: using the SimpleMenu widget and its children 
/* 
* xmenu7, c 
*/ 
#include <stdio. h> 
#include <Xll/Intrinsic. h> 
#include <Xl I/StringDefs. h> 
#include <Xl 1/bitmaps/xlogol 6> 
#include <Xll/Xaw/MenuButton.h> 
#include <Xll/Xaw/SimpleMenu.h> 
#include <Xl I/Xaw/SmeBSB. h> 
#include <Xll/Xaw/SmeLine. h> 
#define NUM MENU ITEMS 12 
-- _ 
static String menu_entry_names[] = { 
"quit", 
"iteml", 
"item2", 
"item3", 
"i ine", 
"item5", 
"it em6", 
"item7", 
"blank", 
"menu I", 
"menu2", 

380 X Too&# Intrinsics Programming Manual 



Example 12-7. xmenuT: using the SimpleMenu widget and its children (continued) 

"menu 3", 
}; 
static Boolean status[NUM MENU ITEMS]; 
-- _ 
static Pixmap mark; 
/* ARGSUSED */ 
static void 
MenuSelect(w, client data, garbage) 
-- 
Widget w; 
XtPointer client data; 
-- 
XtPointer garbage; /* call data */ 
-- 
int pane_hum = (int) client_data; 
printf("Menu item %s has been selected.\n", XtName(w)); 
if (pane_num == 0) /* quit selected. */ 
exit(0); 

if (status[pane_hum]) 
XtVaSetValues(w, 
XtNleftBitmap, None, 
NULL); 
else 
XtVaSetValues(w, 
XtNleftBitmap, mark, 
NULL); 
statuslpane_num] = !status[pane_num]; 
} 
void 
main(argc, argv) 
char **argv; 
int argc; 
XtAppContext app_context; 
Widget topLevel, menu, button, entry; 
int i; 
Arg arglist[l]; 
topLevel = tVappInitialize( 

&app_context, 
"XMenu 7", 
NULL, 0, 
&argc, argv, 
NULL, 
NULL); 

/* Application context */ 
/* Application class */ 
/* command line option list */ 
/* command line args */ 
/* for missing app-defaults file */ 
/* terminate varargs list */ 

button = XtCreateManagedWidget("menuButton", 
menuButtonWidgetClass, topLevel, 
arglist, (Cardinal) 0); 

menu = XtCreatePopupShell("menu", simpleMenuWidgetClass, 
button, NULL, 0); 

for (i = 0; i < NUM MENU ITEMS ; i++) { 
-- _ 
String item = menu_entry_names[i]; 

Menus, Gadgets, and Cascaded Pop Ups 381 



If your goal is to create only the required pop ups, you can create the pop up in a callback 
function or action routine that you have registered to place or pop up the pop up. In this case, 
you would have a static variable in the callback or action to make sure that the pop-up wid- 
gets are only created the first time the pop up is popped up. You need to have created the 
pop-up shell before this can work. 

There is also another way to create only the required pop ups. Shell widgets have an Xt- 
NcreatePopupChildProc resource which you can set to a function that creates the 
Shell's children. See XtCreatePopupChildProc(2) in Volume Five, X Toolkit 
Intrinsics Reference Manual, for the calling sequence of this function type. The Xt specifica- 
tion does not say whether an XtCreatePopupChildProc is called just once when the 
shell is first popped up or every time it is popped up. But the MIT implementation of Xt calls 
it every time the shell is popped up, so you will again need a static variable to make sure the 
children are only created once. 

12.3 About Dialog Boxes 

Although we have been talking so far exclusively about menus, much that has been said is 
also true of dialog boxes. Both menus and dialog boxes that get user input usually need to 
get that input before other application functions can be invoked. Of course, one way to dis- 
able all other application functions is to make all other widgets insensitive with xtSet- 
Sensitive (passing it FALSE). Setting the sensitivity of one common ancestor does this 
efficiently, but even this is too slow because all the widgets redraw themselves dimmed or 
grayed. It is much faster to use a global grab. Unlike menus, which require the global grab 
in order to get button release events outside the application so they can pop down properly, 
dialog boxes do not, strictly speaking, need a grab. But they sometimes make the grab any- 
way to disable other application functions. 
Dialog boxes can also invoke other dialog boxes. For example, a dialog box that gets input 
might check the validity of the input before popping down the dialog, and if incorrect, pop up 
a message telling the user the problem with the input. Cascaded dialog boxes are imple- 
mented the same way as cascaded menus. Note that, as a general rule, sub-dialog boxes are 
popped up with grab mode XtGrabExclusive, which means that the user must satisfy 
the most deeply nested dialog first. 
Some pop ups do not need to disable other application functions. For example, imagine a 
dialog box that informed the user of some fact without requiring confirmation. This kind of 
pop up would be popped up with grab mode XtGrabNone, allowing the user to continue 
with other application functions. 
We pointed out earlier that the built-in callback functions for popping up a widget are not 
useful for menus because they make no passive global pointer grab. However, they come in 
handy for dialog boxes. The functions XtCallbackNone, XtCallbackExclusive, 
and XtCallbackNonexclusive can be used to pop up dialog boxes, as long as the 
position of the dialog box need not depend on information in an event. 

384 X Toolkit Intrinsics Programming Manual 



We haven't shown how to use Xt's standard callback for popping down a widget: 
Cal "lbackPopdown. Instead of calling XtPopdown in the callback functions for each 
menu entry, we can add xtCal 1 backPopdown to the callback list after the existing call- 
back function, xtCall backPopdown requires an XtPopdownld structure to be passed 
as the client data argument This structure must contain the pop-up shell and the 
-- 
widget that invoked the pop up (the MenuButton or Command widgeO. 
All three of the standard pop-up callbacks set the invoking widget to insensitive mode before 
popping up the widget XtCallbackPopdown resets the invoking widget to sensitive 
mode. Therefore, if you use XtCallbackNone, XtCallbackNonexclusive, or 
XtCallbackExclusive without also using XtCallbackPopdown, remember to set 
the widget to sensitive mode yourself. This feature is useless but also harmless when the pop 
up is spring-loaded, because the invoking widget is often the main application window and 
that widget rarely responds to sensitivity. 
In certain rare cases, you may want to use XtAddGrab and XtRemoveGrab directly to 
append a widget to or remove a widget from the current pop-up cascade. These functions are 
called internally by the Xt facilities that pop widgets up and down, and should not be neces- 
sary on their own. Note that these functions never make a request to the server to start or 
release a passive global pointer grab--they affect only Xt's internal event dispatching. 
(However, the functions XtGrabKey, XtGrabKeyboard, XtGrabButton, and Xt- 
GrabPointer do initiate global grabs. These functions are described in Chapter 13, Mis- 
cellaneous Toolkit Programming Techniques.) 

12.4 Gadgets 

When an application includes many different menus with many fields each, the overhead of 
having separate widgets for every menu pane becomes significant. Because each widget 
requires structures on the client side and windows on the server side, every widget increases 
the executable size and server memory usage and increases the traffic over the network. It is 
always a good idea to minimize the number of widgets used in your application. 
Writing a single widget that implements an entire menu, including all its panes, solves this 
problem. The widget c.ould, define subresources for configuring each pane. (The callback list 
would be one of these subresources. XtCallCallbacks could not be used to invoke 
these callbacks because it cannot distinguish between subparts. However, the callbacks can 
be called directly by looping through the callback list. This is awkward, but not too diffi- 
cult.) This widget would not lack flexibility if the subparts are implemented as completely 
separate code  that the types of menu panes are extensible. However, gadgets turn out to be 
an easier and more elegant solution to the problem. 
As of Release 4, Xt provides gadgets, which are simplified widgets that do not create win- 
dows.* Gadgets require less memory than widgets on the client side (and less disk space for 
the executable file) and consume none at all on the server side. Gadgets can be used for the 
*The OSF Motif 1.0 Intrinsics support a different implementation of gadgets than those described here. Motif 1.l, 
however, uses the R4 standard Intrinsics, which includes the gadget implementation described here. 

Menus, Gadgets, and Cascaded Pop Ups 385 



panes of a menu, solving all of the problems just discussed. A gadget is fully configurable 
using the resource database just like a widget, and can have its own callback list. 
However, the reduced consumption of gadgets does have a price. Gadgets have to draw on 
their parent's window, and they share this space with the parent and with all other gadget 
children. The gadgets and the parent must agree to draw in certain areas only. For this rea- 
son, gadgets must be used with a special composite widget parent that is prepared to manage 
them properly. 
The Release 4 SimpleMenu widget is such a parent. It is a composite widget designed to 
manage gadget children. The gadgets provided by Release 4 are Sme, SmeBSB, and Sme- 
Line (where Sme stands for Simple Menu Entry). These provide a blank entry (and generic 
menu entry superclass), an entry which can contain a bitmap, a string, and another bitmap 
(thus BSB), and an entry that draws a horizontal line. We will use and describe this widget 
and these gadgets both to show how menu widgets are built and to demonslrate how the par- 
ent and the gadgets work together. 
Gadgets do not handle events automatically as widgets do, and because they have no win- 
dows, the server does not handle overlapping between them. This places certain demands on 
the parent. All the gadgets that are children of a particular parent share that parent's window. 
The parent is responsible for coordinating the gadget children, telling them about events by 
calling their functions. Therefore, the composite widget that manages a group of gadgets 
must be specially designed for that purpose, not a general-purpose composite or constraint 
widget such as Box or Form. It is possible for a composite widget to manage both gadget and 
widget children, but its code has to be more involved to do this. 
Like normal widgets, gadgets provide their own code to redraw themselves in their expose 
method. However, since gadgets do not receive events, they depend on the parent to directly 
call their expose method. The parent keeps track of the geometry of each child, and when 
the parent's expose method is called, this method calculates whether the area exposed 
overlaps any of the gadget children. If the area exposed does overlap a gadget, the parent's 
expose method calls that gadget's expose method, which redraws the area. 
A gadget's actions also have to work differently from widget actions because of the fact that 
gadgets don't get events. A gadget defines its actions as methods--as fields in its class part 
structure--instead of in an action list and translation table. It initializes these fields directly 
to pointers to functions during class initialization. The parent widget has corresponding 
actions that are defined and operate like normal actions, except that they determine which 
gadget the event that invoked the action occurred in and call the gadget method correspond- 
ing to that action. In other words, the parent has actions that operate the gadget children. 
One weakness of a menu composed of gadget panes is that gadgets cannot have an accelera- 
tor table. Therefore, accelerators cannot be used to provide a keyboard equivalent that would 
invoke each menu pane. 
The parent of gadgets has to position the gadget children so that they do not overlap, or take 
care of the consequences if they do overlap. Since the gadgets draw on the parent's window, 
if they did overlap they would draw over each other's graphics, with unpredictable results. 
The parent would have to calculate the area of overlap between two gadgets, and clear this 
area before letting one of the gadgets draw itself. (A gadget could clear its own area before 
drawing, but this would be unnecessary in many cases, and would cause flashing.) 

386 X Toolkit Intrinsics Programming Manual 



is the widget_class field of the Object instance pan.* In this example, the entry 
counter variable is a pointer to the gadget ID (opaque pointer to the instance structure) of one 
of the children. Another variable, class, declared as a pointer to the SmeObjectClass 
class structure (the expected class of the children), is set to the widget_class field in the 
instance structure of one of the children. Then the expose field of this class structure is 
checked to see if it is NULL, and if not it is invoked. 
Note that the class of the children is hardcoded in this method. This widget can manage only 
Sme widgets and its subclasses. 
The resize method of SimpleMenu must resize the children when it is resized itself. 
(Actually, this is unlikely, since the SimpleMenu widget itself is a subclass of Shell and is 
therefore not managed by any parent.) This method is invoked only when the user resizes the 
menu using the window manager. Since this widget has the authority to determine the geom- 
etry of its children, it can simply resize them. This panicular resize method (shown in 
Example 12-12) simply sets their width to be the same as its own. 

Examp 12-1 SimpMenu: se meod 
static void 
Resize(w) 
Widget w; 
{ 
SimpleMenuWidget smw = (SimpleMenuWidget) w; 
SmeObject * entry; 

if ( !XtlsRealized(w) ) return; 

ForAllChildren(smw, entry) /* reset width of all entries. */ 
if (XtlsManaged( (Widget) *entry)) 
(*entry)->rectangle.width = smw->core.width; 

Redisplay(w, (XEvent *) NULL, (Region) NULL); 
Notice that this resize method invokes the expose method (Redisplay) because the 
gadgets don't have resize methods, and will not redraw themselves in response to their 
size change.t 
Now let's look at SimpleMenu's actions. Their only purpose is to call the gadgets' actions 
when the appropriate events arrive. These actions are added in the usual way: they are 
declared at the top of the .c file, then registered with an action list that is entered into the 
class structure initialization, and then defined. One of the three actions is shown in Example 
12-13. 

*The Core instance part structure (not complete) is the concatenation of the instance parts of the three superclasses 
Object, RectObj, and the unnamed class. Therefore, it also includes a w i dge t_c 1 a s s field. Since composite wid- 
gets do not normally need to invoke the methods of their children, you shouldn't need to access this field. 
#The gadget children could have resi ze methods, and this resize method could call the children's resi ze meth- 
ods. The gadget's resi ze methods would simply call their expose method. However, this does exactly the same 
thing as the code shown while being more complicated. 

Menus, Gadgets, and Cascaded Pop Ups 393 



Example 12-13. SimpleMenu: the Notify action routine 
/* ARGSUSED */ 
static void 
Notify(w, event, params, num_params) 
Widget w; 
XEvent * event; 
String * params; 
Cardinal * num_params; 
( 
SimpleMenuWidget smw = (SimpleMenuWidget) w; 
SmeObject entry = smw->simple_menu.entry_set; 
SmeOb jectClass class; 
if ( (entry == NULL) I I !XtIsSensitive((Widget) entry) ) 
return; 
class = (SmeObjectClass) entry->object.widget_class; 
(class->sme class.notify)( (Widget) entry ); 
-- 
) 
This action determines whether the chosen entry is sensitive and, if so, calls the notify 
method of that gadget. As described above in the section on the gadget children, gadgets 
define their actions as methods so that they can conveniently be called by their parent. Since 
these methods are stored in the class structure not the instance structure, this is done using 
the technique described above for the expose method. 
Although not critical to its handling of gadgets, SimpleMenu does one more interesting thing. 
It registers the PositionMenuAction action in the global application action list (as 
opposed to the internal widget action list) so that the application or application-defaults file 
can refer to this action in translation tables without needing to register the action. This action 
can be triggered by any type of event in the widget and positions the menu according to data 
in the event type. (SimpleMenu has a resource that controls whether this placement process 
makes sure that the menu is not off the screen.) 
A widget can add an action to the global action list by calling XtAddAction just like an 
application would, but from its class initialize method. 
Any composite widget that is capable of managing gadgets must declare a Composite exten- 
sion structure in the .c file and set the accepts_objects field of that structure to True. 
It must then set the pointer to the extension structure into the Composite class pan structure 
in the class_part_initialize method. Extension structures were introduced in 
Chapter 5, Inside a Widget, and are discussed further in Chapter 13, Miscellaneous Toolkit 
Programming Techniques. Example 12-14 shows this code from SimpleMenu.c. 

Example 12-14. SimpleMenu.c: Setting accepts_objects in the Composite extension structure 

CompositeClassExtensionRec extension rec = { 
-- 
/* next extension */ NULL, 
-- 
/* record_type */ NULLQUARK, 
/* version */ XtCompositeExtensionVersion, 
/* record size */ sizeof(CompositeClassExtensionRec), 
-- 
/* accepts_objects */ TRUE, 
); 

static void 

394 X Toolkit Intrinsics Programming Manual 



Examp 12-14. SimpMenu.c:Seing accepts_objec  He Compos#eexnsbn structure 
ontinue 
ClassPartInitialize(wc) 
WidgetClass wc; 
{ 
SimpleMenuWidgetClass smwc = (SimpleMenuWidgetClass) wc; 
/* 
* Make sure that our subclass gets the extension rec too. 
*/ 
extension_rec.next_extension = smwc->composite_class.extension; 
smwc->composite_class.extension = (XtPointer) &extension_rec; 
) 
This code, wi names changed, will appe in 1 gadget pen. 

Menus, Gadgets, and Cascaded Pop Ups 395 



13 

Miscellaneous Toolkit 
Programming Techniques 

This chapter describes various Xt functions that have not been treated else- 
where in the book. 

In This Chapter: 

Errors and Warnings .......................................................................... 399 
Objects .............................................................................................. 402 
Macros For Getting Information .......................................................... 403 
The Keyboard Focus and accept_focus Method ................................. 404 
Keyboard Interpretation ........................... . ......................................... 406 
Memory Allocation ............................................................................. 408 
Action Hooks and Calling Actions Directly .......................................... 408 
Xt Grabbing Functions ....................................................................... 409 
File Finding and Internationalization ................................................... 409 
Application Contexts .......................................................................... 410 
Multiple Api)licaion Contexts ......................................................... 411 
Rewriting XtAppMainLoop for Multiple Application Contexts ........... 412 
Functions Used with Multiple Application Contexts ......................... 412 
Multiple Top-level Shells .................................................................... 413 
Connecting to Multiple Servers .......................................................... 413 
Class Extension Structures ................................................................ 414 



13 
Miscellaneous Toolkit 
Programming Techniques 

This chapter discusses various Xt facilities that didn't fit neatly into any other chapter. Many 
of them are functions provided mostly because Xt uses them internally, and they are unlikely 
to be useful in application or widget code. Some of them are quite important for accomplish- 
ing certain tasks. You should scan the contents of this chapter to familiarize yourself with 
these facilities so that you will be aware of them. 

The topics covered are errors and warning messages, objects, a description of all of Xt's mac- 
ros and functions for getting information, the Core accept_focus method, how to inter- 
pret key events, Xt's facilities for memory management, making global grabs, file finding 
and internationalization, multiple application contexts, multiple top-level shells, and con- 
necting to multiple servers. 

13.1 

Errors and Warnings 

There are several broad categories of errors that may occur in Xt applications. One is the X 
server error, which is a form of event that tells the client that some parameter in an earlier 
request was illegal, or that no more server memory is available. A second is the connection 
failure error generated by Xlib when the connection with the server fails (usually due to a 
system crash or netvork interruption). Xlib provides the XSetErrorHandler and 
XSetlOErrorHandler functions to allow the application to provide a routine to handle 
these two types of errors. Xt provides no interface to these routines--Toolkit applications 
must use the Xlib routines to customize these error handlers (Xlib uses default error handlers 
when the application does not use these routines to specify them). For a description of these 
error handlers and the routines for changing them, see Volume One, Xlib Programming 
Manual. 

A third category is made up of error and warning messages that Xt reports when function 
parameters are specified improperly, when a translation is incorrectly specified, and for many 
other reasons. For a complete listing of all errors and warnings that can be generated by Xt, 
see Volume Five, X Toolkit lntrinsics Reference Manual, Appendix D, Standard Errors and 
Warnings. Xt provides separate parallel routines for errors and for warnings. The difference 
between Xt errors and Xt warnings is that errors are fatal and the application exits after print- 

Miscellaneous Toolkit Programming Techniques 399 



ing the error, while warnings are nonfatal and the application continues. The main purpose 
of these facilities is to generate consistent messages. 

Two levels of interface are provided: 

A high-level interface that takes an error name and class and looks the error up in an error 
resource database. The high-level fatal error handler is invoked by a call to XtApp- 
grrorMsg; the high-level nonfatal error handler is invoked by a call to XtApp- 
WarningMsg. The high-level functions construct a string and pass it to the lower-level 
interface. 

A low-level interface that takes a simple string, which is printed out as the error message. 
The low-level fatal error handler is invoked by a call to XtAppgrror; the low-level 
nonfatal error handler is invoked by a call to XtAppWarning. 

These error-reporting interfaces are used internally by Xt, but widget or application code can 
also use them. For example, when a resource is given an illegal value in a resource file, the 
widget or application can report the error or warning to the user (which depends on whether 
the widget or application can continue after the error--most widgets issue only warnings and 
then fall back on their default value). 
The low-level handlers are much easier to use, but they do not support internationalization 
(alternate languages) at all since the messages are hardcoded in the application. The high- 
level handlers can potentially support internationalization, but not as elegantly as the normal 
resource database since Xt searches for the error database file in a fixed location, not using 
the language string. If you want your application or widget to run in more than one language, 
you should use the high-level handlers, but only one database for one language can be 
installed on a system at a time. This is likely to be improved in later releases of Xt. 
To use the low-level handlers, you specify the string message as the sole argument to Xt- 
AppError or XtAppWarning. 
Contrary to what you might expect, the high-level handlers XtAppErrorMsg and Xt- 
AppWa rningMsg are actually harder to use than the low-level handlers. You must pass six 
arguments to the calls that generate the errors or warnings, and then to take advantage of 
their benefits you must set up an error resource database. The first three arguments are the 
name, type, and class of the error. The use of these three arguments is not yet standardized 
since they are not widely used. However, in Xt itself, the name identifies the error message, 
and the type identifies the task that was in progress when the error occurred (or the section of 
code). The class, within Xt, is always XtToolkitError. The three remaining arguments 
of XtAppErrorMsg and XtAppWarningMsg are a default message, a parameter list, 
and the number of parameters. The default message will be printed only if no matching mes- 
sage is found in the database. Because Xt does not define or install any error database, it uses 
these default messages only, and ignores the name, type, and class information. (Xt uses the 
high-level handlers so that an error resource file can be installed to print all the errors in a 
foreign language.) The parameter list is used together with the message in the database. The 
message may be in standard printf format, and the parameters are used to fill in any variable 
fields. 

400 X Toolkit Intrinsics Programming Manual 



Example 13-1 shows one of the rare cases where XtAppErrorMsg is invoked in the 
Athena widgets. 

Example 13-1. How to invoke XtAppErrorMsg (from AsciiSrc.c) 

if (src->ascii_src.string == NULL) 
XtAppErrorMsg(XtWidgetToApplicationContext(src), 
"NoFile", "asciiSourceCreate", "XawError", 
"Creating a read only disk widget and no file \ 
specified.", NULL, 0); 

The error resource database is stored in a file, lusrlliblX111XtErrorDB, under most UNIX- 
based operating systems. Since this database is made up of one file, you must append the 
resource settings you need to this file rather than replacing it. The resource name searched 
for in the database is the concatenation of the name and type arguments specified in the 
calls to XtAppE r re rMsg or XtAppWa rni ngMsg. 
You can redefine the routine that prints the message in order to change the fixed part of the 
message or to add features like logging of errors and warnings. Use XtAppSetError- 
MsgHandler and XtAppSetWarningMsgHandler (if you are using the high-level 
handlers) or XtAppSetErrorHandler and XtAppSetWarningHandler (if you are 
using the low-level handlers). See the reference pages for XtErrorMsgHandler(2) and 
XtErrorHandler(2) in Volume Five, X Toolkit Intrinsics Reference Manual, for a 
description of how to define a new error or warning handler. The default error and warning 
messages printed are: 
X Toolkit Error : message. (for errors) 
X Toolkit Warning: message. (for warnings) 
Remember that Xt itself uses these messages (not just your widget code), so that they must 
remain appropriate when called from anywhere in the Xt, widget, or application code. If you 
want the message to identify the name of the widget set or widget, you must include this 
information in the pan of the message filled in from the string you pass or from the resource 
database. 
Table 13-1 summarizes Xt's calls for issuing errors and warnings and for modifying the mes- 
sages issued. 

Table 13-1. Xt Error and Warning Message Utilities 

Message 

Issue Error 
Issue Warning 
Set Error Handler 
Set Warning Handler 

Low Level 

XtAppError 
XtAppWarning 
XtAppSetErrorHandler 
XtAppSetWarningHandler 

High Level 

XtAppErrorMsg 
XtAppWarningMsg 
XtAppSetErrorMsgHandler 
XtAppSetWarningMsgHandler 

Miscellaneous Toolkit Programming Techniques 401 



XtIsWMShell, XtIsVendorShell, XtIsTransientShell, XtIsTopLevel- 
Shell, and XtI sApplicationShell. 
You have already seen xt I sManaged used in composite widgets. See Chapter l l, Geom- 
etry Management. 
You have also already seen xt I sReali zeal used in various methods to make sure a widget 
has a window before operations are attempted on the window. For example, the expose 
method calls xt I sRealized before drawing into the window. 
xtIsSensitive checks the value of the XtNsensitive resource for a widget and its 
ancestors. If any of them is FALSE, it returns FALSE. Remember that sensitivity controls 
whether a widget responds to user events. 
XtHasCallbacks lets you tell whether a widget class has a callback of a certain resource 
name, and whether any callback functions have actually been added to it. It returns the 
enum value XtCallbackNoList if there is no callback list, XtCallbackHasNone if 
there is a callback list with no functions on it, and XtCallbackHasSome if there is a call- 
back list containing functions pointers. 
XtNameToWidget searches a hierarchy for the widget ID of the specified widget instance 
name. Its primary use from the application is to get the IDs of the child widgets of a com- 
pound widget such as Dialog, so that their resources can be set directly. This is a violation of 
the rules of data hiding, however, and is not recommended. In widget code, XtName- 
ToWidget is used to provide a layer of absaction so that widgets can be identified using 
string names. For example, it is used by the converter defined by Form that allows widget 
names to be specified in resource files. The opposite function, which returns a widget 
instance name given the widget ID, is XtName (which perhaps should have been called "Xt- 
WidgetToName"). 
XtWindowToWidget gives you the Widget which corresponds to the specified X win- 
dow ID. This is used mainly by Xt, but you may find a use for it. 
XtDisplayOfObject, XtScreenOfObject, and XtWindowOfObject search the 
parental hierarchy of an object to discover the closest windowed ancestor and then return a 
pointer to a Display structure, a pointer to a Screen structure, or a Window ID. These 
macros are useful for making Xlib calls from within code that implements a subclass of 
Object. 
XtGetApplicationNameAndClass returns the name and class strings of an applica- 
tion. The name is usually a rgv [ 0 ] stripped of any directories, while the class is the string 
passed as the second argument of XtAppInitialize. These are the name and class used 
by Xt to look up resources for the application and its widgets. You are unlikely to need this 
function. 

404 X Too/k# Intrinsics Programming Manual 



13.4 The Keyboard Focus and accept_focus Method 

The keyboard focus is the window to which the server sends keyboard events. The window 
manager controls which window this is. Under click-to-type window managers, the window 
that was most recently clicked on (usually with some keyboard key held) receives the key- 
board focus. Under a real-estate-driven or pointer-following window manager, the keyboard 
focus is always the root window, which results in keyboard events being sent to the applica- 
tion (and to the individual window) the pointer is currently in. In any case, even 
click-to-type window managers set the keyboard focus only to children of the root win- 
dow--the application top-level windows. 
The Core class pan structure includes a field for the accept_focus method. This method 
lets a widget set the keyboard focus to one of its children when it gets the keyboard focus. A 
typical example is an application that wants to set the keyboard focus to the text entry child 
of a dialog box whenever the dialog box is given the keyboard focus by the window manager. 
This would be done so that the user can type with the pointer anywhere in the dialog widget 
instead of just with the pointer in the text entry widget. 
To implement this example, the text entry child would need an accept_focus method 
that would set the keyboard focus to itself using the Xlib call XSetTnputFocus, and the 
dialog box would need an accept_focus method that called XtCallAcceptFocus 
on the text entry widget child. The application can call XtCallAcceptFocus on the dia- 
log widget in response to FocusIn events to start this process, and set the focus back to 
PointerRoot on FocusOut events.* For details on these events and how to set the key- 
board focus with XSetInputFocus, see Volume Two, Xlib Reference Manual. (The 
Athena Dialog widget and Text widget do not define the appropriate accept_focus 
methods for this process of settting the keyboard focus to work.) This procedure is illustrated 
in Figure 13-1. 
The accept_focus returns a Boolean value to report whether it succeeded in setting the 
keyboard focus, and XtCallAcceptFocus returns this same value. 
The XtSetKeyboardFocus function can be used to redirect keyboard events that occur 
anywhere within a dialog box to a child of the dialog, usually a text entry widget. (This func- 
tion affects only Xt's event dispatching, and is independent of the X server keyboard focus, 
which has a similar but more widespread effect.) The Dialog widget can itself call this func- 
tion instead of calling XtCallAcceptFocus. Dialog can also provide a resource or pub- 
lic function to allow the application to control it. 

*XtCal IAcceptFocus is not provided in MIT's version of the R3 Intrinsics. It may be present in some vendor's 
versions of R3, but this is unlikely. It is available in all versions of the R4 Intfinsics. 

Miscellaneous Toolkit Programming Techniques 405 



From within an action routine, you can call XtGetActionKeysym to get the keysym that 
resulted in the action being called. This can be very useful, since the event passed to the 
action contains only the keycode of the key that was pressed. However, there is another way 
to acheive a similar result. You can use string parameters of actions to pass in the keysym 
that you specified in the translation table. For example, if you provide the translation 
: <Key>q : Quit (q), the Quit action will be passed the string "q" in its params argu- 
ment However, XtGetActionKeysym is very useful if you translate a wide range of key 
events to one action, and then want to distinguish between them in the action. 

13.6 

Memory Allocation 

Xt provides routines for performing routine memory allocation and deallocation. The rou- 
tines XtMalloc, XtCalloc, XtRealloc, and XtFree are equivalents of the standard 
C routines malloc, calloc, realloc, and free but they add error checking and 
reporting. The allocation routines make sure the allocation succeeded, and if it did not, they 
print a (fatal) error message. XtFree makes sure the passed pointer is not NULL before cal- 
ling free. 
XtNew is a macro which allocates storage for one instance of the passed type and returns a 
pointer. For example, XtNew (XtCallbackList) allocates storage for one callback list 
structure. XtNewString is a macro that allocates storage for a string, copies the string 
into the new storage, and returns the pointer. For example, a string can be copied into new 
storage using the following: 
static String buff] = "How do you do?"; 
String p; 

p = XtNewString (buf) ; 
After this sequence, p points to a separate string that contains "How do you do?" Then buf 
can be changed without affecting p. 

13.7 Action Hooks and Calling Actions Directly 

Xt allows you to register any number of functions to be called whenever any action in an 
application context is invoked. This is done with XtAppAddActionHook. Note that 
there is just one "action hook" in the application context, so that all the action hook functions 
registered for that application context are called whenever any of the actions in that applica- 
tion context are invoked. The registration does not specify any particular action or any par- 
ticular widget. 

The main reason for registering an action hook is to record all the actions that were invoked 
in an application, so that they can be played back later using XtCallActionProc. An 
action hook function is called with all the same arguments that are passed to an action, plus 
the string name of the action. The action hook function would store this information as a unit 

408 X Toolkit Intrinsics Programming Manual 



XtResolvePathname, since it searches directories in a standard order based on X/Open 
Portability Guide conventions. 
If you want to find a file but are not interested in internationalization, you can use XtFind- 
File. 

13.10 Application Contexts 

The introduction to application contexts in Section 3.8 described their use in 99 percent of 
applications. As you may recall, their purpose is chiefly to attain portability to certain sys- 
tems that do not provide a separate address space for each process. 

Xt provides parallel versions of many routines--one set that uses the default application con- 
text, and one set that has an explicit application context argument. The routines that use the 
default application context are remnants of an earlier release when application contexts did 
not work properly. To acheive the desired portability, you must now use the versions with the 
explicit argument. We have done this throughout this book. In Volume Five, X Toolkit 
Intrinsics Reference Manual, the reference pages for all the functions that use the default 
application context note the fact that they should no longer be used. 

Table 13-2 shows the complete list of routines that have two versions. 

Table 13-2. Xt Routines That Use Default and Explicit Application Contexts 

Default 

(regring functns) 
XtAddActions 
XtAddConverter 
XtAddInput 
XtTimeOut 
XtWorkProc 
(creating shells) 
XtCreateApplicationShell 

(eve dpahing) 
XtMainLoop 
XtNextEvent 
XtPeekEvent 
XtPending 
XtProcessEvent 

(error and warning messages) 
XtError 
XtErrorMsg 
XtGetErrorDatabase 
XtGetErrorDatabaseText 
XtSetErrorHandler 
XtSetErrorMsgHandler 
XtSetWarningHandler 

Explicit 

XtAppAddActions 
XtAppAddConverter 
XtAppAddInput 
XtAppTimeOut 
XtAppWorkProc 

XtAppCreateShell 

XtAppMainLoop 
XtAppNextEvent 
XtAppPeekEvent 
XtAppPending 
XtAppProcessEvent 

XtAppError 
XtAppErrorMsg 
XtAppGetErrorDatabase 
XtAppGetErrorDatabaseText 
XtAppSetErrorHandler 
XtAppSetErrorMsgHandler 
XtAppSetWarningHandler 

410 X Toolkit Intrinsics Programming Manual 



13.10.2 Rewriting XtAppMainLoop for Multiple Application Contexts 

To use multiple application contexts, you need to write your own equivalent of XtApp- 
MainLoop to dispatch events to your multiple application contexts. This is necessary 
because XtAppMainLoop dispatches events only from one application context, and it 
never returns so you can't call it again for the other. 
The available tools are XtAppNextEvent, XtAppPeekEvent, XtAppPending, Xt- 
AppProcessEvent, and the Xlib functions XFlush and XSync. Rewriting XtApp- 
MainLoop for two or more application contexts is tricky, because you don't want to let the 
dispatching of any one application context get behind. It is not as simple as dispatching 
events from each application context alternately, since the events might not occur alternately. 
It is easy to get stuck waiting for events in one application context while events queue up at 
the other. There is little experience in how this should be done properly, and no examples in 
the dislribution from MIT. However, hypothetically, the following describes how it could 
work. 
To do this properly, you have to understand how Xlib's network optimization works. Xlib 
buffers up many types of requests and sends (flushes) them to the server as a group.* A flush 
is most commonly caused by a routine such as XtAppNextEvent that waits for an event if 
none are available. It is because XtAppNextEvent waits forever for an event that the 
routine could get locked waiting for events in one application context while the user types 
frantically in the other. 
The answer is to use XtAppPending to determine whether an event is available on a par- 
ticular application context, and then call XtAppProcessEvent if there is an event to pro- 
cess. Then continue to do the same on each other application context. However, this alone is 
not enough. Neither XtAppPending nor XtAppProcessEvent called in this manner 
cause Xlib's buffer of requests to be sent to the server. Therefore, periodic calls to xSync or 
XFlush are necessary to flush the output buffer. The difficult part is to call these enough to 
flush the buffer when necessary, but not so much as to eliminate the advantages of the buffer- 
ing. There is no ideal solution to this problem. 
On multi-tasking systems it is perhaps possible to fork so that each application context runs 
in a separate process. 

13.10.3 

Functions Used with Multiple Application Contexts 

XtWidgetToApplicationContext and XtDisplayToApplicationContext 
could be useful if you use more than one application context in an application. XtWidget- 
ToApplicationContext is also useful in widget code, to call error-issuing routines 
flaat require an application context argument, such as XtAppWarning and XtApp- 
Wa rningMsg. 

*For a detailed discussion of Xlib's network optimization and its effects, see the introduction to Volume Zero, X 
Protocol Reference Manual. 

412 X Toolkit Intrinsics Programming Manual 



13.11 Multiple Top-level Shells 

A single application can have more than one top-level window. In other words, you are not 
restricted to containing your application's entire user interface in a single rectangle. If you 
have one section of the application that is most appropriate as a long, thin vertical window 
that looks like a long, permanent menu, and another section that is a long, horizontal bar such 
as a ruler, each of these could be a separate top-level window. That way, not only is less 
screen space wasted than if these two windows were placed within a single rectangle, but the 
user can move the two windows around separately using the window manager. The user can 
also iconify them separately when not needed. 
To create additional top-level application shell widgets, you call XtAppCreateShell or 
XtVaAppCreateShell. (XtCreateApplicationShell is now superceded.) The 
class specified in the call should be topLevelShellWidgetClass. 
As you may know, a single server may have several screens attached. At present, all shells 
created will appear on the default screen. There is no way for the application to specify that 
a shell be created on a particular screen, but then again, doing this is usually unwise anyway 
because not many users actually have more than one screen. The user can specify which 
screen is considered the default screen using the -display command-line option. 

13.12 Connecting to Multiple Servers 

One of the great features of the server-client model is that a single program can connect to 
several servers to display on the screens of several users. For example, this would allow you 
to create an X-based version of the UNIX utility wall in which one user can make a message 
appear on all user's screens throughout a network. You could also create a conferencing pro- 
gram in which each user has a window on their screen in which they can type and view typ- 
ing by others in real time, and their typing will appear on all the other user's screens. 

The Xt application opens a connection with a server using XtOpenDisplay (this routine 
requires an explicit application context argument). Once you have opened the connection, 
you will want to create a shell widget on the server's default screen using XtCreate- 
ApplicationShe]'l or XtAppCreateShell. Then, you create widgcts for each 
server simply by using the appropriate Shell widget as parent. Thereafter, XtAppMain- 
Loop dispatches events from all the connections to the appropriate widget. 

Miscellaneous Toolkit Programming Techniques 413 



When a widget class does not need an extension feature--for example, a Composite widget 
that does not accept gadget children--the widget class does not provide code in the 
class initialize method to set the extension field. 

The .c file of all widget classes should initially set all extension fields to NULL. The dif- 
ference between classes that use extension features and those that don't is only the presence 
or absence of code in class initialize to set the extension fields. 
-- 

The four required fields in an extension structure are: 

next_extension 
record_type 

version 
record_size 

Specifies the next record in the list, or NULL. 
Specifies the particular structure declaration to which each extension 
record instance conforms. 
Specifies a symbolic constant supplied by the definer of the structure. 
Specifies the total number of bytes allocated for the extension record. 

When you initialize an extension structure of a given class in the Example 13-3 shows how to 
initialize the Composite extension structure. The first two fields are usually NULL and 
NULLQUARK. The reference page for each class that has an extension structure will document 
how to initialize the third and fourth fields. 
CompositeClassExtensionRec extension rec = { 
-- 
/* next extension */ NULL, 
-- 
/* record_type */ NULLQUARK, 
/* version */ XtCompositeExtensionVersion, 
/* record size */ sizeof(CompositeClassExtensionRec), 
-- 
/* accepts_objects */ TRUE, /* only new field */ 
}; 

The next_extension field implies correctly that you can nest extension structures. Per- 
haps a later release of Xt will require the addition of more Composite class fields. These 
could be added to the end of the existing extension structure, or a new extension structure 
could be defined and a pointer to it placed in next extension. This allows additions to 
-- 
be made to a class structure without breaking binary compatibility. 

You may be wondering whether you should use extension structures when extending your 
own widgets. Probably not. Because you are likely to release your set of widgets as a pack- 
age, you have no need for binary compatibility with previous releases (of your own). Binary 
compatibility would only be an advantage if you wanted to replace a few widgets from a for- 
mer release and save users who may have subclassed the widgets you have replaced from 
recompiling their widgets. For the trouble involved, the benefit is very small. 

Miscellaneous Toolkit Programming Techniques 415 



A 

OPEN LOOK and Motif 

This appendix gives an overview of the widgets available in the AT& T widget 
set (also known as Xt+) and OSF Motif widget set. It gives a sense of the 
look and feel of applications developed with each set, and provides the inher- 
itance hierarchy and overview of the available widgets. 

In This Chapter: 

The AT&T OPEN LOOK Widgets ......................................................... 423 
Application Controls ....................................................................... 424 
Command Buttons ....................................................................... 424 
Exclusive and Nonexclusive Settings ........................................... 426 
Analog Controls ........................................................................... 428 
Composite Widgets ........................................................................ 428 
Menus and Control Areas ............................................................ 428 
General Purpose Composite Widgets .......................................... 429 
Scrollbars and Scrollable Windows .............................................. 429 
Pop Ups ........................................................................................ 431 
Text Widgets .................................................................................. 433 
Drawing Areas ..... ........................................................................... 433 
The OSF/Motif Widgets ...................................................................... 433 
Application Controls ....................................................................... 436 
Command Buttons ....................................................................... 436 
Analog Controls ........................................................................... 436 
Composite Widgets ........................................................................ 437 
Menus and Control Areas ............................................................ 437 
General Purpose Composite Widgets .......................................... 440 
Scrollable Windows ...................................................................... 441 
Pop Ups ........................................................................................ 442 
Text Widgets .................................................................................. 443 
Drawing Areas ............................................................................... 443 



feature. Nor should its implementation be considered the only way to provide features called 
for by OPEN LOOK. 
The Open Software Foundation's Motif toolkit is based on a combination of widget sets orig- 
inally developed by two OSF sponsors, Digital and Hewlett Packard. The look and feel of 
the widget set was proposed by HP/Microsoft. It is designed to emulate the look and feel of 
the IBM/Microsoft Presentation Manager standard widely expected to be adopted in the 
microcomputer world. 
Motif's API (Application Programmer's Interface) is based on DECWindows. Digital also 
provided Motif with some underlying enhancements to the Xt Intrinsics (most notably an 
implementation of windowless widgets called gadgets) and various supporting utilities. 
Motif release 1.0, described here, is based on the R3 Intrinsics; with these enhancements. 
Motif release 1.1, due in late summer 1990, is based on the standard R4 Intrinsics. 
Table A-1 compares the widgets available in Athena, AT&TOPEN LOOK set, and Motif. 

Table A-1. Comparison of Athena, OPEN LOOK, and Motif Widgets 

Simple widgets (mostly controls): 
Athena OPEN LOOK 

Command 
Toggle 

MenuButton 

Scrollbar 

OblongButton 
ToggleButton 
CheckBox* 

ButtonStack 

Motif 

Push_Button 
DrawnButton 
RectButton 
-- 

Gp 
Label 
Text 

AbbrevStack 

ScrollingList* 
Scrollbar 

Slider 

StadcText 
Text 
TextField 

CascadeButton 

ArrowButton 

List 

ScrollBar 

Scale* 

Label 
Text 
Text 

Separator 

Description 

Invokes a command 
Invokes a command 
Chooses a setting 
Alternate way of 
choosing a setting 
Invokes a menu, dis- 
plays label 
Invokes a menu, dis- 
plays default 
Reverses direction of 
movement 
Displays a list of select- 
able strings 
Scrolls through an 
associated window 
Sets (or displays) an 
analog value 
Resize point for panes 
in VPaned 
Displays a fixed string 
Displays editable text 
Displays a single line 
of editable text 
Displays a line or other 
separator 

*Checkbox, ScrollingList, and Scale are technically composite widgets. 

420 X Toolkit Intrinsics Programming Manual 



Table A-1. Comparison of Athena, OPEN LOOK, and Motif Widget (continued) 
Pop ups (subclasses of shell): 

Athena 

SimpleMenu 

OPEN LOOK 

Menu 
Notice 

PopupWindow 

Help 

Motif 

MenuShell 
DialogShell 

Description 

Parents a popup menu 
Displays a dialog 
requiring input 
Displays a more com- 
plex dialog 
Displays a help win- 
dow 

Composite and Constraint Widgets: 
Athena OPEN LOOK 

Box 

ForlTl 

Viewport 

VPaned 

BulletinBoard 

ConolArea 

Motif 

BulletinBoard 

Exclusives 

Nonexclusives 

FooterPanel 

ScrollingList* 

Caption 

ScrollingWindow 

DrawingArea 

RowColumn 

FralTle 

SelecdonBox 

Command 

FileSelectionBox 

ScrolledWindow 

MainWindow 

PanedWindow 

*Checkbox, ScrollingList, and Scale are technically composite widgets. 

Description 

Free-form placement 
area 
Free-form drawing area 
Displays children in 
order added 
Arranges children in 
rows or columns 
Manages children rela- 
tive to each other 
Makes RectButton chil- 
dren exclusive 
Makes RectButton chil- 
dren nonexclusive 
Provides a consistently- 
sized message area 
Gives consistent border 
to enclosed widgets 
Provides a selectable 
list of swings, plus a 
text area for entering a 
new value 
Provides a selectable 
list of commands 
Provides a selectable 
list of ffdenames 
Displays a label and 
one child widget 
Displays a scrollable 
child window 
ScrolledWindow with 
special appearance 
Displays panes resiz- 
able in one direction 

Appendix A: OPEN LOOK and Motif 421 



Comparable widgets share a line in the table. Widgets for which no equivalent occurs in a 
given set are indicated by a hyphen in the appropriate column. Note that comparisons are 
approximate only, since widgets have complex behavior that may distinguish them signifi- 
cantly from another widget with an ostensibly similar purpose. 
The following sections provide an overview of the widgets available in the OPEN LOOK and 
Motif widget sets. Throughout, we contrast them with the Athena widgets, which have been 
used as examples in this book, to give you an idea of the additional features provided by the 
commercial widget sets. 
Keep in mind that the look and feel of an application is controlled by the window manager as 
well as by the widget set. Both AT&T and OSF supply window managers to complement 
their widgets. 
Note that both widget sets make additions to the basic X Toolkit API. In the AT&T OPEN 
LOOK widget set, these API additions are rather minor. There is one essential function, O1- 
Initialize, which sets initial values needed by other routines and by certain widgets. 
Ollnitialize creates a base window, which from the programmer's point of view is 
identical to the Intrinsics-supplied TopLevelShcll widget class, but which automatically 
handles certain features of the OPEN LOOK interface. Thcre are also several convenience 
functions, mostly having to do with conversions between pixel sizcs and various standard 
units. More importantly, thcre is a facility for registering help screens for each element in an 
application. 
Motif 1.0 has made more extensive API additions and even changes, modifying all of the 
base widget classes, and other Intrinsics features. Therefore, the Motif 1.0 Intrinsics are not 
compatible with the MIT R3 or R4 Intrinsics. Motif 1.0 support for windowless widgets, or 
"gadgets," is part of OSF's proprietary version of the Intrinsics, which is not completely 
compatible with the version of gadgets support in the MIT R4 release. However, Motif 1.1 is 
expected to be fully compatible with the MIT Release 4 Intrinsics. 
In addition, Motif makes heavy use of convcnience functions. Rather than using Xt- 
CreateManagedWidget to create each widget, there is a separate creation routine for 
each widget. In some cases, a convenience routine creates more than one widget. Rather 
than using separate calls to XtCreatePopupShell and XtCreateManagedWidget 
to create a pop-up shell and the dialog box it displays, you might call a function such as Xm- 
CreateMessageDialog to create both widgets at once. Some convenience routines cre- 
ate special configurations of a single, complex widget (e.g., a composite widgct with specific 
childrcn.) 
In Motif, all resources are referred to by names beginning with XmN or XmC rather than the 
familiar XtN and XtC. 
Motif also uses the call_data argument of callback functions extensively. Almost every 
widget has a structure defined as widgetclassCallbackStruct (e.g., XmToggle- 
ButtonCallbackStruct). This struct contains diffcrent fields for each widget, but 
each contains a field called reason. The reason field defines which callback has been 
called. So using this feature allows you to have a single piece of code to handle all callbacks 
for a widget. 

422 X Toolkit Intrinsics Programming Manual 



I 
[Primitive 
I 

I I 
Stack I Button 

Core 
I, 

' j 

Others not instantiated by 
application programmer: 
Arrow Magnifier 
Check Pushpin 
 ListPane TextPane 
Help 

Constraint 
! 

Manager 

I 
WMShell j 
I 
J VendorShell / 
I 
I TopLevelShel' I 
i 
J BaseWindow / 
I MenuShel, j l NoticeShel, tl PopupWindowShel, i 

* New in Release 2 of OpenLook Toolkit 

Figure A-2. Class inheritance hierarchy of the AT& T OPEN LOOK widgets 

The OPEN LOOK widget set implements similar functions using the OblongButton and 
ButtonStack widgets. Figure A-3 shows a Control Area containing OblongButton and 
ButtonStack widgets. 

The OblongButton widget provides many niceties lacking from the Athena Command 
widget. One of the most important is that OblongButton has a resource that allows one but- 
ton among several to be designated as the default, in which case the button is bordered by a 

Appendix A: OPEN LOOK and Motif 425 



In an Exclusives widget, RectButton widgets are laid out side by side in one or more col- 
umns. One or none of the RectButton widgets is chosen as the default, which is indicated by 
a double border. Once a RectButton is selected, it is shown with a dark border The Exclu- 
sives widget makes sure that no more than one RectButton is selected at a time. 
In a Nonexclusives widget, RectButtons are displayed with separation between each button. 
As when used in an Exclusives widget, a dark border indicates that the option has been cho- 
sen. However, more than one button may be chosen at a time. 
Figure A-4 shows examples of exclusive and nonexclusive settings on menus. Note that, like 
the OblongButton, a RectButton may display a pixmap instead of a label. This makes the 
RectButton useful for a palette in a paint program. 

Size V) ( Patterns V) () 

(Italic 

'Underl ine ) 

'Overstrike) 

Figure A-4. OPEN LOOK RectButtons controlled by Exclusives and Nonexclusives widgets 

The CheckBox widget provides an alternate way to display nonexclusive settings to the user. 
It displays a small box next to the label and displays a checkmark in the box when the option 
is selected. Checkboxes appear in ControlAreas rather than on menus. Figure A-5 shows 
examples of CheckBox widgets. 

Appendix A: OPEN LOOK and Motif 427 



A.1.2.2 General Purpose Composite Widgets 

A.1.2.3 

We've already discussed the Composite widgets relating to control areas and menus. How- 
ever, there are several general-purpose composite widgets in the OPEN LOOK set as well. 
The BulletinBoard widget provides a free-form area for placing subwindows. Widgets can 
be placed on a BulletinBoard at arbitrary x and y coordinates; if no coordinates are specified, 
they appear in the upper left corner. The BulletinBoard provides no management of its chil- 
dren, and is often used to estabish the base frame for an application, since it allows the appli- 
cation programmer to place the major components of the application, rather than having to go 
by some Composite widget's arbitrary placement decisions. 
A BulletinBoard is often used as the main window of an application. 
The Form widget is a constraint widget similar to the Athena Form widget. It allows the 
placement of widgets to be specified relative to each other, and with rules governing their 
separation or relative position. 
The Caption widget is like an Athena Label widget turned inside out. Like the Label widget, 
it prints a string. However, while the label widget's string is printed inside a visible widget 
border, a Caption string appears outside a bordered area. Caption is a composite widget 
class, and its label typically refers to a child widget of any size, which the Caption widget 
manages. The label can be aligned on either the right, left, top or bottom of the child widget. 
The FooterPanel widget provides a consistent method for placing a footer along the bottom 
of another window. The footer panel takes two children. The top child is typically the main 
composite widget of the application; the bottom widget may contain a control or message 
area. The basic feature of the FooterPanel widget is that when the widget is resized, it 
applies all the change in the vertical direction to the top child, maintaining the bottom child 
at a constant height. 

Scrollbars and Scrollable Windows 

OPEN LOOK scrollbars use the visual metaphor of an elevator on a cable, but functionally 
they are similar to the Athena Scrollbar widget. The drag area (the thumb in an Athena 
Scrollbar widget) doesn't change size; instead, as shown in Figure A-7, there is a separate 
area that indicates the p:opo/tion of the data that is currently being displayed. 

Scrollbars may be oriented either horizontally or vertically. 

Scrollbars are used as a component of a ScrolledWindow widget, which, like the Athena 
Viewport widget, provides a scrollable view of a data area in a child widget. The child 
widget is typically larger than the view area, but only the area in the parent's view area can 
be seen at any one time. Figure A-1 showed a ScrolledWindow widget as the main applica- 
tion pane. The ScrollingList widget displays a scrollable list of editable text fields, and pro- 
vides facilities for choosing and displaying one of the fields as "currently selected." Items 
can be selected from the list, changed, copied, and so on. This widget is useful for providing 
an interface to select a file for reading or writing. 

Appendix A: OPEN LOOK and Motif 429 



A.1.3 Pop Ups 

In addition to Menu widgets, the OPEN LOOK widget set contains three other special types of 
pop-up widgets: Notices, PopupWindows, and Help windows. A Notice is used to request 
confirmation or other information from the user. The widget contains a text area, where the 
message to the user is displayed, and a control area containing one or more buuons, one of 
which must be the default button. 

Figure A-9 shows an OPEN LOOK Notice widgeL 

, 

!.!!i! l:ile [xi,t,. Overtrite it? 

Figure A-9. An OPEN LOOK Notice 

A Notice grabs the pointer. The only input allowed is to the Notice. Once the user has 
clicked a button, the Notice disappears. 
The second special pop-up type is a PopupWindow, which can be used for more complex pop 
ups. Unlike a Notice, which is a subclass of OverrideShell, a PopupWindowShell is a sub- 
class of WMShelI, and so is decorated by the window manager. It has all the visual attributes 
of a top-level window, including resize comers, etc. In addition, it displays a pushpin in the 
upper left corner. If the user clicks on the pushpin with the pointer, the menu doesn't go 
away when its action has been performed, but stays on the screen. This allows the user to 
keep menus (and other frequently-referenced pop ups, such as help screens) "pinned" on the 
display, where they can be moved like regular windows. (Menus can also display a pushpin; 
its presence or absence is controlled by a widget resource.) " 
A PopupWindow typically contains an upper control area that may include menus, and a 
lower control area that may be used for buttons invoking widget actions. Resources allow for 
automatic creation of several buttons, including a "reset to factory" button, a "set defaults" 
button, and several other ways of setting standard properties for an application. 

Appendix A: OPEN LOOK and Motif 431 



A.2.1 

A.2.1.1 

Application Controls 
Like OPEN LOOK, Motif has a much richer set of application controls than Athena. 

Command Buttons 

MotiFs PushButton is equivalent to Athena's Command widget and OPEN LOOK's Rect- 
Button. It has a 3-D appearance and seems to be depressed when clicked on. It invokes sep- 
arate callbacks for button up, button down, and button click, much like the equivalent widg- 
ets in other sets. 
The DrawnButton works similarly, but allows the programmer to provide a pixmap for the 
appearance of the button. 
Figure A-14 shows a DrawnButton and a PushButton. 

I I 

Cancel 

A.2.1.2 

Figure A-14. Motif DrawnButton and PushButton widgots 

The CascadeButton is similar in effect to OPEN LOOK's ButtonStack--it can have a particu- 
lar appearance that indicates that a menu is invoked, rather than a single callback. Typically, 
this is simply an arrow pointing in the direction where the menu will appear. 
A ToggleButton is used for option setting, much like OPEN LOOK's RectButton or Check- 
Box. Figure A-16 shows a box containing a set of ToggleButtons. 
The Separator widget can be used to draw a line or other separator between a group of widg- 
ets in a menu or other box. It is typically used in menus. 
The List widget displays a list of strings set by the application and allows the user to select 
one or more of the strings. The selected data is passed to a callback function. (We'll talk 
more about this widget in the section on scrolling.) 

Analog Controls 

Motif's Scale widget is similar to OPEN LOOK's Slider but is more powerful since it can be 
used to display as well as to control analog values. 

436 X Too&# Intrinsics Programming Manual 



A.2.2 Composite Widgets 

A.2.2.1 

As with OPEN LOOK, we've divided the discussion of Composite widgcts into three areas: 
Menus and Control Areas, General-Purpose Composite Widgets, and Scrollable Windows. 
These distinctions are somewhat arbitrary and with menus the sections overlap with the one 
on Pop ups, which appears later. 

Menus and Control Areas 

Motif provides a special Shell widget class called McnuShell for managing pop-up menus. 
However, most actual menu displays are managed by the RowColumn composite widget, 
which, like OPEN LOOK's ControlArea, displays buttons in rows or columns. 
Through resources, the RowColumn widget can be configured to create such specialized, 
predefined elements as a McnuBar (which can only accept CascadeButton widget.,; as chil- 
dren), several different styles of pull-down or pop-up menu panes, and several preconfigurcd 
control areas, such as a "Radio Box" containing multiple exclusive TogglcButton gadgets. 
Here you can begin to see the wide divergence in programming style made possible by the Xt 
Intdnsics. It is possible to create a hierarchy of relatively simple widget.,; to perform separate 
parts of a task, or a single, very complex widget which is highly configurablc. In one of its 
incarnations, the RowColumn widget is equivalent to an OPEN LOOK ControlArca plus an 
Exclusives widget; in another, a ControlArca plus a Noncxclusives. 
In general, Motif widgets are more complex and have many more resources than widgct`s pro- 
vided in other widget sets. To simplify their use, though, Motif provides numerous conve- 
nience functions. For example, XmCreat.eRadioBox will create a RowColumn widget 
with one specialized set of resources, while XmCreat:eMenuBar will create one that is 
entirely different in appearance and function. 
Figure A-15 shows a RowColumn widget configured as a McnuBar and Figure A-16 shows 
one configured as a RadioBox (each with appropriate children). 

Appendix A: OPEN LOOK and Motif 437 



Figure A-17 shows a RowColumn widget implementing a drop-down menu. 
Items on Motif menus can be selected by dragging the pointer down the menu and releasing 
it when the chosen item is highlighted. Alternately, the pointer can simply be clicked on the 
menu title to drop down the menu. Clicking on an item in the menu selects it; clicking any- 
where other than in the menu pops the menu down without executing any item. 
Note also that as a general feature, Motif menus support accelerators. That is, there are key- 
board equivalents for every menu item. These keyboard accelerators are listed after the 
menu label, as shown above. In addition, typing the underlined letter in any menu item label 
when the pointer is in the menu will select that menu item. These underlined letters are 
called "mnemonics." 
The items on a menu bar or menu pane simply appear as labels but when selected take on the 
3-D appearance of a PushButton. 

Figure A-17. A Motif RowColumn widget configured as a drop-down menu 

Appendix A: OPEN LOOK and Motif 439 



A.2.2.3 Scrollable Windows 

A Motif ScrollBar is illustrated in Figure A-19. 

Figure A- 19. A Motif ScrollBar 

Like the Athena Scrollbar widget, the scrollbar has a "thumb" or slider that can be dragged 
up and down to scroll the associated window. You can also click above or below the thumb 
to move it a screenful at a time. Unlike the Athena widget, it also displays arrows at either 
end that can be used to scroll line by line. The associated window scrolls in the indicated 
direction as long as the pointer button is held down in one of the arrows. 
There are several different types of scrolling windows. The ScrolledWindow widget, like 
Athena's Viewport, provides a general mechanism for attaching scrollbars to some other win- 
dow. 
The MainWindow widget is a subclass of ScrolledWindow with a special appearance 
reserved for application main windows. Figure A-14 showed a MainWindow widget. 
Using the XmCreateScrolledList function, a List widget can be created as a child of 
a ScrolledWindow, giving the effect of a simple scrolled list. In addition, there are several 
flavors of more complex scrolling lists. These include the SelectionBox widget, and its two 
subclasses, Command and FileSelectionBox. 
A general-purpose SelectionBox is akin to a ScrolledWindow/List combination, but adds a 
Text widget for entering additional data not on the list. The SelectionBox also adds at least 
three buttons labeled by default OK, Cancel and Help. 

Figure A-20 shows a SelectionBox. 

Appendix A: OPEN LOOK and Motif 441 



Item 
*Foreground ................ black 
*activeForeground .......... black 
*activeBackground ........... gray 
*topShadowCoior ........... white 
*bottomShadowColor ....... black 

Selection 

list box 

scroll bars 

selection box 

push buon 

Figure A-20. A Motif SelectionBox 

A FileSelectionBox is a SelectionBox specially designed to present a list of filenames for 
selections. A Command widget is a special kind of SelectionBox whose list consists of the 
history of commands entered in the Text widget. Each time a new command is entered, it is 
added to the history list. 

A.2.3 

Pop Ups 

Motif defines two classes of Shell widgets: DialogS hell, which is used for parenting Dialog 
boxes, and MenuShell, which is used for menus. These classes are rarely instantiated 
directly, but are instead created by convenience functions that also create their composite 
children. 

For example, functions exist to create a DialogShell with a variety of pre-configured 
MessageBox widgets as the visible child. 

As we've already discussed, a specially configured RowColumn widget is used to create a 
menu pane as the visible child of a MenuShell widget. 

442 X Toolkit Intrinsics Programming Manual 



A.2.4 Text Widgets 

Like Athena and the AT&T OPEN LOOK widgets, Motif provides a Text widget that supports 
a complete editing command set. Like Athena, and unlike AT&T's OPEN LOOK widget set, 
both single- and multiline editing is supported by a single widget. But arranging for single- 
line editing is easier with Motif than with Athena. 

A.2.5 

Drawing Areas 

As you may recall, to do drawing in the Athena widgets we either created a custom widget or 
instantiated a Core widget in order to obtain a window for drawing. The Motif DrawingArea 
widget class answers this need in Motif. It provides a window for drawing and provides very 
simple, bulletin-board like composite management of children. 

Though the name of this widget class sounds promising, you should be aware that Motif 
really provides no more sophisticated drawing capabilities than Athena or the AT&T OPEN 
LOOK widget set. In each case, once you have selected the widget to draw on, you simply 
draw in its window using Xlib calls. 

Appendix A: OPEN LOOK and Motif 443 



B 

Specifying Fonts and Colors 

This appendix describes the possible values for color, font, and geometry 
resource specifications. 

In This Chapter: 

Color Specification ............................................................................. 447 
Color Names ................................................................................. 447 
Hexadecimal Color Specification .................................................... 448 
The RGB Color Model .................................................................. 449 
How Many Colors are Available? ................................................. 450 
Font Specification .............................................................................. 452 
Font Naming Conventions .............................................................. 453 
Font Name Wildcarding .................................................................. 454 
Font Name Aliasing ....................................................................... 456 
Making the Server Aware of Aliases ............................................... 457 
The fonts.dir Files .......................................................................... 457 
Window Geometry ............................................................................. 458 



B 
Specifying Fonts and Colors 

This appendix describes the possible values for color, font, and geometry resource specifica- 
tions. 

B.1 Color Specification 

Many clients have resources and command-line options that allow you to specify the color of 
the window background, foreground (the color that text or graphic elements will be drawn 
in), or window border. For example, the following resources might be set for a Label widget: 
*background : orange set the background color to orange 
* foreground : black set the foreground color to black 
*borderColor : black This must be Halloween! 
The corresponding command-line options have the form: 
-bg co2 or sets the background color 
-fg co2 or sets the foreground color 
-bd co2 or sets the border color 
Some clients allow additional options to specify color for other elements, such as the cursor, 
highlighting, and so on. 
By default, the background is usually white and the foreground black, even on color worksta- 
tions. You can specify a new color using either the names in the X Window System's color 
name database or hexadecimal values. 

B.1.1 

Color Names 

The rgb.txt file, usually located in/usrllib/X11 on UNIX systems, is supplied with X and con- 
sists of predefined colors assigned to specific (but not necessarily intuitive) names.* 

*A corresponding compiled file called rgb.pag contains the definitions used by the server;, the rgb.txt file is the 
human-readable equivalent. 

Appendix B: Specifying Fonts and Colors 447 



The following are the default color names that come with the X Window System. (See 
Appendix A, System Management, in Volume Three, X Window System User's Guide, for 
information on customizing color name definitions.) This file is not part of the X standard, so 
vendors are free to modify it. However, most will just add to it, or redefine the values associ- 
ated with each color name for better effects on their display hardware. 

aquamarine mediumaquamarine black blue 
cadetblue cornflowerblue darkslateblue lightblue 
lightsteelblue mediumblue mediumslateblue midnightblue 
navyblue navy skyblue slateblue 
steelblue coral cyan firebrick 
gold goldenrod mediumgoldenrod green 
darkgreen darkolivegreen forestgreen limegreen 
mediumforestgreen mediumseagreen mediumspringgreen palegreen 
seagreen springgreen yellowgreen darkslategrey 
darkslategray dlmgrey dlmgray llghtgrey 
lightgray khaki magenta maroon 
orange orchid darkorchld medlumorchld 
pink plum red Indlanred 
mediumvioletred orangered violetred salmon 
sienna tan thistle turquoise 
darkturquolse medlumturquolse violet bluevlolet 
wheat white yellow greenyellow 

As of R4, a number zero through three can be appended to each of these names in order to get 
various intensities of each color. In addition, a complete range of grays are provided by 
using the name gray or grey followed by a number from zero through 100. There are also a 
few colors not provided in the R3 database, such as snow and misty rose. These names can be 
used directly when the specific color is wanted. 
For example, the command line: 
% xterm -bg lightblue -fg darkslategray -bd plum & 
creates an xterm window with a background of light blue, foreground of dark slate gray, and 
border of plum. Note that the RGB values in the color database provided by MIT are correct 
for only one type of display; you may find that the color you get is not exactly what you 
expect given the name. To combat this, vendors may have corrected the RGB values to give 
colors closer to what the name implies. 
At the command line, a color name should be typed as a single word (for example, dark- 
slategray). However, you can type the words comprising a color name separately if you 
enclose them in quotes, as in the following command line: 
% xterm -bg "light blue" -fg "dark slate gray" -bd plum & 

B.1.2 

Hexadecimal Color Specification 

You can also specify colors more exactly using a hexadecimal color string. You probably 
won't use this method unless you require a color not available by using a color name. More- 
over, you shouldn't use this method unless necessary because it tends to discourage the shar- 

448 X Toolkit Intrinsics Programming Manual 



B.1.2.1 

ing of colors between applications. In order to understand how this works, you may need a 
little background on how color is implemented on most workstations. 

The RGB Color Model 

Most color displays on the market today are based on the RGB color model. Each pixel on 
the screen is actually made up of three phosphors: one red, one green, and one blue. Each of 
these three phosphors is excited by a separate electron beam. When all three phosphors are 
fully illuminated, the pixel appears white to the human eye. When all three are dark, the 
pixel appears black. When the illumination of each primary color varies, the three phosphors 
generate a subtractive color. For example, equal portions of red and green, with no admix- 
ture of blue, makes yellow. 
As you might guess, the intensity of each primary color is controlled by a three-part digital 
value--and it is the exact makeup of this value that the hexadecimal specification allows you 
to seL 
Depending on the underlying hardware, different servers may use a larger or smaller number 
of bits (from 4 to 16 bits) to describe the intensity of each primary. To insulate you from this 
variation, clients are designed to take color values containing anywhere from 4 to 16 bits (1 
to 4 hex digits), and the server then scales them to the hardware. As a result, you can specify 
hexadecimal values in any one of the following formats: 
#RGB 
#RRGGBB 
#RRRGGGBBB 
#RRRRGGGGBBBB 
where R, G, and B represent single hexadecimal digits and determine the intensity of the red, 
green, and blue primaries that make up each color. 
When fewer than four digits are used, they represent the most significant bits of the value. 
For example, #3a6 is the same as #3000a0006000. 
What this means concretely is perhaps best illustrated by looking at the values that corre- 
spond to some colors in the color name database. We'll use 8-bit values (two hexadecimal 
digits for each primary_) because that is the way they are defined in the rgb.txt file: 

#000000 black 
#FCFCFC white 
#FF0000 red 
#00FF00 green 
#0000FF blue 
#FFFF00 yellow 
#00FFFF cyan 
#FF00FF magenta 
#SF9F9F cadet blue 
#42426F cornflower blue 
#BFD8D8 light blue 
#8F8FBC light steel blue 
#3232CC medium blue 
#23238E navy blue 
#3299CC sky blue 

Appendix B: Specifying Fonts and Colors 449 



B.1.2.2 

#007FFF slate blue 
#236B8E steel blue 

As you can see from the colors given above, pure red, green, and blue result from the corre- 
sponding bits being turned full on. All primaries off yields black, while all nearly full on 
gives white. Yellow, cyan, and magenta can be created by pairing two of the other primaries 
at full intensity. The various shades of blue shown above are created by varying the intensity 
of each primary--sometimes in unexpected ways. 
The bottom line here is that if you don't intimately know the physics of color, the best you 
can do is to look up existing colors from the color name database and experiment with them 
by varying one or more of the primaries till you find a color you like. Unless you need pre- 
cise colors, you are probably better off using color names. 
If you do specify a color using a hexadecimal value, try to use the same value for several 
applications so that they will share a color call. 

In any event, using hexadecimal values for colors is not generally recommended, since it dis- 
courages sharing of color cells. 

How Many Colors are Available? 

The number of distinct colors available on the screen at any one time depends on the amount 
of memory available for color specification. 
A color display uses multiple bits per pixel (also referred to as multiple planes or the depth of 
the display) to select colors. Programs that draw in color use the value of these bits as a 
pointer to a lookup table called a colormap, in which each entry (or colorcell) contains the 
RGB values for a particular color.* As shown in Figure B-l, any given pixel value is used as 
an index into this table--for example, a pixel value of 16 will select the sixteenth colorcell. 
This implementation explains several issues that you might encounter in working with color 
displays. 
First, the range of colors possible on the display is a function of the number of bits available 
in the colormap for RGB specification. If 8 bits are available for each primary, then the 
range of possible colors is 256 3 (somewhere over 16 million colors). This means that you 
can create incredibly precise differences between colors. 
However, the number of different colors that can be displayed on the screen at any one time 
is a function of the number of planes. A four-plane system can index 2 '= colorcells (16 dis- 
tinct colors); an eight-plane system can index 2 s colorcells (256 distinct colors); and a 
24-plane system can index 2 24 colorcells (over 16 million distinct colors). 
If you are using a four-plane workstation, the fact that you can precisely define hundreds of 
different shades of blue is far less significant than the fact that you can't use them all at the 
same time. There isn't space for all of them to be stored in the colormap at one time. 
*There is a type of high-performance display in which pixel values are used directly to control the illumination of the 
red, green, and blue phosphors, but far more commonly, the bits per pixel are used indirectly, with the actual color 
values specified independently, as described here. 

450 X Toolk# Intrinsics Programming Manual 



Frame Buffer 16 
I 
I A Pixel Value 12 
9 
7 
r Cell 6 
IZ}- 5 
4 
3 
2 
1 

Colormap 
R G B 

0 0 255 

R = Red 
G = Green 
B = Blue 

Figure B-1. Multiple planes used to index a colormap 

This limitation is made more significant by the fact that X is a multiclient environment. 
When X starts up, usually no colors are loaded into the colormap. As clients are invoked, 
certain of these cells are allocated. But when all of the free colorcells are used up, it is no 
longer possible to request new colors. When this happens, you will usually be given the 
closest possible color from those that have already been allocated. However, you may 
instead be given an error message and told that there are no free colorcells. 
In order to minimize the chance of running out of colorcells, many programs use "shared" 
colorcells. Shared colorcells can be used by any number of applications, but they can't be 
changed by any of them. They can be deallocated only by each application that uses them, 
and when all applications have deallocated the cell, it is available for setting again. Shared 
cells are most often used for background, border, and cursor colors. 
Alternately, some clients have to be able to change the color of graphics they have already 
drawn. This requires another kind of cell, called private, which can't be shared. A typical 
use of a private cell would be for the palette of a color mixing application. Such a program 
might have three bars of each primary color, and a box which shows the mixed color. The 
primary bars would use shared cells, while the mixed color box would use a private cell. 
In summary, some programs define colorcells to be read-only and shareable, while others 
define colorcells to be read/write and private. 
To top it off, there are even clients that may temporarily swap in a whole private colormap of 
their own. Because of the way color is implemented, if this happens, all other applications 
will be displayed in unexpected colors. 

Appendix B: Specifying Fonts and Colors 451 



B.2.1 Font Naming Conventions 

In Release 2, font names were determined by the names of the files in which they are stored, 
without the .snfextension. For example, the filefg-16.snfcontzfins the font named fg-16. 
If you do a listing of any of the current font directories, you'll notice that the filenames also 
have .snf extensions. However, font names are not determined by the names of the files in 
which they are stored. 
Now, a font's name is determined by the contents of the font property named FONT* rather 
than the name of the file in which the font is stored. 
If you run xlsfonts, you'll get an intimidating list of names similar to the one shown in Figure 
B-2, which upon closer examination contains a great deal of useful information: 

vertical resolution in dpi 

points (in tenths average width (in 
foundry weight set width of a point) tenths of a pixel) 
-adobe-courier-bold-o-normal--lO-lOO-75-75-m_60_iso8859_i 
font family slant pixels spacing character set 

horizontal resolution in dpi 

Figure B-2. A font name 

This rather verbose line is actually the name of the font stored in the file courB010 (in the 
75dpi directory). This font name specifies the foundry (Adobe), the font family (Courier), 
weight (bold), slant (Oblique), set width (normal), size of the font in pixels (10), size of the 
font in tenths of a point (100--measured in tenths of a point, thus equals 10 points), horizon- 
tal resolution (75dpi), vertical resolution (75dpi), spacing (m, for monospace), average width 
in tenths of a pixel (60--measured in tenths of a pixel, thus equals 6 pixels) and character set 
(iso8859-1). 

The meaning of many of these statistics is obvious. Some of the less obvious information is 
explained below. 

Foundry 

The type foundry (in this case, Adobe) that digitized and supplied the 
font. 

*A property is a piece of information associated with a window or a font. See Volume One, Xlib Programming 
Manual, for more information about properties. 

Appendix B: Specifying Fonts and Colors 453 



Set width A value describing a font's proportionate width, according to the foun- 
dry. Typical set widths include: normal, condensed, narrow, double 
width. All of the newer fonts have the set width normal. 
Pixels and points Type is normally measured in points, a printer's unit equal to 1/72 of an 
inch. The size of a font in pixels depends on the resolution of the display 
font in pixels. For example, if the display font has 100 dots per inch (dpi) 
resolution, a 12 point font will have a pixel size of 17, while with 75 dpi 
resolution, a 12 point font will have a pixel size of 12. 
Spacing Either m (monospace, i.e., fixed-width) or p (proportional, i.e., variable- 
width). 
Horizontal and vertical resolution 
The resolution in dots per inch that a font is designed for. Horizontal and 
vertical figures are required because a screen may have different capaci- 
ties for horizontal and vertical resolution. 
Average width Mean width of all characters in the font, measured in tenths of a pixel, in 
this case 6 pixels. 
Character set ISO, the International Standards Organization, has defined character set 
standards for various languages. The iso8859-1 in Figure B-2 represents 
the ISO Latin 1 character set, which is used by all of the fonts in the 
75dpi and lOOdpi directories. The ISO Latin 1 character set is a superset 
of the standard ASCH character set, which includes various special char- 
acters used in European languages other than English. See Appendix H 
of Volume Two, Xlib Reference Manual, for a complete listing of the 
characters in the ISO Latin 1 character set. 
This font-naming convention is intended to allow for the unique naming of fonts of any style, 
resolution and size. It is powerful, but unwieldy. 
To create a label widget that displays text in the font stored in the file courBOlO, you could 
use the resource setting: 
*label: -adobe-courier-bol d-o-normal--I 0-i 00-75- 75-m- 60-i so8859-i 
Since typing a font name of this length is neither desirable nor practical, the X Window Sys- 
tem developers have provided two alternatives: wildcarding and aliasing. 

B.2.2 

Font Name Wildcarding 

Any unnecessary part of a font name can be "wildcarded" by specifying a question mark (?) 
for any single character and an asterisk (*) for any group of characters. 

For 
example, using a wildcarded font name, the resource specification above could be writ- 
ten: 

*label : * courier-bold-o-*-i 00- 
(Note that when using wildcards with the -fn command line option, you must take care to 
quote the font names, since the UNIX shell has special meanings for the wildcard characters * 

454 X Toolkit Intrinsics Programming Manual 



example, say you use the following name to specify a 24 point (size), medium (weight), Italic 
(slant) Charter (family) font: 

*charter-medium-i-*-240-* 

This will match either of the following two font names (the first for 75 dpi monirs and the 
second for 1130 dpi monirs): 
-bitstream-charter-medium-i-normal--25-240-75-75-p-136-iso8859-1 
-bitstream-charter-medium-i-normal--33-240-100-lO0-p-136-iso8859-1 

depending on which directory comes first in your font path. Specifying font size explicitly in 
pixels (25 for the first or 33 for the second) rather than in points would limit you to matching 
only one of these fonts. 

Given the complexity of font names and the rules of precedence used by the server, you 
should use wildcards carefully. 

B.2.3 

Font Name Aliasing 

Another way to abbreviate font names is by aliasing--that is, by associating them with alter- 
native names. You can create a file (or files) called fonts.alias, in any directory in the font 
search path, to set aliases for the fonts in that directory. The X server uses bothfonts.dir files 
(see Section C.2.5) and fonts.alias files to locate fonts in the font path. 
Be aware that when you create or edit a fonts.alias file, the server does not automatically 
recognize the aliases in question. You must make the server aware of newly created or edited 
alias files by resetting the font path with xset as described in Section C.2.4. 
The fonts.alias file has a two-column format similar to the fonts.dir file (described in a 
moment): the first column contains aliases, the second contains the actual font names. If you 
want to specify an alias that contains spaces, enclose the alias in double quotes. If you want 
to include double quotes or other special characters as part of an alias, precede each special 
symbol with a backslash. 
When you use an alias to specify a font in a command line, the server searches for the font 
associated with that alias in every directory in the font path. Therefore, a fonts.alias file in 
one directory can set aliases for fonts in other directories as well. You might choose to create 
a single alias file in one directory of the font path to set aliases for the most commonly used 
fonts in all the directories. Example B-1 shows a sample fonts.alias file. 
Example B-1. Sample fonts.alias file 
xterml2 -adobe-courler-med I um-r-norma I--I 2-I 20-75-75-m-70- I so8859-i 
xterml4 -adobe-courler-medium-r-norma I--I 4-I 40-75-75-m- 90-I so8859-i 
terml8 -adobe-courler-medium-r-normal--I 8-I 80-75-75-m-I 10-i so8859-I 
As the names of the aliases suggest, this sample file contains aliases for three fonts (of differ- 
ent point sizes) that are easily readable in xterm windows. 
You can also use wildcards within the font names in the right hand column of an alias file. 
For instance, the alias file above might also be written: 
xterml2 *courier-medium-r-*- 120 * 

456 X Toolkit Intrinsics Programming Manual 



The corresponding resource is XtNGeometry, which can be set in a resource file as fol- 
lows: 
*mywidget. geometry : geometry_string 
The argument to the geometry option (geometry), referred to as a "standard geometry 
string," has the form: 
wi dthxh ei gh t+xof f+yof f 
The variables width and height, are values in pixels for many clients. However, applica- 
tion developers are encouraged to use units that are meaningful to the application. For 
example, xterm uses columns and rows of text as width and height values in the xterm win- 
dow. xoff (x offset), and yoff (y offset) are always in pixels. 
You can specify any or all elements of the geometry string. Incomplete geometry specifica- 
tions are compared to the resource manager defaults and missing elements are supplied by 
the values specified there. If no default is specified there, and uwm is running, the window 
manager will require you to place the window interactively. 
The values for the x and y offsets have the following effects: 

Table B-1. Geometry Specification: x and y Offsets 

Offset Variables 

+xoff 

+yoff 

-xoff 

-yoff 

Description 

A positive x offset specifies the distance that the left edge of the win- 
dow is offset from the left side of the display. 
A positive y offset specifies the distance that the top edge of the win- 
dow is offset from the top of the display. 
A negative x offset specifies the distance that the right edge of the win- 
dow is offset from the right side of the display. 
A negative y offset specifies the distance that the bottom edge of the 
window is offset from the bottom of the display. 

For example, the command line: 
% xclock -geometry 125x125-i0+i0 & 
places a clock 125x125 pixels in the upper-right corner of the display, 10 pixels from both 
the top and the right edge of the screen. 
For xterm, the size of the window is measured in characters and lines. (80 characters wide by 
24 lines long is the default terminal size.) If you wanted to use the vtl00 window in 132- 
column mode, with 40 lines displayed at a time, you could use the following geometry op- 
tions: 
% xterm-geometry 132x40-i0+350 & 
This will place an xterm window 132 characters wide by 40 lines long in the lower-right cor- 
ner, 10 pixels from the right edge of the screen and 350 pixels from the top of the screen 

Appendix B: Specifying Fonts and Colors 459 



Some clients may allow you to specify geometry strings for the size and position of the icon 
or an alternate window, usually through resources (in an .Xdefauhs or other resource file). 
See the appropriate client reference pages in Part Three of Volume Three, X Window System 
User's Guide, for a complete list of available resources. 

You should be aware that, as with all user preferences, you may not always get exactly what 
you ask for. Clients are designed to work with a window manager, which may have its own 
rules for window or icon size and placement. However, priority is always given to specific 
user requests, so you won't often be surprised. 

460 X Toolkit Intrinsics Programming Manual 



C 

Naming Conventions 

This appendix describes a suggested set of conventions for naming widgets, 
and elements within widget code. 

t 



Truncated include f'de names 

Strip the lower case letters a word at a time until the 
basename is nine characters or fewer (but strip as few 
letters as possible from the initial word). Thus: 
<Xm/Ve ryLongWidgetName, h> 
becomes: 

<Xm/VeryLWN.h> 

but: 

<Xm/Verylongwidgetname.h> 
becomes: 

Macro namesfor preprocessor 
in includefiles 

<Xm/Verylongw.h> 
(Note differenceinVeryLong(two wos)and Very- 
long (one wo).) 
#ifndef XM LABEL H 

This is to prevent header files from being included more 
than once. 

If a widget has a corresponding gadget, then Gadget is 
appended to the widget name, so XmLabelGadget is 
the gadget class name. 
Widget class pointer xmLabe 1Wi dgetC1 a s s 
Gadget class pointer xmLabelGadgetCl a s s 
Create function for widgets Widget XmCreateLabel (parent, name, 
or gadgets arglist, argcount) 
This is a shortcut to using XtCreateWidget. How- 
ever, in the case of top-level widgets (menus, dialogs, 
MainWindow), it also creates the shell widget and creates 
the requested widget within it. 
The special Create functions can also be used as conve- 
nience routines for specialized widget instances. For 
example, XmCreateWorkingDialog and Xm- 
CreateWarningDialog actually create a Message- 
Box whose XmDialogType resources are respectively 
XmDIALOG WARNING and XmDIALOG WORKING. 
OPEN LOOK uses conventions similar to Motif, but leaves the prefixes off the widget class 
name. We recommend that you supply a prefix for any widgets you write, especially if there 
is any chance that some other widget set may use the same class name. In other words, if we 
wrote a new Label widget, we might call it OraLabel, not just Label, so that we could still use 
the Athena Label widget in the same application. 

464 X Toolkit Intrinsics Programming Manual 



D 

Release Notes 

This appendix summarizes the changes between Release 3 and Release 4 
of X Toolkit, as concerns writing or converting widgets and applications. 

In This Chapter: 

Summary of New Functions and Procedure Types ............................. 467 
Application Writing ............................................................................. 470 
New Function for Initializing an Application ..................................... 470 
Varargs Interfaces ......................................................................... 470 
Special Types for Varargs List Members ...................................... 471 
Loading the Resource Database .................................................... 471 
The Language String ................................................................... 471 
New Built-In Application Resources ............................................. 472 
Fallback Resources ..................................................................... 472 
Parsing the Command Line ............................................................ 472 
Changes Affecting Both Application and Widget Writing ..................... 473 
Actions .......................................................................................... 473 
Directly Invoking Actions .............................................................. 473 
Action Hook Registration ............................................................. 473 
Obtaining Event Information in an Action Procedure .................... 473 
Registering Button and Key Grabs For Actions ............................ 474 
Action Functions and Unrealized Widgets .................................... 474 
Reserved Names for Resources and Actions ................................. 474 
Resource String Identifier Convention ............................................ 474 
Resource File Format .................................................................... 474 
Modifier Names ............................................................................. 475 
Determining Specification Revision Level ....................................... 475 
Implementation-specific Datatype Definitions ................................. 475 
Event Handlers .............................................................................. 476 
Error and Warning Handlers ........................................................... 476 
Changes Affecting Widget Writing ...................................................... 476 
New Name for Core Class ............................................................. 476 



File Content Changes .................................................................... 477 
Changes to Private .h Files .......................................................... 477 
Changes to .c Files ...................................................................... 477 
Class Extension Structures ............................................................ 477 
Composite Class Extension Structure .......................................... 478 
Constraint Class Extension Structure ........................................... 479 
New Constraint get_values_hook method .................................... 479 
Shell Class Extension Structure ................................................... 479 
New XtNvisual Resource ............................................................... 480 
Methods ........................................................................................ 480 
Mapping Order of Realized Child Widgets ...................................... 481 
Callback Lists ................................................................................ 481 
XtNunrealizeCallback ................................................................... 481 
Internal Format of Callback Lists .................................................. 481 
New Routine to Call Callback List ................................................ 482 
Resource Lists ............................................................................... 482 
Base Offsets in Resource List ...................................................... 482 
XtProcedureArg ........................................................................... 482 
Default Resource Values ............................................................. 482 
Getting a Constraint Resource List ............................................... 482 
Converters ..................................................................................... 482 
New Xt Resource Representations .............................................. 483 
New Xt Resource Converters ....................................................... 483 
New Fn for Issuing Conversion Warnings ..................................... 484 
New Resource Converters Interface ............................................ 484 
Keyboard Handling ........................................................................ 486 
KeyCode-to-KeySym Conversions ............................................... 486 
KeySym-to-KeyCode Conversions ............................................... 486 
Selections ...................................................................................... 486 
Objects .......................................................................................... 486 
The Gadget Parent ...................................................................... 487 
Xt Functions that take any Object ................................................ 487 
Xt Functions that take any RectObj .............................................. 489 
Xt Functions that take any Core ................................................... 489 
Xt Functions that take any Composite .......................................... 490 
Xt Functions that take any Shell or a Subclass ............................. 490 
Macros for Getting Object Information .......................................... 490 
Miscellaneous ................................................................................ 490 
XtNameToWidget ......................................................................... 490 
New Exposure Compression Controls .......................................... 491 
Modal Cascades .......................................................................... 492 
Requesting Key and Button Grabs ............................................... 492 
New Macros for Widget Superclass Determination ....................... 493 
Macros and Procedure Equivalents .............................................. 493 
Finding File Names ...................................................................... 493 
Improved Multi-Display Support in Xmu ....................................... 493 



D 
Release Notes 

D.1 

The Xt specification is the definition of the X Consortium standard for Xt. This appendix 
describes the changes to the Xt Inlrinsics specification between Release 3 and Release 4. 
This appendix separates them according to whether they affect just application writers, just 
widget writers, or both, so that you can read the sections appropriate to your needs. 
In the majority of cases, Xt applications correctly written for Release 3 will be source com- 
patible with Release 4. However, there have been many additions to Xt that you may wish to 
use when converting an application or widget to R4 or writing one from scratch. This is a 
fairly complete summary of the additions and changes that have been made to the Intrinsics 
since Release 3. 
Some of the information provided below describes behavior that is not new but that is newly 
documented in R4--behavior that was in the R3 implementation of Xt (and still present in 
R4) but was not in the R3 Xt specification. These places are noted. 

Summary of New Functions and Procedure Types 

XtAppInitiali ze is the new function to be used for initializing Xt applications. 
XtAppSetFallbatkResources allows you to provide a set of backup resources that 
will be used in case the app-defaults file is not installed. An argument in XtApp- 
Initialize is provided for this purpose, so XtAppSetFallbackResources is 
rarely needed. 
The following functions are the new varargs versions of existing functions: xtvaSet- 
Values, XtVaGetValues, XtVaCreateWidget, XtVaCreateManaged- 
Widget, XtVaAppCreateShell, XtVaGetSubresources, XtVaGet- 
ApplicationResources, XtVaCreatePopupShell, XtVaSetSubvalues, 
XtVaGet Subvalues, and XtVaAppInitialize. 
XtInitializeWidgetClass initializes a widget or object class without creating any 
widget or object. This is normally done in order to make available the type converters regis- 
tered by that class before the first instance of that class is created, so that resources for the 
first instance can be set while creating it using XtVaTypedArg, a new feature of Xt- 
VaSetValues and XtVaCreateWidget. 

Appendix D: Release Notes 467 



XtGetActionKeysym is used within an action routine to get the keysym that invoked the 
action. This is useful because the event passed to the action contains only the keycode. 
XtGetKeysymTable and XtKeysymToKeycodeList are two more functions for 
controlling the mapping of keycodes to keysyms. These functions are rarely needed. 
XtRegi sterGrabAction allows you to write an action that when invoked will automat- 
ically result in a global grab of the pointer or key that invoked the action. Internally in Xt 
this is used to register XtMenuPopup, so it is rarely needed. 
XtLastTimestampProcessed is useful in selection processing, since some events that 
trigger selections do not include a timestamp. XtGetSelectionRequest is used in the 
convert_proc in selections to get the time from the selection request event. 
XtDisplayOfObject, XtScreenOfObject, and XtWindowOfObject are the 
equivalents of XtDisplay, XtScreen, and XtWindow that work for objects, which are 
the windowless and sometimes geometryless forms of widgets. XtIsObject is a macro 
that lets you distinguish an object from a widget. 
XtDisplayToApplicationContext is sometimes useful in applications that open 
connections to more than one display. 
XtName converts a widget ID to a widget name, the opposite of XtNameToWidget. 
XtSetWMColormapWindows sets the value of the WM_COLORMAP_%VINDOWS prop- 
erty on a widget's window. This is done in order to tell the window manager that windows in 
this application other than the top-level window need special colormaps installed. 
Release 4 introduces a set of new selection interfaces which allow the owner and requestor to 
handle the selection in arbitrary chunks. This is called an incremental transfer, to differenti- 
ate it from the existing interfaces that implement an atomic transfer. The protocols for both 
are very similar, but the procedures written by the owner and requestor to convert and receive 
data may be called multiple times in an incremental transfer, instead of just once as in the 
atomic transfer. The new functions and procedure types are: xtCancelConvert- 
SelectionProc, XtCancel SelectionCallbackP roc, XtConvert- 
SelectionIncrProc, XtLoseSelectionIncrProc, XtSelectionDone- 
IncrProc, Xt SelectionI ncrCal ibackP roc, XtGetSelectionValue- 
Incremental, XtGet SelectionValues Increment al, and XtOwn- 
SelectionIncremental. See Chapter 10, lnterclient Communications, for a descrip- 
tion of how these functions and procedure types are used. 
XtGetApplicationNameAndClass allows an application to get its own resource 
name and class. This function is rarely needed. 
Xt implements its handling of the language sting using XtResolvePathname, which 
calls XtFindFile. These two functions are provided for applications that need to search 
the file system for files. XtResolvePathname searches using X/Open language localiza- 
tion conventions, while XtFindFile searches arbitrary paths. 

Appendix D: Release Notes 469 



D.2 Application Writing 

The major changes from an application a'iter's point of view include windowless objects, 
varargs-style interfaces, fallback resources, and locale-driven finding of data files. 

D.2.1 

New Function for Initializing an Application 

Instead of xtInitialize, applications should now use XtAppInitialize or Xt- 
VaAppInitialize to initialize the X Toolkit internals, create an application context, 
open and initialize a display and create the initial application shell instance. Its arguments 
are somewhat different from Xtlnitialize. See Chapter 3, More Techniques for Using 
Widgets, or Volume Five, X Toolkit Intrinsics Reference Manual, for details. XtApp- 
Initialize calls XtToolkitlnitialize, XtCreateApplicationContext, 
XtAppSetFallbackResources, XtOpenDisplay, and XtAppCreateShell. 

One argument of XtAppInitialize is a string containing resources that will be the 
backup in case the application's app-defaults file is not present. These are called fallback 
resources, and the argument is fallback resources. 
-- 

D.2.2 Varargs Interfaces 

All Xt interfaces that require ArgList arguments now have analogs which conform to the 
ANSI C variable-length argument list ("varargs") calling convention. The name of the analog 
is formed by prefixing "Va" to the name of the corresponding ArgList procedure. For 
example, the varargs version of XtCreateWidget is XtVaCreateWidget. Each pro- 
cedure whose name starts with xtva takes as its last arguments, in place of the correspond- 
ing ArgList/Cardinal parameters, a variable-length parameter list of resource name 
and value pairs where each name is of type String and each value is of type XtArgVal. 
The end of the list is identified by a name entry containing NULL. The ArgList and varargs 
interfaces may be used interchangeably within the same application. Table D-1 shows the 
ArgList functions and the analogous varargs functions: 

Table D-1. ArgList Functions and Varargs Counterparts 

ArgList 

XtAppCreateShell 
XtAppInitialize 
XtCreatePopupShell 
XtCreateManagedWidget 
XtCreateWidget 
XtGetApplicationResources 
XtGetSubresources 
XtGetSubvalues 
XtGetValues 

Varargs 

XtVaAppCreateShell 
XtVaAppInitialize 
XtVaCreatePopupShell 
XtVaCreateManagedWidget 
XtVaCreateWidget 
XtVaGetApplicationResources 
XtVaGetSubresources. 
XtVaGetSubvalues 
XtVaGetValues 

470 X Toolkit Intrinsics Programming Manual 



Tab D-1. ALt Functions and Varas Counas (continue 
ArgList Varargs 
XtSetSubvalues XtVaSetSubvalues 
XtSetValues XtVaSetValues 

D.2.2.1 

Special Types for Varargs List Members 

Two special symbols are defined for use only in varargs lists: XtVaTypedArg and Xt- 
VaNestedList. Each can be used in place of a resource name to indicate that the follow- 
ing fields should be treated differently than a normal resource value. XtVaTypedArg 
allows you to use the subsequent four arguments to instruct Xt how to invoke the proper type 
converter to convert the given value into the type required by the widget. To use Xt- 
VaTypedArg while creating the first instance of a widget class, however, you must call 
Xt InitializeWidgetClas s first. 
XtVaNestedList lets you include an ArgList in a varargs list. This is normally done 
to include the same list of resource settings in several calls to create widgets. Xt- 
VaCreateArgsList dynamically allocates a varargs list, for use with XtVaNested- 
List in multiple calls. 
For more information on XtVaTypedArg and XtVaNestedList, see Chapter 3, More 
Techniques for Using Widgets. 

D.2.3 

D.2.3.1 

Loading the Resource Database 

There have been several extensions in the way the resource database is loaded. 

The Language String 

In R4, a mechanism for making applications portable between languages is introduced. It 
allows the application writer to create separate app-defaults files for each language. Each of 
these files will have the same name, but they will have different paths. A language string 
determines the path.* In other words, Xt will look for the app-defaults file in 
/usr/lib/X11/LANG/app-defaults before it looks in/usr/lib/X11/app-defaults. This is done for 
both the application's app-defaults file and the user's XAPPLRESDIR file. For details on the 
exact order of searching and merging for resource files, see Chapter 9, Resource Manage- 
ment and Type Conversion. 

*This mechanism conforms to the X/Open Portability Guide language localization conventions. 

Appendix D: Release Notes 4 71 



an application name to be used in extracting applicable resource specifications from the 
resource database. If RESOURCE_NAME is not set, the final component of a rgv [ 0 ] is 
used. If a rgv [ 0 ] does not exist or is the empty string, the application name is "main". 

D.3 Changes Affecting Both Application and Widget Writing 

D.3.1 Actions 

Several new functions associated with actions have been defined. 

D.3.1.1 

D.3.1.2 

D.3.1.3 

Directly Invoking Actions 

Normally, action procedures are invoked by the Intrinsics when an event or event sequence 
arrives for a widget. Occasionally it may be desirable to invoke an action procedure directly, 
without generating (or synthesizing) an event. One such circumstance is an application or 
subclass action routine which envelopes an existing (superclass) action routine. XtCall- 
ActionProc can be used to do this. XtCallActionProc is also useful for playing 
back actions recorded with XtAppAddAct i onHook. 

Action Hook Registration 

An application can use XtAppAddActionHook to specify a procedure that will be called 
just before every action routine is dispatched by the translation manager. 
Action hooks should not modify any of the data pointed to by the arguments other than the 
cl i en t_da t a argument. 
XtRemoveActionHook removes an action hook procedure. (Notice that the XtApp- 
AddActionHook takes an application context argument, which XtRemoveAction- 
Hook doesn't, thus the asymmetry in their names.) 

Obtaining Event Information in an Action Procedure 

When an action procedure is invoked on a KeyPress or KeyRelease event, it often 
needs the keysym and modifiers corresponding to the event which caused it to be invoked, 
since the event passed in the action procedure contains only the keycode. In order to avoid 
repeating the processing that was just performed by the Intrinsics to match the translation 
entry, the keysym and modifiers are stored for the duration of the action procedure and are 
made available to the client with XtGetActionKeysym. XtGetActionKeysym 
retrieves the keysym and modifiers that matched the final event specification in the transla- 
tion table entry. 

Appendix D: Release Notes 473 



D.3.1.4 Registering Button and Key Grabs For Actions 

D.3.1.5 

XtRegisterGrabAction registers a grab that will be initiated when the given action is 
invoked in response to KeyPress or ButtonPress events. This function is used inter- 
nally by Xt to register the grab for the XtMenuPopup action. 

Action Functions and Unrealized Widgets 

Action procedures may not assume that the widget in which they are invoked is realized; an 
accelerator specification can cause an action procedure to be called for a widget which does 
not yet have a window. Widget writers should note which of a widget's callback lists are 
invoked from action procedures and warn clients not to assume the widget is realized in those 
callbacks. (This is newly documented but also true of R3.) 

D.3.2 

Reserved Names for Resources and Actions 

Resource names beginning with the two-character sequence "xt" and resource classes begin- 
ning with the two-character sequence "Xt" are reserved to the Intrinsics for implementation- 
dependent uses. Consequently, all symbols beginning with XtNxt and xtcxt are reserved. 
The Intrinsics reserve all action names and parameters starting with the characters "Xt" for 
future standard enhancements. Users, application and widgets should not declare action 
names or pass parameters starting with these characters except to invoke specified built-in 
functions. 
In general, applications should not declare or define anything beginning with Xt in any case, 
since these are generally associated with the Xt standard and could conflict or be confusing. 

D.3.3 

Resource String Identifier Convention 

Definitions of XtN, XtC, and XtR constants should have just a single space between the sym- 
bol and the value, and no comment. This prevents preprocessor warnings from multiple, 
slightly different definitions for the same symbol. 

D.3.4 

Resource File Format 

As of R4, the resource file format is defined in the Xlib specification instead of by Xt, and the 
following was added: To include arbilxary octets in a string, use the 4-character sequence 
"nnn" where nnn is the numeric value of the octet specified as an octal constant. For 
example, a value containing a NULL byte may be stored by including "\000" in the string. 
This is one way to specify ISO-Latinl strings that are above the 128 ASCII characters--these 
strings are needed for Western languages other than English. 

474 X Toolkit Intrinsics Programming Manual 



D.3.5 Modifier Names 

If both an exclamation point (!) and a colon (:) are specified at the beginning of the modifier 
list, it means that the listed modifiers must be in the correct state and that no other modifiers 
except the standard modifiers can be asserted. Any standard modifiers in the event are 
applied as for colon (:) above. 

D.3.6 

Determining Specification Revision Level 

Widget and application developers who wish to maintain a common source pool which will 
build properly with implementations of the Intrinsics at different revision levels of the Xt 
specification may use the symbolic macro XtSpecificationRelease. 

Since XtSpecificationRelease is new to Release 4, widgets and applications desir- 
ing to build against earlier implementations should test for the presence of this symbol and 
assume only Release 3 interfaces if the definition is not present. 

D.3.7 

Implementation-specific Datatype Definitions 

To increase the portability of widget and application source code between different system 
environments, Xt defines several datatypes whose precise representation is explicitly depen- 
dent upon, and chosen by, each individual implementation. For best portability, applications 
must only depend on the data type characteristics listed here. These characteristics were not 
documented until Release 4. 
These implementation-defined datatypes are: 
Boolean A datum that contains a zero or non-zero value. Unless explicitly stated, 
clients should not assume that the non-zero value is equal to the symbolic 
value True. 
Cardinal An unsigned datum with a minimum range of [0..T16-1]. 
Dimension An unsigned datum with a minimum range of [0..T16-1]. 
Position A signed datum with a minimum range of [-2^15..2^15-1]. 
XtPointer A datum large enough to containa char*, int*, function pointer, struc- 
ture pointer, or long value. A pointer to any type or function, or a long 
value, may be converted to an xtPointer and back again and the result 
will compare equally to the original value. In ANSI C environments it is 
expected that xtPointer will be defined as void*. 
XtArgVal A datum large enough to contain an XtPointer, Cardinal, Dimen- 
sion, or Position value. 
XtEnum A datum large enough to encode at least 128 distinct values, two of which 
are the symbolic values True and False. The symbolic values TRUE 
and FALSE are also defined to be equal to True and False, respectively. 

Appendix D: Release Notes 475 



D.3.8 Event Handlers 

Event handlers now have an additional final argument, continue_to_dispatch. This 
argument specifies whether or not the remaining event handlers registered for the current 
event should be called. This feature should be used with care. 

XtInsertEventHandler registers an event handler procedure before or after all previ- 
ously registered event handlers. 

XtInsertRawEventHandler registers an event handler procedure that receives events 
before or after all previously registered event handlers without selecting for the events. 

D.3.9 

Error and Warning Handlers 

The routines that install error and warning handlers now return the previous handlers. 

D.4 

Changes Affecting Widget Writing 

The Xt specification has undergone several sets of revisions in the course of adoption as an X 
Consortium standard specification. The Release 3 specification was the first X Consortium 
standard for Xt. Release 4 and future releases will have complete source compatibility with 
widgets and applications written to previous Consortium standard revisions. 
The Intdnsics do not place any special requirement on widget programmers to retain source 
or binary compatibility for their widgets as they evolve, but several conventions have been 
established to assist those developers who want to provide such compatibility. In particular, 
widget programmers may wish to define class extension records, as described in Section 
13.13. 

D.4.1 New Name for Core Class 

Prior to R4, the official name of the Core class was WidgetClass. An alias has been 
added to allow the Core widget to be referenced using the name CorewidgetClass, 
which makes its naming parallel with all other classes. Similarly, all other symbols that ref- 
erence Core class structures also have analogous aliases, as shown in Table D-2. 

Table D-2. New Naming for Core Class Symbols and Variables 

Existing Symbol 

CoreClassSucmre 
WidgetClassRec 
*WidgetClass 
widgetClassRec 
widgetClass 

Added Symbol 

CoreClassRec 
*CoreWidgetClass 
coreClassRec 
coreWidgetClass 

476 X Toolkit Intrinsics Programming Manual 



D.4.3.2 

The accepts objects field allows Xt to check to make sure that the composite parent is 
-- 
capable of managing the type of child being created. If not, a fatal error occurs. Note that a 
fatal error also occurs if no composite extension record is defined. 

Constraint Class Extension Structure 

The extension record defined for Constlaint is as follows: 

typedef struct { 
XtPointer next extension; 
-- 
XrmQuark record_type; 
long version; 
Cardinal record size; 
XtArgsProc get_Qalues_hook; 
} ConstraintClassExtensionRec, *ConstraintClassExtension; 

The record_type should be initialized to NULLQUARK. The version field should be 
initialized to XtConstraintExtensionVersion. 

D.4.3.3 

D.4.3.4 

New Constraint get_values_hook method 

If the Consxaint widget or any of its superclasses have declared a ConstraintClass- 
Extension record in the constraint class part extension fields with a record type of 
NULLQUARK and the get_values_hook field in the extension record is nOn-NULL, Xt- 
GetValues calls this get_values_hook method to allow the parent to return derived 
consaint fields. The Consaint get_values_hook method is for processing the 
resources of subparts. 
The Constlaint extension get_values_hook method is called after the Core 
get_values_ hook methods are called. 

Shell Class Extension Structure 

The extension record defined for Consllaint is as follows: 
. 
typede f struct 
XtPointer next extension; 
_ 
XrmQuark record_type ; 
long version; 
Cardinal record size; 
-- 
XtGeometryHandler root_geometry_manager; 
} ShellClassExtensionRec, *ShellClassExtension; 
The symbolic constant for the ShellClassExtension version id is XtShell- 
ExtensionVersion. 
The root_geometry_manager field specifies a procedure which acts as the parent ge- 
ometry manager for geometry requests made by shell widgets. When a shell widget calls 
XtMakeGeometryRequest or XtMakeResizeRequest, the root_geometry 
--manager procedure is invoked to negotiate the new geometry with the window manager. 
If the window manager permits the new geometry, the root_geometry_manager 
should return XtGeometryYes; if the window manager denies the geometry request or 

Appendix D: Release Notes 4 79 



D.4.7.3 New Routine to Call Callback List 

XtCallCallbackList executes the procedures in a callback list, specifying the call- 
back list by address. In other words, the function calls all the procedures on the callback list 
without reference to the widget those callback functions are registered for. This function 
avoids the callback list lookup overhead. 

D.4.8 

D.4.8.1 

D.4.8.2 

Resource Lists 

XtOffsetOf determines the byte offset of a field within a structure type. It performs the 
same function as xtoffset, but is more portable. 

Base Offsets In Resource LIst 

XtWidgetBaseOffset has been added as an address mode which can be used in 
resource lists. XtWidgetBaseOffset is similar to XtBaseOffset except that it 
searches for the closest windowed ancestor if the object is not a subclass of Core. 

XtProcedureArg 

In the field usually specified as XtBaseOffset, you can specify XtProcedureArg 
instead. This instructs Xt to call a procedure of type XtConvertArgProc tO get the 
resource value. 

D.4.8.3 

D.4.8.4 

Default Resource Values 

The default_address field in each resource list element specifies the address of the 
default resource value. As a special case, if the default_type is XtRString, then the 
value in the default_addr field is the pointer to the string rather than a pointer to the 
pointer. 

Getting a Constraint Resource List 

XtGetConstraintResourceList gets the constraint resource list structure for a wid- 
get class. 

482 X Toolkit Intrinsics Programming Manual 



D.4.9 Converters 

D.4.9.1 

New Xt Resource Representations 

The following resource representation types are now defined by the Intrinsics. 

Table D-3. New Representation Types 

Resource Type 

XtRBitmap 
XtRGeometry 
XtRInitialState 
XtRLongBoolean 
XtRObject 
XtRStringTable 
XtRVisual 

Structure or Field Type 

Pixmap, depth=l 
char*,nn as definedby XParseGeometry 
int 
long 
Object 
char** 
Visual* 

D.4.9.2 

<X111StringDefs.h> now defines the following resource types as a convenience for widgets, 
although they do not have any corresponding datatype assigned: XtREditMode, Xt- 
RJustify and XtROrientation. 

New Xt Resource Converters 

Xt now defines conveners from XtRString tO XtRInitialState, from XtRString 
tO XtRVisual, and from XtRString tO XtRAtom. 
The XtRString tO XtRInitialState conversion accep the values NormalState 
or I conicState as defined by the Inter-Client Communications ConvenOons. 
The XtRString to XtRVisual conversion calls XMatchVisualInfo using the Xt- 
Nscreen and XtNdepth resources and returns the first mashing visual on the list. 
The widget resource list must be certain to specify any resource of type XtRVisual after 
the depth resource. The allowed string values are the Protocol visual class names: 
StaticGray, StaticColor, TrueColor, GrayScale, PseudoColor, and 
DirectColor. 
The string to font and font structure conveners no longer evaluate the constant Xt- 
DefaultFont tO the font in the screen's default graphics context. Instead, they do the fol- 
lowing: 
1. Query the resource database for the resource whose full name is "xtDefaultFont", class 
"XtDefaultFont" (that is, no widget name/class prefixes) and use a type XtRString 
value returned as the font name, or a type XtRFont or XtRFontStruct value 
directly as the resource value. 
2. If the resource database does not contain a value for xtDefaultFont, class XtDefaultFont, 
or if the returned font name cannot be successfully opened, an implementation-defined 
font in ISO8859-1 character set encoding is opened. (One possible algorithm is to 

Appendix D: Release Notes 483 



form an XListFonts using a wildcard font name and use the first font in the list. This 
wildcard font name should be as broad as possible to maximize the probability of locating 
a usable font; for example, "-*-*-*-R-*-*-*- 120-*-*-*-*-ISO8859-1".) 

3. If no suitable ISO8859-1 font can be found, issue an error message. 

D.4.9.3 

D.4.9.4 

New Fn for Issuing Conversion Warnings 

XtDisplayStringConversionWarning supercedes XtStringConversion- 
Warning as the convenience routine for resource converters that convert from string values. 

New Resource Converters Interface 

A new interface declaration for resource type converters was defined to provide more infor- 
mation to converters, to support conversion cache cleanup with reference counting, and to al- 
low additional procedures to be declared to free resource values. The old interfaces remain 
(for backwards compatibility) and a new set of procedures was defined which work only with 
the new type converter interface. 

D.4.9.4.1 

Registering a Resource Converter. To register a new converter for all application con- 
texts in a process, use XtSetTypeConverter. To register a new converter in a single 
application context, use XtAppSetTypeConverter. XtAddConverter and Xt- 
AppAddConverter are superceded by these new routines. The new routines provide a 
cache_type argument that specifies when and how conversions made with this converter 
should be cached. Another argument specifies a procedure, called a destructor, that will be 
called to free resource values when the reference count reaches zero. 

D.4.9.4.2 

XtDestructor functions. To allow the Innsics to free cached resource values produced 
by type converters when widgets are destroyed or displays are closed, you may provide a re- 
source destructor procedure. You register one in the call that registers the new-style type 
converter. 

D.4.9.4.3 

New Resource Converter Procedure Type. A resource converter procedure pointer is 
now of type XtTypeConverter. In R3 it was XtConverter. XtTypeConvert has 
two new arguments, display, and converter data. The converter data field 
specifies a location into which the converter may store converter-specific data that is associ- 
ated with this conversion. 

Any converter that queries the server to get the conversion should use the di splay argu- 
ment to specify which server to query. For example, the XtRString tO XtRPixel con- 
vert uses its display argument in the XAllocColor Xlib call it makes. The display 

484 X Toolkit Intrinsics Programming Manual 



D.4.10 Keyboard Handling 

D.4.10.1 

D.4.10.2 

KeyCode-to-KeySym Conversions 

The Intrinsics maintain tables internally to map keycodes to keysyms for each open display. 
Translator procedures and any other client may share a single copy of this table to perform 
the same mapping. 
XtGetKeysymTable returns a pointer to the keycode to keysym mapping table for a par- 
ticular display. 

KeySym-to-KeyCode Conversions 

XtKeysymToKeycodeList returns the list of keycodes that map to a particular keysym 
in the keyboard mapping table maintained by the Inlrinsics. 

D.4.11 

Selections 

Selection requests for the TIMESTAMP target are now answered automatically by Xt. 
Also, XtGetSelectionRequest has been added. XtGetSelectionRequest 
retrieves the SelectionRequest event which triggered the convert_selection 
procedure. This is necessary for some ICCCM target types. XtGetSelectionRequest 
may only be called from within a convert_selection procedure. 
A whole set of routines for incremental transfers have been added. An incremental transfer is 
just like an atomic transfer, except that the functions you write to convert and get the data 
must expect to be called multiple times for the same selection. The basic three functions that 
parallel the functions provided for atomic transfers are xtOwnSelection- 
Incremental, XtGetSelectionValueIncremental, and XtGetSelection- 
Values Incremental. The function types registered with these three basic functions are 
XtConvert SelectionIncrP roc, XtLoseSelectionIncrP roc, Xt- 
SelectionDoneIncrP roc, XtCancelConvert SelectionP roc, Xt- 
SelectionIncrCallbackProc, and XtCancelSelectionCallbackProc. 
XtLastTimestampProcessed retrieves the timestamp from the most recent call to 
XtDispatchEvent which contained a timestamp. (XtDispatchEvent records the 
last timestamp in any event which contains a timestamp.) 

D.4.12 Objects 

Although widget writers are free to treat Core as the base class of the widget hierarchy, there 
are actually three classes above it. These classes are Object, RectObj (Rectangle Object), 
and the un-named class. All of these classes, their subclasses and all widgets are referred to 
generically as objects. By convention, the term widget refers only to a direct subclass of 
Core and the term gadget refers to a direct subclass of RectObj. A direct subclass of Object 

486 X Toolkit Intrinsics Programming Manual 



D.4.12.2 Xt Functions that take any Object 

In R3, all functions which had an argument of type Widget or widgetClass could ac- 
cept any class of widget. Now that objects have been implemented, this is no longer true. 
The following lists describe what classes are valid in all Xt functions that accept widget or 
widget class arguments or that return such values. 
The WidgetClass arguments to the f0Howg procedures may be objectClass or any 
subclass: 

XtCheckSubclass 
XtCreateWidget 
XtGetConstraintResourceList 
XtGetResourceList 

XtInitializeWidgetClass 
XtIsSubclass 
XtVaCreateWidget 

The Widget arguments to the following procedures can be of class Object or any subclass: 

XtAddCallback 
XtAddCallbacks 
XtCallCallbacks 
XtCheckSubclass 
XtClass 
XtConvert 
XtConvertAndStore 
XtCreateWidget 
XtDestroyWidget 
XtDisplayOfObject 
XtGetApplicationResources 
XtGetGC 
XtGetSubresources 
XtGetSubvalues 
XtGetValues 
XtHasCallbacks 
XtIsApplicationShell 
XtIsComposite 
XtIsConstraint, 
XtIsManaged emmsFalseif 
notRectObjorsubclass) 
XtIsObject 
XtIsOverrideShell 
XtIsRealized emms esmteof 
eneestwdowedancestor) 
XtIsRectObj 
XtIsSensitive(remmsFalse 
if not RectO or subclass) 

XtIsShell 
XtIsSubclass 
XtIsToplevelShell 
XtIsTransientShell 
XtIsVendorShell 
XtIsWidget 
XtIsWMShell 
XtName 
XtNameToWidget 
XtReleaseGC 
XtRemoveAllCallbacks 
XtRemoveCallback 
XtRemoveCallbacks 
XtScreenOfObject 
XtSetKeyboardFocus (descendant) 
XtSetValues 
XtSuperclass 
XtVaCreateWidget 
XtVaGetApplicationResources 
XtVaGetSubresources 

XtVaGetSubvalues 
XtVaGetValues 
XtVaSetValues 

XtWidgetToApplicationContext 
XtWindowOfObject 

488 X Toolkit Intrinsics Programming Manual 



D.4.12.3 

D.4.12.4 

The return value of these procedures will be of class Object or a subclass: 

XtCreateWidget 
XtVaCreateWidget 
XtParent 
XtNameToWidget 
The return value of these procedures will be oectChss or a subclass: XtClass, xt- 
Superclass. 

Xt Functions that take any RectObj 

The WidgetClass arguments to the llowing procedures may berectObjClass or any 
subclass: XtCreateManagedWidget, XtVaCreateManagedWidget. 

The Widget arguments to the following procedures can be of class RectObj or any sub- 

class: 

XtConfigureWidget 
XtMakeGeometryRequest 
XtMakeResizeRequest 
XtManageChild 
XtManageChildren 
XtMoveWidget 

XtQueryGeometry 
XtResizeWidget 
XtSetSensitive 
XtTranslateCoords 
XtUnmanageChild 
XtUnmanageChildren 

Thereturnvalue ofthe llowing procedures will beofclass RtO orasubclass:xt- 
CreateManagedWidget,XtVaCreateManagedWidget. 

Xt Functions that take any Core 

The Widget arguments to the following procedures must be of class Core or any subclass: 

XtAddEventHandler 
XtAddGrab 

XtAddRawEventHandler 
XtAugmentTranslations 
XtBuildEventMask 
XtCallAcceptFocus 
XtCallActionProc 
XtCreatePopupShell 
XtCreateWindow 
XtDisownSelection 
XtDisplay 
XtGetSelectionRequest 
XtGetSelectionValue 
XtGetSelectionValueIncremental 
XtGetSelectionValues 
XtGetSelectionValuesIncremental 
XtGrabButton 

XtInstallAccelerators 
XtInstallAllAccelerators (bo 
destinafionandsource) 
XtMapWidget 
XtOverrideTranslations 
XtOwnSelection 
XtRealizeWidget 
XtRemoveEventHandler 
XtRemoveGrab 
XtRemoveRawEventHandler 
XtResizeWindow 
XtScreen 
XtSetKeyboardFocus (subtree) 
XtSetMappedWhenManaged 
XtSetWMColormapWindows 
XtUngrabButton 
XtUngrabKey 
XtUngrabKeyboard 

Appendix D: Release Notes 489 



D.4.12.5 

D.4.12.6 

XtGrabKey 
XtGrabKeyboard 
XtGrabPointer 
XtlnsertEventHandler 
XtlnsertRawEventHandler 
XtWindow 

XtUngrabPointer 
XtUninstallTranslations 
XtUnmapHidget 
XtUnrealizeWidget 
XtVaCreatePopupShell 

The turnvalue ofthe llowing procede wibeofclass Core or a subclass: Xt- 
WindowToWidget. 

Xt Functions that take any Composite 

The Widget arguments to the owing procedes must beofclassComposi or anysub- 
class: XtCreateManagedWidget, XtVaCreateManagedWidget. 

Xt Functions that take any Shell or a Subclass 

TheWidgetClass argumentsto the owingprocedures must beofclassShellorasub- 
class: XtCreatePopupShell, XtVaCreatePopupShell, XtAppCreateShell. 

The Widget arguments to the following procedures must be of a subclass of Shell: 

XtCallbackExclusiv 
XtllbackNone 
XCallbackNonexclusive 
XtCallbackPpdown 

XtPopdown 
XtPopup 
XtPopupSpringLoaded 

The return value of the following procedures will be of a subclass of Shell: 

XtAppCreateShell 
XtApplnitialize 
XtCreatePopupShell 
XtVaCreatePopupShell 

D.4.12.7 

Macros for Getting Object Information 

The display pointer, screen pointer and window of a widget or of the closest widget ancestor 
of a gadget are available by calling XtDisplayOfObject, XtScreenOfObject, and 
XtWindowOfObject. XtIsObject tells you whether a class is a subclass of Object 
but not of RectObj. 

XtName returns a pointer to the instance name of the specified object. The name does not 
include the names of any of the object's ancestors. 

490 X Toolkit Intrinsics Programming Manual 



D.4.13 Miscellaneous 

D.4.13.1 

D.4.13.2 

XtNameToWidget 

XtNameToWidget now allows an asterisk (*) to separate widget names, to match any 
number of intermediate widgets. The method whereby XtNameToWidget searches the hi- 
erarchy for a matching widget has been more carefully spelled out: see XtNameToWidget 
in Volume Five, X Toolkit Intrinsics Reference Manual. 

New Exposure Compression Controls 

The compress__exposure field of the Core structure can now be set to additional values 
to tailor the exposure compression for a particular widget. The four basic values are shown 
in Table D-4. 

Table D-4. Flags for compress_exposure Field of Core Class Structure 

Symbol 

XtExposeCompressMaximal 

XtExposeCompressMultiple 

XtExposeCompressSeries 

XtExposeNoCompress 

Description 

All expose series currently in the queue are co- 
alesced into a single event without regard to inter- 
vening nonexposure events. If a partial series is in 
the end of the queue, the Intrinsics will block until 
the end of the series is received. This setting is not 
advised, since ConfigureNotify events may be 
between Expose event series. 
Consecutive series of exposure events are coalesced 
into a single event when an exposure event with 
count--0 is reached and either the event queue is 
empty or the next event is not an exposure event. 
Each series of exposure events is coalesced into a 
single event when an exposure event with 
count==0 is reached. 

No exposure compression is performed; every select- 
ed event is individually dispatched to the expose pro- 
cedure, with a region argument of NUr,r,. 

Note that the first two values are different names for the settings available under R3, False 
and True respectively. The most useful value is XtExposeCompressMultiple. Any 
of the above values can be optionally ORed with any combination of the following flags (all 
i mplemen tad on -defined): 

Appendix D: Release Notes 491 



Table D-5. Optional OR Flags for compress._exposure Field of Core Class Structure 

Symbol 

XtExposeGraphicsExpose 

XtExposeGraphicsExposeMerged 

XtExposeNoExpose 

Description 

Specifies that GraphicsExpose events 
are zlso to be dispatched to the expose 
method. GraphicsExpose events will 
be compressed, if specified, in the same 
manner as Expose events. 
Specifies in the case of xt Ex- 
poseCompressMultiple and XtEx- 
poseCompressMaximal that sedes of 
GraphicsExpose and Expose events 
are to be compressed together, with the final 
event type determining the type of the event 
passed to the expose procedure. If this flag 
is not set, then only series of the same event 
type as the event at the head of the queue 
are coalesced. This flag also implies 
Xt ExposeGraphicsExpose. 
Specifies that NoExpose events are also to 
be dispatched to the expose procedure. 
NoExpose events are never coalesced 
with other exposure events, nor with each 
other. 

D.4.13.3 

Requesting Key and Button Grabs 

Xt now provides a set of key and button grab interfaces that are parallel to those provided by 
Xlib. Toolkit applications and widgets that need to passively grab keys or buttons should use 
the following Intrinsics routines rather than the corresponding Xlib routines. 
The new Xt routines are: XtGrabKey, XtUngrabKey, XtGrabKeyboard, Xt- 
UngrabKeyboard, XtGrabButton, XtUngrabButton, XtGrabPointer, and 
XtUngrabPointer. 
Remember that these routines are interfaces to Xlib grab routines: they are not the same as 
the Xt grab mode which affects only the dispatching of events within your application. 
To affect dispatching of events outside of your application, in R3 you needed to make a Xlib 
call to grab the pointer, or use MenuPopup, the standard action that made the grab for you 
(which is now also called XtMenuPopup). Given the new R4 grab routines, you can pop- 
up a menu using any of the pop-up mechanisms (xtPopup, XtPopupSpringLoaded, 
XtCallbackExclusive, XtCallbackNonexclusive, or XtCallbackNone) 

492 X Toolkit Intrinsics Programming Manual 



E 

The xbitmap Application 

This appendix shows the complete code for all versions of xbitmap, which is 
described in Chapters 4 and 5. 

In This Chapter: 

The BitmapEdit Widget ...................................................................... 497 
The BitmapEdiP.h Private Header File ............................................... 510 
The BitmapEdit.h Public Header File .................................................. 511 
xbitmap8 ............................................................................................ 513 



E 
The xbitmap Application 

This appendix shows the complete code for the BitmapEdit widget (without selections), and 
the complete code for an advanced version of the xbitmap application (xbitmap8 in the 
example distribution) which is similar to xbitmap3 described in Chapter 4 except that it both 
reads and writes X11 bitmap files (xbitmap3 was capable of writing them only). 

All source code from this book is available flee from numerous sources, as described in the 

Preface. 

E.1 

The BitmapEdit Widget 

Examp E- 1. BitmapEdit: comp widget code 
/. 
* BitmapEdit.c - bitmap editor widget. 
*/ 
#include <Xll/IntrinsicP.h> 
#include <Xll/StringDefs.h> 
#include <stdio.h> 
#include "BitmapEdP.b" 
#define INTERNAL WIDTH 2 
#define INTERNAL HEIGHT 4 
#define DEFAULT PIXMAP WIDTH 
#define DEFAULT PIXMAP HEIGHT 
#define DEFAULT CELL SIZE 30 
/* values for instance variable is drawn */ 
#define DRAWN 1 
#define UNDRAWN 0 
/* modes for drawing */ 
#define DRAW 1 
#define UNDRAW 0 
#define MAXLINES 1000 
#define SCROLLBARWIDTH 15 
#define DEFAULTWIDTH 300 

32 /* in cells */ 
32 /* in cells */ 

/* in pixels */ 

/* max of horiz or vertical cells */ 

/* widget size when showAll is False */ 

Appendix E: The xbitmap Application 497 



Example E-1. BitmapEdit: complete widget code (continued) 

#define offset (field) XtOffset (BitmapEditWidget, field) 
static XtResource resources[] = { 
{ 
XtNforeground, 
XtCForeground, 
XtRPixel, 
sizeof(Pixel), 
offset(bitmapEdit.foreground), 
XtRString, 
XtDefaultForeground 
), 
{ 
XtNcallback, 
XtCCallback, 
XtRCallback, 
sizeof(XtPointer), 
offset(bitmapEdit.callback), 
XtRCallback, 
NULL 
}, 
{ 
XtNcellSizeInPixels, 
XtCCellSizeInPixels, 
XtRInt, sizeof(int), 
offset(bitmapEdit.cell_size in pixels), 
XtRImmediate, 
(XtPointer)DEFAULT CELL SIZE 
), 
{ 
XtNpixmapWidthInCells, 
XtCPixmapWidthInCells, 
XtRDimension, 
sizeof(Dimension), 
offset(bitmapEdit.pixmap_width_in_cells), 
XtRImmediate, 
(XtPointer) DEFAULT PIXMAP WIDTH 
}, 
{ 
XtNpixmapHeightInCells, 
XtCPixmapHeightInCells, 
XtRDimension, 
sizeof(Dimension), 
offset(bitmapEdit.pixmap_height in cells), 
XtRImmediate, 
(XtPointer)DEFAULT PIXMAP HEIGHT 
}, 
{ 
XtNcurX, 
XtCCurX, 
XtRInt, 
sizeof(int), 
offset(bitmapEdit.cur_x), 
XtRImmediate, 
(XtPointer) 0 
}, 

498 

X Toolkit Intrinsics Programming Manual 



Examp E-1. BitmapEdit: comp widget code Continued) 
( 
XtNcurY, 
XtCCurY, 
XtRInt, 
sizeof(int), 
offset(bitmapEdit.cur_y), 
XtRString, 
(XtPointer) NULL 
}, 
{ 
XtNcellArray, 
XtCCellArray, 
XtRString, 
sizeof(String), 
offset(bitmapEdit.cell), 
XtRImmediate, 
(XtPointer) 0 
}, 
{ 
XtNshowEntireBitmap, 
XtCShowEntireBitmap, 
XtRBoolean, 
sizeof(Boolean), 
offset(bitmapEdit.showAll), 
XtRImmediate, 
(XtPointer) TRUE 
}, 
); 
/* Declaration of methods */ 
static void Initialize(); 
static void Redisplay(); 
static void Destroy(); 
static void Resize(); 
static Boolean SetValues(); 
static XtGeometryResult QueryGeometry(); 
/* these Core methods not needed by BitmapEdit: 
* static void ClassInitialize(); 
* static void Realize(); 
*/ 
/* the following are private functions unique to BitmapEdit */ 
static void DrawPixmaps(), DoCell(), ChangeCellSize(); 
/* the following are actions of BitmapEdit */ 
static void DrawCell(), UndrawCell(), ToggleCell(); 
/* The following are public functions of BitmapEdit, declared extern 
* in the public include file: */ 
char *BitmapEditGetArrayString(); 
static char defaultTranslations[] = 
<BtnlDown>: DrawCell() \n\ 
<Btn2Down>: UndrawCell() \n\ 
<Btn3Down>: ToggleCell() \n\ 
<BtnlMotion>: DrawCell() \n\ 

Appendix E: The xbitmap Application 499 



:::i:::i Example E-1. BitmapEdit: complete widget code (continued) 
.-. 

:-:: <Btn2Motion>: UndrawCell() \n\ 
<Btn3Motion>: ToggleCell()"; 

static XtActionsRec actions[] = { 
{"DrawCell", DrawCell}, 
{"UndrawCell", UndrawCell}, 
{"ToggleCell", ToggleCell}, 
}; 

/* definition in BitmapEdit.h */ 
static BitmapEditPointInfo info; 

BitmapEditClassRec bitmapEditCl 

assRec = { 

}; 

{ 
/* core class fields */ 
-- 
/* superclass */ (WidgetClass) &coreClassRec, 
/* class_name */ "BitmapEdit", 
/* widget_size */ sizeof(BitmapEditRec), 
/* class initialize */ NULL, 
-- 
/* class_part_initialize */ NULL, 
/* class_inited */ FALSE, 
/* initialize */ Initialize, 
/* initialize hook */ NULL, 
-- 
/* realize */ XtInheritRealize, 
/* actions */ actions, 
/* num_actions */ XtNumber(actions), 
/* resources */ resources, 
/* num_resources */ XtNumber(resources), 
/* xrm_class */ NULLQUARK, 
/* compress_motion */ TRUE, 
/* compress_exposure */ XtExposeCompressMultiple, 
/* compress_enterleave */ TRUE, 
/* visible_interest */ FALSE, 
/* destroy */ Destroy, 
/* resize */ Resize, 
/* expose */ Redisplay, 
/* set_values */ SetValues, 
/* set_values_hook */ NULL, 
/* set_values_almost */ XtInheritSetValuesAlmost, 
/* get_values_hook */ NULL, 
/* accept_focus */ NULL, 
/* version */ XtVersion, 
/* callback_private */ NULL, 
/* tm_table */ defaultTranslations, 
/* query_geometry */ QueryGeometry, 
/* display_accelerator */ XtInheritDisplayAccelerator, 
/* extension */ NULL 
}, 
{ 
/* dummy_field */ 0, 
}, 

WidgetClass bitmapEditWidgetClass = (WidgetClass) & bitmapEditClassRec; 
static void 
GetDrawGC(w) 
Widget w; 

500 X Toolkit Intrinsics Programming Manual 



Examp E-1. B#mapEdit: comp widget code Continued) 
{ 
BitmapEditWidget cw = (BitmapEditWidget) w; 
XGCValues values; 
XtGCMask mask = GCForeground  GCBackground I GCDashOffset 
 GCDashList I GCLineStyle; 
/* 
* Setting foreground and background to 1 and 0 looks like a 
* kludge but isn't. This GC is used for drawing 
* into a pixmap of depth one. Real colors are applied with a 
* separate GC when the pixmap is copied into the window. 
*/ 
values.foreground = i; 
values.background = 0; 
values.dashes = i; 
values.dash offset = 0; 
values.line_style = LineOnOffDash; 
cw->bitmapEdit.draw_gc = XCreateGC(XtDisplay(cw), 
cw->bitmapEdit.big_picture, mask, &values); 
static void 
GetUndrawGC(w) 
Widget w; 
{ 
BitmapEditWidget cw = (BitmapEditWidget) w; 
XGCValues values; 
XtGCMask mask = GCForeground I GCBackground; 
/* this looks like a kludge but isn't. This GC is used for drawing 
* into a pixmap of depth one. Real colors are applied as the 
* pixmap is copied into the window. 
*/ 
values.foreground = 0; 
values.background = I; 
cw->bitmapEdit.undraw_gc = XCreateGC(XtDisplay(cw), 
cw->bitmapEdit.big_picture, mask, &values); 
} 

static void 
GetCopyGC(w) 
Widget w; 
{ 

BitmapEditWidget cw = (BitmapEditWidget) w; 
XGCValues values; 
XtGCMask mask = GCForeground  GCBackground; 

values.foreground = cw->bitmapEdit.foreground; 
values.background = cw->core.background_pixel; 
cw->bitmapEdit.copy_gc = XtGetGC(cw, mask, &values); 

/* ARGSUSED */ 
static void 
Initialize(treq, tnew) 
Widget treq, tnew; 
{ 

Appendix E: The xbitmap Application 501 



Example E- 1. BitmapEdit: complete widget code (continued) 

BitmapEditWidget new = (BitmapEditWidget) tnew; 
new->bitmapEdit.cur x = 0; 
-- 
new->bitmapEdit.cur_y = 0; 
/* 
* Check instance values set by resources that may be invalid. 
*/ 
if ((new->bitmapEdit.pixmap_width in cells < I) 
(new->bitmapEdit.pixmap_height in cells < I)) { 
XtWarning("BitmapEdit: pixmapWidth and/or pixmapHeight is too 
small (using i0 x I0)."); 
new->bitmapEdit.pixmap_width in cells = I0; 
new->bitmapEdit.pixmap_height in cells = I0; 
if (new->bitmapEdit.cell size in pixels < 5) { 
_ 
XtWarning("BitmapEdit: cellSize is too small (using 5)."); 
new->bitmapEdit.cell size in pixels = 5; 
-- 
if ((new->bitmapEdit.cur x < 0) I I (new->bitmapEdit.cur_y < 0)) 
XtWarning("BitmapEdi: cur_x and cur_y must be non-negative\ 
(using 0, 0)."); 
new->bitmapEdit.cur x = 0; 
_ 
new->bitmapEdit.cur_y = 0; 
if (new->bitmapEdit.cell == NULL) 
new->bitmapEdit.cell = 
XtCalloc(new->bitmapEdit.pixmap_width in cells 
* new->bitmapEdit.pixmap_height in cells, sizeof(char)); 
new->bitmapEdit.pixmap_width_in_pixels = 
new->bitmapEdit.pixmap_width in cells * 
-- _ 
new->bitmapEdit.cell_size in pixels; 
new->bitmapEdit.pixmap_height in pixels = 
new->bitmapEdit.pixmap_height in cells * 
new->bitmapEdit.cell_size in pixels; 
if (new->core.width == 0) { 
if (new->bitmapEdit.showAll == False) 
new->core.width = (new->bitmapEdit.pixmap_width_in_pixels 
> DEFAULTWIDTH) ? DEFAULTWIDTH : 
(new->bitmapEdit.pixmap_width in pixels); 
else 
new->core.width = new->bitmapEdit.pixmap_width in pixels; 
if (new->core.height == 0) { 
if (new->bitmapEdit.showAll == False) 
new->core.height = (new->bitmapEdit.pixmap_height in pixels 
> DEFAULTWIDTH) ? DEFAULTWIDTH : 
(new->bitmapEdit.pixmap_height in pixels); 
else 
new->core.height = new->bitmapEdit.pixmap_height in pixels; 

CreateBigPixmap(new); 

502 

X Toolkit Intrinsics Programming Manual 



Example E-1. BitmapEdit: complete widget code (continued) 

GetDrawGC (new) ; 
GetUndrawGC (new) ; 
GetCopyGC (new) ; 

DrawIntoBigPixmap(new); 

/* ARGSUSED */ 
static void 
Redisplay(w, event) 
Widget w; 
XExposeEvent *event; 
{ 
BitmapEditWidget cw = (BitmapEditWidget) w; 
register int x, y; 
unsigned int width, height; 
if (!XtIsRealized(cw)) 
return; 

if (event) ( /* called from btn-event or expose */ 
x = event->x; 
y = event->y; 
width = event->width; 
height = event->height; 
} 
else ( /* called because complete redraw */ 
x = 0; 
y = 0; 
width = cw->bitmapEdit.pixmap_width in pixels; 
height = cw->bitmapEdit.pixmap_height in pixels; 
} 

if (DefaultDepthOfScreen(XtScreen(cw)) == I) 
XCopyArea(XtDisplay(cw), cw->bitmapEdit.big_picture, XtWindow(cw), 
cw->bitmapEdit.copy_gc, x + cw->bitmapEdit.cur_x, y + 
cw->bitmapEdit.cur_y, width, height, x, y); 
else 
XCopyPlane(XtDisplay(cw), cw->bitmapEdit.big_picture, XtWindow(cw), 
cw->bitmapEdit.copy_gc, x + cw->bitmapEdit.cur_x, y + 
cw->bitmapEdit.cur_y, width, height, x, y, I); 

/* ARGSUSED */ 
static Boolean 
SetValues(current, request, new) 
Widget current, request, new; 
! 
BitmapEditWidget curcw = (BitmapEditWidget) current; 
BitmapEditWidget newcw = (BitmapEditWidget) new; 
Boolean do_redisplay = False; 
if (curcw->bitmapEdit.foreground != newcw->bitmapEdit.foreground) 
XtReleaseGC(curcw, curcw->bitmapEdit.copy_gc); 
GetCopyGC(newcw); 
do_redisplay = True; 
} 

if ((curcw->bitmapEdit.cur x != newcw->bitmapEdit.cur x) I I 
-- _ 

Appendix E: The xbitmap Application 503 



Examp E-1. BitmapEdit: compte widget code Continued) 
(curcw->bitmapEdit.cur_y != newcw->bitmapEdit.cur_y)) 
do_redisplay = True; 
if (curcw->bitmapEdit.cell size in pixels != 
-- 
newcw->bitmapEdit.cell_size in pixels) { 
ChangeCellSize(curcw, newcw->bitmapEdit.cell_size_in_pixels); 
do_redisplay = True; 
) 
if (curcw->bitmapEdit.pixmap_width in cells != 
newcw->bitmapEdit.pixmap_width in cells) { 
newcw->bitmapEdit.pixmap_width in cells = 
curcw->bitmapEdit.pixmap_width in cells; 
XtWarning("BitmapEdit: pixmap_width in cells cannot be set\ 
by XtSetValues.\n"); 
) 
if (curcw->bitmapEdit.pixmap_height in cells != 
newcw->bitmapEdit.pixmap_height in cells) { 
newcw->bitmapEdit.pixmap_height in cells = 
curcw->bitmapEdit.pixmap_height in cells; 
XtWarning("BitmapEdit: pixmap_height in cells cannot\ 
be set by XtSetValues.\n"); 

return do_redisplay; 

static void 
Destroy(w) 
Widget w; 
{ 
BitmapEditWidget cw = (BitmapEditWidget) w; 
if (cw->bitmapEdit.big_picture) 
XFreePixmap(XtDisplay(cw), cw->bitmapEdit.big_picture); 
if (cw->bitmapEdit.draw_gc) 
XFreeGC(XtDisplay(cw), cw->bitmapEdit.draw_gc); 
if (cw->bitmapEdit.undraw_gc) 
XFreeGC(XtDisplay(cw), cw->bitmapEdit.undraw_gc); 
if (cw->bitmapEdit.copy_gc) 
XFreeGC(XtDisplay(cw), cw->bitmapEdit.copy_gc); 
/* NOTE! This should only free when the application didn't 
* allocate it. Need to add another. */ 
XtFree(cw->bitmapEdit.cell); 

static void 
DrawCell(w, event) 
Widget w; 
XEvent *event; 
{ 

BitmapEditWidget cw = (BitmapEditWidget) w; 
DrawPixmaps(cw->bitmapEdit.draw_gc, DRAW, cw, event); 

static void 

504 X Toolkit Intrinsics Programming Manual 



Examp E-1. BitmapEdit: compte widget code (continued) 
UndrawCell(w, event) 
Widget w; 
XEvent *event; 
{ 
BitmapEditWidget cw = (BitmapEditWidget) w; 
DrawPixmaps(cw->bitmapEdit.undraw_gc, UNDRAW, cw, event); 
} 
static void 
ToggleCell(w, event) 
Widget w; 
XEvent *event; 
{ 
BitmapEditWidget cw = (BitmapEditWidget) w; 
static int oldx = -I, oldy = -I; 
GC gc; 
int mode; 
int newx, newy; 
/* This is strictly correct, but doesn't 
* seem to be necessary */ 
if (event->type == ButtonPress) { 
newx = (cw->bitmapEdit.cur x + ((XButtonEvent *)event)->x) / 
cw->bitmapEdit.cell_size_in_pixels; 
newy = (cw->bitmapEdit.cur_y + ((XButtonEvent *)event)->y) / 
cw->bitmapEdit.cell size in pixels; 
} 
else { 
newx = (cw->bitmapEdit.cur x + ((XMotionEvent *)event)->x) / 
-- 
cw->bitmapEdit.cell size in pixels; 
newy = (cw->bitmapEdit.cur_y + ((XMotionEvent *)event)->y) / 
cw->bitmapEdit.cell size in pixels; 
-- 
} 

if ((mode = cw->bitmapEdit.cell[newx + newy * 
cw->bitmapEdit.pixmap_width_in_cells]) == DRAWN) { 
gc = cw->bitmapEdit.undraw_gc; 
mode = UNDRAW; 
} 
else { 
gc = cw->bitmapEdit.draw_gc; 
mode = DRAW; 
} 

if (oldx != newx II oldy != newy) { 
oldx = newx; 
oldy = newy; 
DrawPixmaps(gc, mode, cw, event); 
} 

static void 
DrawPixmaps(gc, mode, w, event) 
GC gc; 
int mode; 
Widget w; 
XButtonEvent *event; 

Appendix E: The xbitmap Application 505 



Example E- 1. BitmapEdit: complete widget code (continued) 

BitmapEditWidget cw = (BitmapEditWidget) w; 
int newx = (cw->bitmapEdit.cur x + event->x) / 
cw->bitmapEdit.cell_size in pixels; 
int newy = (cw->bitmapEdit.cur_y + event->y) / 
cw->bitmapEdit.cell_size in .pixels; 
XExposeEvent fake event; 
-- 
/* if already done, return */ 
if (cw->bitmapEdit.cell[newx + newy * 
cw->bitmapEdit.pixmap_width in cells] == mode) 
return; 
/* otherwise, draw or undraw */ 
XFillRectangle(XtDisplay(cw), cw->bitmapEdit.big_picture, gc, 
cw->bitmapEdit.cell size in pixels*newx + 2, 
cw->bitmapEdit.cell size in pixels*newy + 2, 
(unsigned int)cw->bitmapEdit.cell size in pixels - 3, 
(unsigned int)cw->bitmapEdit.cell size in pixels - 3); 
cw->bitmapEdit.cell[newx + newy * cw->bitmapEdit.pixmap_width in cells] 
= mode; 
info.mode = mode; 
info.newx = newx; 
info.newy = newy; 
fake_event.x = cw->bitmapEdit.cell size in pixels * 
newx - cw->bitmapEdit.cur x; 
fake_event.y = cw->bitmapEdit.cell size in pixels * 
-- 
newy - cw->bitmapEdit.cur_y; 
fake_event.width = cw->bitmapEdit.cell_size_in_pixels; 
fake_event.height = cw->bitmapEdit.cell_size_in_pixels; 
Redisplay(cw, &fake event); 
XtCallCallbacks(cw, XtNcallback, &info); 
} 
CreateBigPixmap(w) 
Widget w; 
{ 
BitmapEditWidget cw = (BitmapEditWidget) w; 
/* always a 1 bit deep pixmap, regardless of screen depth */ 
cw->bitmapEdit.big_picture = XCreatePixmap(XtDisplay(cw), 
RootWindow(XtDisplay(cw), DefaultScreen(XtDisplay(cw))), 
cw->bitmapEdit.pixmap_width in pixels + 2, 
cw->bitmapEdit.pixmap_height in pixels + 2, I); 
} 
DrawIntoBigPixmap(w) 
Widget w; 
{ 
BitmapEditWidget cw = (BitmapEditWidget) w; 
int n_horiz_segments, n vert_segments; 
XSegment segment[MAXLINS]; 
register int x, y; 
XFillRectangle(XtDisplay(cw), cw->bitmapEdit.big_picture, 
cw->bitmapEdit.undraw_gc, 0, 0, 
cw->bitmapEdit.pixmap_width in pixels 

506 X Toolkit Intrinsics Programming Manual 



Examp E- 1. BitmapEdit: compte widget code (continued) 
+ 2, cw->bitmapEdit.pixmap_height_in_pixels + 2); 
n_horiz_segments = cw->bitmapEdit.pixmap_height in cells + I; 
n_vert_segments = cw->bitmapEdit.pixmap_width in cells + I; 
for (x = 0; x < n_horiz_segments; x++) { 
segment[x].xl = 0; 
segment[x].x2 = cw->bitmapEdit.pixmap_width in pixels; 
segment[x].yl = cw->bitmapEdit.cell_size in pixels * x; 
segment[x].y2 = cw->bitmapEdit.cell size in pixels * x; 
XDrawSegments(XtDisplay(cw), cw->bitmapEdit.big_picture, 
cw->bitmapEdit.draw_gc, segment, n_horiz_segments); 
for (y = 0; y < n_vert_segments; y++) { 
segment[y].xl = y * cw->bitmapEdit.cell_size_in_pixels; 
segment[y].x2 = y * cw->bitmapEdit.cell size in pixels; 
segment[y].yl = 0; 
segment[y].y2 = cw->bitmapEdit.pixmap_height_in_pixels; 
XDrawSegments(XtDisplay(cw), cw->bitmapEdit.big_picture, 
cw->bitmapEdit.draw_gc, segment, n_vert_segments); 
/* draw current cell array into pixmap */ 
for (x = 0; x < cw->bitmapEdit.pixmap_width in cells; x++) { 
for (y = 0; y < cw->bitmapEdit.pixmap_height_in_cells; y++) 
if (cw->bitmapEdit.cell[x + (y * 
cw->bitmapEdit.pixmap_width in cells)] == DRAWN) 
DoCell(cw, x, y, cw->bitmapEdit.draw_gc); 
else 
DoCell(cw, x, y, cw->bitmapEdit.undraw_gc); 

} 
) 
} 

/* A Public function, not static */ 
char * 
BitmapEditGetArrayString(w) 
Widget w; 
{ 
BitmapEditWidget cw = (BitmapEditWidget) w; 
return (cw->bitmapEdit.cell); 
} 

/* ARGSUSED */ 
static void 
Resize(w) 
Widget w; 
{ 
BitmapEditWidget cw = (BitmapEditWidget) w; 
/* resize does nothing unless new size is bigger than entire pixmap */ 
if ((cw->core.width > cw->bitmapEdit.pixmap_width in pixels) && 
(cw->core.height > cw->bitmapEdit.pixmap_height in pixels)) { 
/* 
* Calculate the maximum cell size that will allow the 
* entire bitmap to be displayed. 
*/ 

Appendix E: The xbitmap Application 507 



Example E- 1. BitmapEdit: complete widget code (continued) 

Dimension w_temp_cell_size in pixels, h_temp_cell_size in pixels; 
Dimension new cell size in pixels; 
-- -- 

w_temp_cell_size in pixels = cw->core.width / 
cw->bitmapEdit.pixmap_width in cells; 
h_temp_cell_size in pixels = cw->core.height / 
cw->bitmapEdit.pixmap_height in cells; 

if (w_temp_cell_size in pixels < h_temp_cell_size in pixels) 
new_cell_size in pixels = w_temp_cell_size in pixels; 
else 
new_cell_size in pixels = h_temp_cell_size in pixels; 

/* if size change mandates a new pixmap, make one */ 
if (new cell size in pixels != cw->bitmapEdit.cell size in pixels) 
-- -- _ 
ChangeCellSize(cw, new cell size in pixels); 
-- -- 
} 
} 
static void 
ChangeCellSize(w, new_cell_size) 
Widget w; 
int new cell size; 
-- _ 
{ 
BitmapEditWidget cw = (BitmapEditWidget) w; 
int x, y; 
cw->bitmapEdit.cell_size in pixels = new cell size; 
-- _ 
/* recalculate variables based on cell size */ 
cw->bitmapEdit.pixmap_width_in_pixels = 
cw->bitmapEdit.pixmap_width in cells * 
cw->bitmapEdit.cell size in pixels; 
-- 
cw->bitmapEdit.pixmap_height in pixels = 
cw->bitmapEdit.pixmap_height in cells * 
cw->bitmapEdit.cell_size in pixels; 

/* destroy old and create new pixmap of correct size */ 
XFreePixmap(XtDisplay(cw), cw->bitmapEdit.big_picture); 
CreateBigPixmap(cw); 

/* draw lines into new pixmap */ 
DrawIntoBigPixmap(cw); 

/* draw current cell array into pixmap */ 
for (x = 0; x < cw->bitmapEdit.pixmap_width in cells; x++) { 
for (y = 0; Y < cw->bitmapEdit.pixmap_height in cells; y++) { 
if (cw->bitmapEdit.cell[x + (y * 
cw->bitmapEdit.pixmap_width in cells)] == DRAWN) 
DoCell(cw, x, y, cw->bitmapEdit.draw_gc); 
else 
DoCell (cw, x, y, cw->bitmapEdit.undraw_gc) ; 
} 
} 

static void 

508 X Toolkit intrinsics Programming Manual 



Examp E-2. BitmapEdiP.h: comp pdva header file ontued) 
typedef struct _BitmapEditRec { 
CorePart core; 
BitmapEditPart bitmapEdit; 
} BitmapEditRec; 
#endif /* _ORABitmapEditP_h */ 

E.3 The BitmapEdit.h Public Header File 

Examp E-3. B#mapEdit.h: comp public header file 
#ifndef _ORABitmapEdit_h 
#define _ORABitmapEdit_h 
/* 
* BitmapEdit Widget public include file 
*/ 

/* 
* This include not needed unless the application includes 
* Intrinsic.h after this file. Anyway, it doesn't hurt. 
*/ 
#include <Xll/Core.h> 

/* Resources: 
* Name Class RepType Default Value 
* (from RectObj) 
* ancestorSensitive 
* x Position Int 0 
* y Position Int 0 
* width Dimension Dimension 0 
* height Dimension Dimension 0 
* borderWidth BorderWidth Int 
* sensitive Sensitive 

* (from WindowObj) 
* screen Screen Pointer 
* depth Depth Int 
* colormap Colormap Pointer 
* background Background Pixel 
* backgroundPixmap Pixmap Pixmap 
* borderColor BorderColor Pixel 
* borderPixmap BorderPixmap Pixmap 
* mappedWhenManaged MappedWhenManaged Boolean True 
* translations 
* accelerators 

* (from Core) 

XtCopyScreen 
XtCopyFromParent 
XtCopyFromParent 
White 
XtUnspecifiedPixmap 
Black 
XtUnspecifiedPixmap 

Appendix E: The xbitmap Application 511 



Examp E-3. BitmapEdit.h: comp public header file (continued) 
* none 
. 
* (from BitmapEdit) 
* foregroundPixel Foreground Pixel Black 
* backgroundPixel Background Pixel White 
* callback Callback Callback NULL 
* cellSize CellSize Int 30 
* pixmapWidth PixmapWidth Int 32 
* pixmapHeight PixmapHeight Int 32 
*/ 
/* 
* This public structure is used as call data to the callback. 
* It passes the x, y position of the cel toggled (in units of 
* cells, not pixels) and a mode flag that indicates whether the 
* cell was turned on (I) or off (0). 
*/ 
typedef struct { 
int mode; 
int newx; 
int newy; 
} BitmapEditPointInfo; 
#define XtNcellSizeInPixels "cellSizeInPixels" 
#define XtNpixmapWidthInCells "pixmapWidthInCells" 
#define XtNpixmapHeightInCells "pixmapHeightInCells" 
#define XtNcurX "curX" 
#define XtNcurY "curY" 
#define XtNcellArray "cellArray" 
#define XtNshowEntireBitmap "showEntireBitmap" 
#define XtCCellSizeInPixels "CellSizelnPixels- 
#define XtCPixmapWidthInCells "PixmapWidthInCells" 
#define XtCPixmapHeightInCells "PixmapHeightInCells" 
#define XtCCurX "CurX" 
#define XtCCurY "CurY" 
#define XtCCellArray "CellArray" 
#define XtCShowEntireBitmap "ShowEntireBitmap" 
extern char *BitmapEditGetArrayString(); /* w */ 
/* Widget w; */ 
/* Class record constants */ 
extern WidgetClass bitmapEditWidgetClass; 
typedef struct _BitmapEditClassRec *BitmapEditWidgetClass; 
typedef struct _BitmapEditRec *BitmapEditWidget; 
#endif /* _ORABitmapEdit_h */ 
/* DON'T ADD STUFF AFTER THIS #endif */ 

512 X Toolkit Intrinsics Programming Manual 



Example E-4. xbitmap8: complete application code (continued) 

"XBitmap8", 
table, XtNumber(table), 
&argc, argv, 
NULL, 
NULL); 

/* Application class */ 
/* command line option list */ 
/* command line args */ 
/* for missing app-defaults file */ 
/* terminate varargs list */ 

if (argv[l] != NULL) 
filename = argv[l]; 
else ( 
fprintf(stderr, "xbitmap: must specify filename on command line.\n"); 
exit(l); 
form = XtCreateManagedWidget("form", formWidgetClass, topLevel, NULL, 0); 
buttonbox = XtCreateManagedWidget("buttonbox", boxWidgetClass, form, 
NULL, 0); 
output = XtCreateManagedWidget("output", commandWidgetClass, buttonbox, 
NULL, 0); 

XtAddCallback(output, XtNcallback, Printout, NULL); 
quit = XtCreateManagedWidget("quit", commandWidgetClass, buttonbox, 
NULL, 0); 

XtAddCallback(quit, XtNcallback, exit, NULL); 
XtAppAddActions(app_context, window_actions, XtNumber(window_actions)) ; 
switch (XReadBitmapFile(XtDisplay(quit), 
RootWindowOfScreen(XtScreen(quit)), filename, 
&width, &height, &normal_bitmap, &junk, &junk)) { 
case BitmapSuccess: 
file_contained_good_data = True; 
if ((pixmap_width in cells != width) 
(pixmap_height in cells != height)) 
fprintf(stderr, "xbitmap: bitmap file dimensions\ 
do not match resource database,\ 
ignoring database.kn"); 
i = 0; 
XtSetArg(args[i], XtNpixmapWidthInCells, width); i++; 
XtetArg(args[i], XtNpixmapHeightInCells, height); i++; 
pixmap_width in cells = width; 
pixmap_height_in_cells = height; 
cell = FillCell(quit); 
XtSetArg(args[i], XtNcellArray, cell); i++; 

} 
break; 
case BitmapOpenFailed: 

fprintf(stderr, "xbitmap: could not open bitmap file, using 
fresh bitmap.\n"); 
break; 
case BitmapFileInvalid: 
fprintf(stderr, "xbitmap: bitmap file invalid.kn"); 
exit(l): 
case BitmapNoMemory: 
fprintf(stderr, "xbitmap: insufficient server memory to 
create bitmap.kn"); 
exit(l); 

Appendix E: The xbitmap Application 515 



Example E-4. xbitmap8: complete application code (continued) 

default: 
fprintf(stderr, "xbitmap: programming error.\n"); 
exit(l); 

/* args are set in if and switch above if file was read */ 
bigBitmap = XtCreateManagedWidget("bigBitmap", 
bitmapEditWidgetClass, form, args, i); 
XtAddCallback(bigBitmap, XtNcallback, cell_toggled, NULL); 
if (!file_contained_good_data) { 
XtVaGetValues(bigBitmap, 
XtNpixmapHeightInCells, &pixmap_height in cells, 
XtNpixmapWidthInCells, &pixmap_width in cells, 
NULL); 
normal_bitmap = XCreatePixmap(XtDisplay(quit), 
RootWindowOfScreen(XtScreen(quit)), 
pixmap_width in cells, pixmap_height_in_cells, I); 
} 
set up things(topLevel); 
showNormalBitmap = XtVaCreateManagedWidget("showNormalBitmap,,, 
widgetClass, buttonbox, 
XtNwidth, pixmap_width in cells, 
XtNheight, pixmap_height in cells, 
XtNtranslations, XtParseTranslationTable(trans), 
NULL); 
showReverseBitmap = XtVaCreateManagedWidget("showReverseBitmap,,, 
widgetClass, buttonbox, 
XtNwidth, pixmap_width in cells, 
XtNheight, pixmap_height in cells, 
XtNtranslations, XtParseTranslationTable(trans), 
NULL); 
XtRealizeWidget(topLevel); 
XtAppMainLoop(app_context); 
) 
set_up_things(w) 
Widget w; 
{ 
XGCValues values; 
values.foreground = i; 
values.background = 0; 
/* note that normal_bitmap is used as the drawable because it 
* is one bit deep. The root window may not be one bit deep. */ 
draw_gc = XCreateGC(XtDisplay(w), normal_bitmap, 
GCForeground  GCBackground, &values); 
values.foreground = 0; 
values.background = i; 
undraw_gc = XCreateGC(XtDisplay(w), normal_bitmap, 
GCForeground  GCBackground, &values); 
/* this GC is for copying from the bitmap 

516 

X Toolkit Intrinsics Programming Manual 



Examp E-4. xbitmap8: compte application code Continued) 
* to the small reverse widget */ 
values.foreground = WhitePixelOfScreen(XtScreen(w)); 
values.background = BlackPixelOfScreen(XtScreen(w)); 
invert_gc = XtGetGC(w, GCForeground I GCBackground, &values); 
} 
/* ARGSUSED */ 
static void 
cell_toggled(w, client_data, info) 
Widget w; 
XtPointer client data; /* unused */ 
-- 
XtPointer info; /* call data (from widget) */ 
{ 
BitmapEditPointInfo *cur_info = (BitmapEditPointInfo *) info; 
/* 
* Note: BitmapEditPointInfo is defined in BitmapEdit.h 
*/ 
XDrawPoint(XtDisplay(w), normal_bitmap, ((cur_info->mode == DRAWN) 
? draw_gc : undraw_gc), cur_info->newx, cur_info->newy); 
Redraw_small_picture(showNormalBitmap); 
Redraw_small_picture(showReverseBitmap); 

Appendix E: The xbitmap Application 517 



F 

Sources of Additional Information 

This appendix describes where you can get more information about the X 
Toolkit and about X in general, including other books on the subject and the 
various ways to get the source code for X. 

In This Chapter: 

Getting the X Software ....................................................................... 521 
Bug Fixes ...................................................................................... 522 
Notes ........................................................................................... 524 
Fairness ...................................................................................... 524 
Netnews ............................................................................................ 525 
Training and Consulting ..................................................................... 525 
Phone Support ............................................................................... 526 
The X Consortium .............................................................................. 526 
Finding Out for Yourself ..................................................................... 527 



F 
Sources of Additional Information 

This appendix lists a few of the official and unofficial sources for information about the X 
Window System and associated software. 

Note that some of this detailed information may become dated rather quickly. The best 
source of current information is the comp.windows.x network news group, described later in 
this appendix. 

This book documents Release 4, the current public release level of the X software as of June 
1990. Even so, many people continue to use R3 since there is a considerable delay between 
the date that MIT disu'ibutes a new release and the date by which vendors integrate that 
release into their own products and issue updates. An R3 version of this manual is available 
while demand is sufficient to continue reprinting. (All changes to Xt in R4 are backwards 
compatible so that any software that runs under R3 will also run under R4. But the converse 
is not true.) 

F.1 

Getting the X Software 

You can get the X software directly from MIT on three 9-track 1600 BPI magtapes written in 
UNIX tar format or on one 9-track 6250 BPI magtape, along with printed copies of MIT's 
manuals, by sending a check in U.S. currency for U.S. $400 to: 
MIT Software Distribution Center 
Technology Licensing Office 
MIT E32-300 
77 Massachusetts Avenue 
Cambridge, MA 02139 
Their telephone number is (617) 253-6966, and the "X Ordering Hotline" is (617) 258-8330. 
If you want the tapes and manuals shipped overseas, the price is $500. The manual set alone 
is $125 including U.S. shipping or $175 including overseas shipping. 
Other distribution media or formats are not available from the MIT Software Distribution 
Center, but are from other independent vendors such as ICS, mentioned later. The Release 
tape comes with source code for sample servers for Sun, HP, IBM, Apollo, Sony, DEC and 
several other workstations, source code for clients written by MIT, sources for the toolkits 

Appendix F: Sources of Additional Information 521 



Xt, XView (in R4), Interviews, and Andrew, contributed software written outside MIT 
(including the examples in this book), and sources and postscript files for all MIT's documen- 
tation. Note that the servers supplied are sample servers only; commercial vendors typically 
release optimized (faster) servers for the same machines. 

Sites that have access to the Internet can retrieve the distribution from the following 

machines using anonymousftp. Here are the current sites: 

Location 

Western USA 
Eastern USA 
Northeastern USA 

Central USA 

Southern USA 
UK (Janet) 
Australia 

Hostname 

gatekeeper.dec.com 
uunet.uu.net 
expo.lcs.mit.edu 
crl.dec.com 
mordred, cs.purdue.edu 
giza.cis.ohio-state.edu 
wuar c hi ve. wust l.e du 
src.doc.ic.ac.uk 
munnari.oz.au 

Address 

16.1.0.2 
192.48.96.2 
18.30.0.212 
192.58.206.2 
128.10.2.2 
128.146.8.61 
129.252.135.4 
129.31.81.36 
128.250.1.21 

Directory 

pub/Xl l /R4 
X/R4 
pubC4 
pub/Xl l /R4 
pub/Xl l /R4 
pub/X. Vl l R 4 
packages/X.Vl lR4 
X.VllR4 
X.Vll/R4 

DO NOT do anonymous ftp during normal business hours, and please use the machine 
nearest you. 

The distribution is also available by UUCP from UUNET, for sites without Internet access. 
The files are split up to be small enough for UUCP distribution. See the preface for instruc- 
tions on getting files from UUNET if you are not a UUNET subscriber. 

F.1.1 

Bug Fixes 

Critical bug fixes as well as a limited number of important new features are available from 
the archive server xstuff@expo.lcs.mit.edu. Electronic mail sent to this address is forwarded 
to a program which responds with the requested information. The rest of this section and the 
two that follow it (entitled Notes and Fairness) explain how to use xstuff. 
The xstuff server is a mail-response program. This means that you mail it a request, and it 
mails back the response. 
The xstuffserver is a very dumb program. It does not have much error checking. If you don't 
send it commands that it understands, it will just answer "I don't understand you." 
The xstuff server reads your entire message before it does anything, so you can have several 
different commands in a single message. It treats the "Subject:" header line just like any 
other line of the message. You can use any combination of upper and lower case letters in 
the commands. 

The archives are organized into a series of directories and subdirectories. Each directory has 
an index, and each subdirectory has an index. The top-level index gives you an overview of 
what is in the subdirectories, and the index for each subdirectory tells you what it contains. 

522 X Toolk# Intrinsics Programming Manual 



F.1.1.1 

path 

You may put as many send commands as you like into one message to the server, 
but the more you ask for, the longer it will take to receive. See the Fairness Section 
below, for an explanation. Actually, it's not strictly true that you can put as many 
send commands as you want into one message. If the server must use UUCP mail to 
send your files, then it cannot send more than 100K bytes in one message. If you 
ask for more than it can send, then it will send as much as it can and ignore the rest. 
The path command exists to help in case you do not get responses from the server 
when you mail to it. 
Sometimes the server is unable to return mail over the incoming path. There are 
dozens of reasons why this might happen, and if you are a true wizard, you already 
know what those reasons are. If you are an apprentice wizard, you might not know 
all the reasons, but you might know a way to circumvent them. 
If you put in a path command, then everything that the server mails to you will be 
mailed to that address, rather than to the return address on your mail. The server 
host expo.lcs.mit.edu does not have a direct UUCP connection to anywhere; you 
must go through mit-eddie (the UUCP name of eddie.mit.edu) or somewhere else. 

Notes 

The xstuff server acknowledges every request by return mail. If you don't get a message 
back in a day or two you should assume that something is going wrong, and perhaps try a 
path command. 

The xstuff server does not respond to requests from users named root, system, daemon, or 
mailer. This is to prevent mail loops. If your name is "Bruce Root" or "Jane Daemon", and 
you can document this, I will happily rewrite the server to remove this restriction. Yes, I 
know about Norman Mailer and Waverley Root. Norman doesn't use netmail and Waverley 
is dead. 

F.1.1.2 

Fairness 

The xstuff server contains many safeguards to ensure that it is not monopolized by people 
asking for large amounts of data. The mailer is set up so that it will send no more than a fixed 
amount of data each day. If the work queue contains more requests than the day's quota, then 
the unsent files will not be processed until the next day. Whenever the mailer is run to send 
its day's quota, it sends the requests out shortest-first. 

If you have a request waiting in the work queue and you send in another request, the new 
request is added to the old one (thereby increasing its size) rather than being filed anew. This 
prevents you from being able to send in a large number of small requests as a way of beating 
the system. 

The reason for all of these quotas and limitations is that the delivery resources are finite, and 
there are many people who would like to make use of the archive. 

524 X Too/k# Intrinsics Programming Manual 



F.3.1 Phone Support 

X programming is a very new field, and since everyone who knows enough to help you is 
overworked, you are likely to hear "you're on your own" if you try to call for help. There are 
no support lines from the developers of X, because X was developed by a university, not a 
system manufacturer or software house. When X becomes widely supported as a commercial 
product, the situation should change as vendors offer support. 

ICS provides phone support for a fee. See Section G.3 for their telephone number. 

F.4 The X Consortium 

The X Consortium can be reached at: 

MIT X Consortium 
545 Technology Square Rm. 217 
Cambridge, MA 02139 
The consortium's phone number is (617) 253-8861; its current members are shown below. 

ACER Counterpoint, Inc. 
AT&T 
Adobe Systems 
Advanced Graphics Engineering 
Apollo Computer, Inc. 
Apple Computer, Inc. 
Ardent Computer 
BULL MTS 
CETIA 
CalComp 
Canterbury University, England 
Carnegie Mellon University 
Codonics, Inc. 
Control Data Corporation 
Cray Research, Inc. 
Data General 
Digital Equipment Corp. 
Eastman Kodak Company 
Evans & Sutherland 
Fujitsu America, Inc. 
GfxBase 
Hewlett Packard Company 
IBM Corporation 
INESC* 
Integrated Computer Solutions, Inc. 
Integrated Solutions, Inc. 

Matrox International 
Megatek Corp. 
Mitsubishi Electric Corporation 
NCR Corporation 
NEC Corporation 
NTT Corporation 
Network Computing Devices, Inc. 
Nova Graphics International 
O'Reilly & Associates, Inc. 
OMRON Tateisi Electronics 
Open Software Foundation 
PCS Computer Systeme GmbH 
Prime Computer, Inc. 
Reuters 
Samsung Software America 
Sequent Computer Systems Inc. 
Siemens AG 
Silicon Graphics Computer Systems 
Societe de Gestion et d'Informatique Publicis 
Software Productivity Consortium 
Solbourne Computer Inc. 
Sony Corporation 
Stanford University 
Stellar Computer Inc. 
Sun Microsystems, Inc. 
Tatung Science and Technology 

*Instituto de Engenharia de Sistemas e Computadores 
526 

X Toolkit Intrinsics Programming Manual 



Interactive Development Environments 
Interactive Systems Corp. 
Jupiter Systems 
Key Systems Engineering Corp. 
Landmark Graphics Corp. 
Locus Computing Corp. 
MIPS Computer Systems 
MITRE Corp. 

Tektronix, Inc. 
Texas Insmaments 
UNICAD, Inc. 
Unisys Corp. 
University of Lowell 
Visual Technology, Inc. 
Wang Laboratories 
X/Open Company Ltd. 

Most of these companies are preparing products based on X. It should not be long before 
many different products are available that support X. 

F.5 

Finding Out for Yourself 

If, heaven forbid, you don't find an answer to your problem in one of the books in our X Win- 
dow System Series, and you can't get anyone to help you, what do you try next? 
X is unusual in that the source code is freely available. It should be possible for most X pro- 
gammers to get a copy of the X source code from the sources listed above. There you can 
look at some examples of how others have used X to write applications. In "Star Wars," the 
saying was "Use the Force, Luke." In X, it is "Use the Source, Luke." However, you may 
find that many of the applications on the release tape use out-of-date techniques, because 
they were written before the release. 
Whenever looking at the code for the server or any of the programming libraries such as Xlib 
or Xt, however, remember that the X standards are defined by documents, not by code. In 
other words, don't depend on any of the undocumented details of the code you happen to 
have access to, since some other vendor may not implement the standard in the same way. 
Nevertheless, it can sometimes be useful to see how things are actually being done. Once 
you understand how the code is organized, you can look up certain details about how X 
works as long as you have a good knowledge of C and a little persistence. 
Xlib and the server are two distinct chunks of code. Each contains code for sending and 
receiving information to and from the other over the network using protocol requests, replies, 
events, and errors. The source tree as supplied on the X distribution tape places the Xlib 
source in the directory baseCibC, where base is the top of the entire source tree. Their server 
source is placed in baseCerver. 
The procedure for finding out something about an Xlib routine is normally to search for the 
routine in the Xlib code, and then figure out what it does. Sometimes the answer can be 
found there. Many of the routines, however, simply place their arguments in a protocol 
request and send it to the server. Then you will have to look in the server code for the 
answer. To find the correct place in the server code, you will need the symbol for the proto- 
col request, which is the first argument in the GetReq call. 
The server code is much more involved than Xlib itself. The device-dependent portions are 
in baselserver/ddx and the device-independent portions are in base/server/chx. The device- 
independent code should be your first stop, because it is here that protocol requests from Xlib 

Appendix F: Sources of Additional Information 527 



arrive and are dispatched to the appropriate code. Search for the protocol request symbol 
you found in Xlib. It will appear in several source files. Start with the occurrence in 
dispatch.c, and try to figure out what the code does. This will require following leads to 
other routines. 

If you don't find a routine in base/server/dix, then it must be in the device-dependent code. 
baselserverlddx has one directory in it for each brand of hardware to which a sample server 
has been ported. It also contains the directories/mi,/cfb,/mfb, and/snf, which contain rou- 
tines used in writing the sample server device-dependent code. Note that servers may 
include code ostensibly for other machines. 

528 X Toolkit Intrinsics Programming Manual 



Glossary 

X uses many common terms in unique ways. A good example is "children." 
While most, if not all, of these terms are defined where they are first used in 
this manual you will undoubtedly find it easier to refresh your memory by 
looking for them here. 



active grab 
A grab is active when the pointer or keyboard is actually owned by a single grab- 
bing client. See also grab. 

ancestor 

If window W is an inferior of window A, then A is an ancestor of W. The parent 
window, the parent's parent window, and so on are all ancestors of the given win- 
dow. The root window is the ancestor of all windows on a given screen. 
application context 
An application context specifies a connection to a scrver. When an application 
program has connections to multiple servers, the application context coordinates 
events and their dispatching, so all connections get processed. 
argument list 
An argument list is used in a call to create a widget in order to "hardcode" the val- 
ue of widget resources, and also in calls to XtSetValues or XtGetValues. It 
consists of an array of Arg structures, each consisting of a resource name and the 
value to which it should be set. 
Athena widget 
MIT distributes a set of widgets developed by MIT's Project Athena in the Athena 
Widget library, Xaw. The include files for Athena widgets reside in 
/usr/include/Xll under Release 3 and usr/include/Xll/Xaw under Release 4. 
atom An atom is a unique numeric ID corresponding to a string name. Atoms are used to 
identify properties, types, and selections in order to avoid the overhead of passing 
arbitrary-length strings over the network. See also property. 
background 
Windows may have a background, consisting of either a solid color or a tile pat- 
tern. If a window has a background, it will be repainted automatically by the 
server whenever there is an Expose event on the window. If a window does not 
have a background, it will be transparent. By default, a window has a background. 
See also foreground. 
backing store 
When a server maintains the contents of a window, the off-screen saved pixels are 
known as a backing store. This feature is not available on all servers. Even when 
available, the server will not maintain a backing store, unless told to do so with a 
window attribute. Use the DoesBackingStores Xlib macro to determine if 
this feature is supported. 

532 X Too&# Intrinsics Programming Manual 



bit gravity 
When a window is resized, the contents of the window are not necessarily discard- 
ed. It is possible to request the server (though no guarantees are made) to relocate 
the previous contents to some region of the resized window. This attraction of win- 
dow contents for some location of a window is known as bit gravity. For example, 
an application that draws a graph might request that the contents be moved into the 
lower-left corner, so that the origin of the graph will still appear in the lower-left 
corner. See also window gravity. 

bit plane 

On a color or gray scale display, each pixel has more than one bit defined. Data in 
display memory can be thought of either as pixels (multiple bits per pixel) or as bit 
planes (one bit plane for each usable bit in the pixel). The bit plane is an array of 
bits the size of the screen. 
bitmap A bitmap is a pixmap with a depth of one bit. There is no bitmap type in X11. In- 
stead, use a pixmap of depth 1. See also pixmap. 
border A window can have a border that is zero or more pixels wide. If a window has a 
border, the border can have a solid color or a tile pattern, and it will be repainted 
automatically by the server whenever its color or pattern is changed or an Expose 
event occurs on the window. 
button grabbing 
A pointer grab that becomes active only when a specified set of keys and/or buttons 
are held down in a particular window is referred to as a button grab. 
byte order 
The order in which bytes of data are stored in memory is hardware-dependent. For 
pixmaps and bitmaps, byte order is defined by the server, and clients with different 
native byte ordering must swap bytes as necessary. For all other parts of the proto- 
col, the byte order is defined by the client, and the server swaps bytes as necessary. 
callback A callback is an application function registered with a widget by the application 
using either of the calls Xt:/kddCal.lback or Xt:/kddCal.lbacks or through an 
argument list. A widget declares one or more callback lists as resources; applica- 
tions add functions to these lists in order to link widgets to applications code. 
change_managed method 
When a parent should change its managed widgets, the change_managed method is 
invoked, at which time a parent reorganizes its children. The change_managed 
method is part of the Composite widget class. 
child, children 
1) A widget created by Xt:Creat:era_dcjet: is a child of the widget specified as 
its parent. The parent controls the layout of its children. 
2) The children of a window are its first-level subwindows. All of these windows 
were created with the same window as parent. A client creates its top-level win- 
dow as a child of the root window. 

Glossary 533 



class 1) (X Toolkit) A widget's class determines what methods will be called for it and 
what instance variables it has. For widget users, a widget's class is declared in the 
.h file for the widget. 
2) (Xlib) There are two uses of the term class in X: window class and visual class. 
The window class specifies whether a window is InputOnly or Input- 
Output. The visual class specifies the color model that is used by a window. See 
the classes DirectColor, GrayScale, PseudoColor, StaticColor, 
StaticGray, and TrueColor. Both window class and visual class are set per- 
manently when a window is created. 
class initialize method 
This method--part of the Core widget--is invoked when a widget class is initial- 
ized. That is, it is called when the first instance of a particular class is created. 
client An application program connects to the window system server by an interprocess 
communication (IPC) path, such as a TCP connection or a shared memory buffer. 
This program is referred to as a client of the window system server. More precise- 
ly, the client is the IPC path itself; a program with multiple paths open to one or 
more servers is viewed by the protocol as multiple clients. X Resources are avail- 
able only as long as the connection remains intact, not as long as a program re- 
mains running. Normally the connection and the program terminate concurrently, 
but the client's resources may live on if XChangeCloseDownMode has been 
called. 

clipping region 
In many graphics routines, a bitmap or list of rectangles can be specified to restrict 
output to a particular region of the window. The image defined by the bitmap or 
rectangles is called a clipping region, or clip mask. Output to child windows is 
automatically clipped to the borders of the parent unless subwindow mode of 
the GC is IncludeInferiors. Therefore the borders of the parent can be 
thought of as a clipping region. 
colorcell An entry in a colormap is known as a colorcell. An entry contains three values 
specifying red, green, and blue intensities. These values are always 16-bit un- 
signed numbers, with zero being minimum intensity. The values are truncated or 
scaled by the server to match the display hardware. See also colormap. 
colormap 
A colormap consists of a set of colorcells. A pixel value indexes into the colormap 
to produce intensities of Red, Green, and Blue to be displayed. Depending on 
hardware limitations, one or more colormaps may be installed at one time, such 
that windows associated with those maps display with true colors. Regardless of 
the number of installable colormaps, any number of virtual colormaps can be creat- 
ed. When needed, a virtual colormap can be installed and the existing installed 
colormap might have to be uninstalled. The colormap on most systems is a limited 
resource that should be conserved by allocating read-only colorcells whenever pos- 
sible, and by selecting RGB values from the predefined color database. Read-only 
cells may be shared between clients. See also colorcell, DirectColor, Gray- 
Scale, PseudoColor, StaticColor, StaticGray, and TrueColor. 

534 X Too/k# Intrinsics Programming Manual 



Composite widget 
A Composite widget is designed to manage the geometry of children; that is, a 
Composite widget instance can be passed in the parent argument to XtCreate- 
Widget. 
connection 
The communication path between the server and the client is known as a 
connection. A client usually (but not necessarily) has only one connection to the 
server over which requests and events are sent. 
Constraint widget 
The Constraint widget is a subclass of Composite. A Constraint widget has more 
information about each child than a Composite widget. 
constraints 
A Constraint widget provides a list of resources, or constraints, for its children. 
The constraints give the Constraint widget information about how each child 
should be layed out. 
containment 
A window contains the pointer if the window is viewable and if the hotspot of the 
cursor is within a visible region of the window or a visible region of one of its infe- 
riors. The border of the window is included as part of the window for containment. 
The pointer is in a window if the window contains the pointer but no inferior con- 
tains the pointer. 
coordinate system 
The coordinate system has x horizontal and y vertical, with the origin (0, 0) at the 
upper-left. Coordinates are discrete, and in terms of pixels. Each window and pix- 
map has its own coordinate system. For a window, the origin is inside the border, if 
there is one. The position of a child window is measured from the origin of the par- 
ent to the outside corner of the child (not the child's origin). 
Core widget 
The Core widget is the basic class in the Toolkit. All widgets that can be displayed 
are subclasses of Core. 
cursor A cursor is the visible shape of the pointer on a screen. It consists of a hotspot, a 
shape bitmap, a mask bitmap, and a pair of pixel values. The cursor defined for a 
window controls the visible appearance of the pointer when the pointer is in that 
window. 
delete child method 
The delete_child method is invoked on a parent after its child is deleted. This 
method is part of the Composite widget and is usually inherited. 
depth The depth of a window or pixmap is the number of bits per pixel. 
dereference 
To access the contents of a pointer, you must dereference it. 

Glossary 535 



event handler 
An event handler is a function that is called by Xt when a particular event is re- 
ceived. Event handlers have the same purpose as translations and actions--to call 
a function in response to an event--but event handlers have lower overhead and 
are not user-configurable. 
event mask 
Events are requested relative to a window or widget. The set of event types a client 
requests relative to a window is described using an event mask, a bitwise OR of de- 
fined symbols specifying which events are desired. 
The event: mask is a window attribute, which can be set in Xlib with 
XSelectInput, and is also specified in calls that grab the pointer or keyboard. 
The do_not_propagate_mask attribute is also an event mask, and it speci- 
fies which events should not be propagated to ancestor windows. In Xt, you never 
need to set a window's event_mask or do_not_propogate_mask directly. 
The translation manager automatically selects the required events. 
event propagation 
Device-related events propagate from the source window to ancestor windows un- 
til a window that has selected that type of event is reached, or until the event is dis- 
carded explicitly in a do_not_propagate_mask attribute. 
event source 
The smallest window containing the pointer is the source of a device-related event. 
expose method 
When Expose events are received, the Intrinsics invoke the expose method. A 
widget should perform its redisplay activities in this method. The expose meth- 
od is pan of the Core widget class. 

exposure 

Window exposure occurs when a window is first mapped, or when another window 
that obscures it is unmapped, resized, or moved. Servers do not guarantee to pre- 
serve the contents of windows when windows are obscured or reconfigured. Ex- 
pose everits a/e sent to clients to inform them when contents of regions of win- 
dows have been lost and need to be regenerated. 
extension 
Named extensions to the core protocol can be defined to extend the system. Exten- 
sion to output requests, resources, and event types are all possible, and expected. 
Extensions can perform at the same level as the core Xlib. 
font A font is an array of characters or other bitmap shapes such as cursors. The proto- 
col does no translation or interpretation of character sets. The client simply indi- 
cates values used to index the font array. A font contains additional metric infor- 
mation to determine intercharacter and interline spacing. 

Glossary 537 



occlude 

Window A occludes window B if both are mapped, if A is higher in the global 
stacking order, and if the rectangle defined by the outside edges of A intersects the 
rectangle defined by the outside edges of B. The (fine) distinction between the 
terms obscures and occludes is that for obscures, the windows have to be mapped, 
while for occludes they don't. Also note that window borders are included in the 
calculation. Note that Input:Ona.y windows never obscure other windows but 
can occlude other windows. 

padding 

Some bytes are inserted in the data stream to maintain alignment of the protocol re- 
quests on natural boundaries. This padding increases ease of portability to some 
machine architectures. 

parent A parent is a Composite widget instance specified as the parent argument in Xt:- 
Creat:er5.dget:. Parents control a child's layout. 
parent window 
Each new window is created with reference to another previously-created window. 
The new window is referred to as the child, and the reference window as the par- 
ent. If C is a child of P, then P is the parent of C. Only the portion of the child that 
overlaps the parent is viewable. 
passive grab 
A passive grab is a grab that will become active only when a specific key or button 
is actually pressed in a particular window. 
pixel value 
A pixel value is an N-bit value, where N is the number of bit planes used in a par- 
ticular window or pixmap. For a window, a pixel value indexes a colormap to de- 
rive an actual color to be displayed. For a pixmap, a pixel value will be interpreted 
as a color in the same way when it has been copied into a window. 
pixmap A pixmap is a three-dimensional array of bits. A pixmap is normally thought of as 
a two-dimensional array of pixels, where each pixel can be a value from 0 to 
(2 r - 1), where N is the depth (z-axis) of the pixmap. A pixmap can also be thought 
of as a stack of N bitmaps. A pixmap may have only one plane. Such a pixmap is 
often referred to as a bitmap, even though there is no bitmap type in X11. 
plane When a pixmap or window is thought of as a stack of bitmaps, each bitmap is 
called a plane. 
plane mask 
Graphics operations can be reswicted to affect only a subset of bit planes in a draw- 
able. A plane mask is a bit mask describing which planes are to be modified. 
pointer The pointer is the pointing device currently attached to the cursor, and tracked on 
the screens. This may be a mouse, tablet, track-ball, or joystick. 
pointer grabbing 
A client can actively grab control of the pointer, causing button and motion events 
to be sent to that client rather than to the client the pointer indicates. 

542 

X Toolkit Intrinsics Programming Manual 



pointing device 
A pointing device is typically a mouse or tablet, or some other device with effec- 
tive two-dimensional motion, that usually has buuons. There is only one visible 
cursor defined by the core protocol, and it tracks whatever pointing device is cur- 
rently attached as the pointer. 
pop up A pop up is a widget outside the normal parental hierarchy of geometry manage- 
ment. It is a child window of the root window that is popped up temporarily to 
give the user a piece of information, or to get some information from the user. 
post-order traversal 
When a tree structure is subject to post-order traversal, its root is visited last; for 
example, a function might process the left descendant, the right descendant, and 
then the root. 
pre-order traversal 
When a tree structure is subject to pre-order traversal, its root is visited first; for 
example, a function might process the root, and then the left and right descendant. 
private header file 
A private header file contains the internal class definitions of a widget. For ex- 
ample, the Label widget's internal class definitions are contained in the private 
header file LabelP.h. This file is included only in the widget .c file of this class and 
any subclasses, never in the application. 

property 

Windows may have associated properties, each consisting of a name, a type, a data 
format, and some data. The protocol places no interpretation on properties; they 
are intended as a general-purpose data storage and intercommunication mechanism 
for clients. There is, however, a list of predefined properties and property types so 
that clients might share information such as resize hints, program names, and icon 
formats with a window manager via properties. In order to avoid passing arbitrary- 
length property-name strings, each property name is associated with a correspond- 
ing integer value known as an atom. See also atom. 
PseudoColor 
PseudoColor is a visual class in which a pixel value indexes the colormap entry to 
produce independent red, green, and blue values. That is, the colormap is viewed 
as an array of triples (RGB values). The RGB values can be changed dynamically. 
public header file 
A public headerfile contains the declarations (e.g., class widget pointer) necessary 
to use a widget. For example, ].abe].r.dgel:C].ass declarations are contained 
in the public header file label.h. This header file is included in the widget .c file 
and in the application source file. 

Glossary 543 



quark A quark is an integer ID that identifies a string. In the context of Xt, this string is 
usually a name, class, or type string for the resource manager. Like atoms and re- 
source IDs, quarks eliminate the need to pass strings of arbitrary length over the 
network. The quark type is XrmQuark, and the types XrmName, XrmClass, 
and XrmRepresentation are also defined to be XrmQuark. 
query geometry method 
Parents call XtQueryGeometry to invoke the child's query geometry method to 
find out a child's preferred geometry. This method is part of the Core widget class. 
raise Changing the stacking order of a window so as to occlude all sibling windows is to 
raise that window. 

real estate 
The window management style characterized by the input being sent to whichever 
window the pointer is in is called real-estate-driven. This is the most common 
style of input management used in X. 
realize method 
The realize method creates a window on the display and is part of the Core widget 
class. 

rectangle 
A rectangle specified by [x,y,w,h] has an (infinitely thin) outline path with cor- 
ners at Ix,y], [x+w,y], [x+w,y+h], and [x,y+h]. When a rectangle is filled, 
the lower-right edges are not drawn. For example, if w=h=0, nothing would be 
drawn when drawing the rectangle, but a single pixel when filling it. For w---h=1, a 
single pixel would be drawn when drawing the rectangle, four pixels when filling 

redirect Window managers (or other clients) may wish to enforce window layout policy in 
various ways. When a client attempts to change the size or position of a window, 
or to map one, the operation may be redirected to the window manager, rather than 
actually being performed. Then the window manager (or other client that redirect- 
ed the input) is expected to decide whether to allow, modify, or deny the requested 
operation before making the call itself. See also window manager. 
reparenting 
The window manager often reparents the top-level windows of each application in 
order to add a title bar and perhaps resize boxes. In other words, a window with a 
title bar is inserted between the root window and each top-level window. See also 
save-set. 

544 

X Toolkit Intrinsics Programming Manual 



stipple 

status 

stacking order 
Sibling windows may stack on top of each other, obscuring lower windows. This is 
similar to papers on a desk. The relationship between sibling windows is known as 
the stacking order. The first window in the stacking order is the window on top. 
StaticColor 
The StaticColor visual class represents a multiplane color screen with a predefined 
and read-only hardware colormap. It can be viewed as a degenerate case of 
t:'aeudoCo].or. See PseudoColor. 
StaticGray 
The StaticGray visual class represents a multiplane monochrome screen with a 
predefined and read-only hardware colormap. It can be viewed as a degenerate 
case of GraySca].e, in which the gray values are predefined and read-only. Typi- 
cally, the values are linearly increasing ramps. See GrayScale. 
A stipple is a single plane pixmap that is used to tile a region. Bits set to 1 in the 
stipple are drawn with a foreground pixel value; bits set to 0, with a background 
pixel value. The stipple and both pixel values are members of the GC. 
Many Xlib functions return a status of TRUE or ',I,SE. If the function does not 
succeed, its return arguments are not disturbed. 

subclass 

A widget subclass has its own features plus many of the features of its superclasses. 
For example, since Composite is a subclass of Core, Composite has all the fields in 
Core plus its own unique fields. A subclass can inherit or replace most superclass 
features. 

superclass 
One widget is a superclass of a second widget when the second widget includes the 
first, or the Core widget is a superclass of the Composite widget because the Com- 
posite widget's definition depends on, or includes, the Core widget. 
tight binding 
A tight binding refers to the use of a dot (.) in a resource specification to indicate 
that the widget class or instance on the right side of the dot is a child of the widget 
whose class or instance name is on the left side of it. 
tile A pixmap can be replicated in two dimensions to tile a region. The pixmap itself is 
also known as a tile. 

time 

A time value in X is expressed in milliseconds, typically since the last server reset. 
Time values wrap around (after about 49.7 days). One time value, represented by 
the constant Current:Time, is used by clients to represent the current server 
time. 

top-level window 
A child of the root window is referred to as a top-level window. 

548 X Toolkit Intrinsics Programming Manual 



translation 
A translation maps an event or event sequence into an action name. Once a trans- 
lation is installed in a widget, the named action function will be invoked when the 
specified event seqeunce occurs in the widget. Translations are specified as ASCII 
strings. 
translation table 
A translation table lists one or more translations. 
"rrueColor 
The TrueColor visual class represents a high-performance multiplane display with 
predefined and read-only RGB values in its hardware colormap. It can be viewed 
as a degenerate case of Direct:Color, in which the subfields in the pixel value 
directly encode the corresponding RGB values. Typically, the values are linearly 
increasing ramps. See DirectColor. 
type property 
A type property is used to identify the interpretation of property data. Types are 
completely uninterpreted by the server; they are solely for the benefit of clients. 

viewable 

A window is viewable if it and all of its ancestors are mapped. This does not imply 
that any portion of the window is actually visible, since it may be obscured by oth- 
er windows. 
visible A region of a window is visible if someone looking at the screen can actually see it; 
that is, the window is viewable and the region is not obscured by any other win- 
dow. 
visual The specifications for color handling for a window, including visual class, depth, 
RGB/pixel, etc., are collectively referred to as a visual, and are stored in a structure 
of type Visual. 
visual class 
Visual class refers to DirectColor, GrayScale, PseudoColor, 
StaticColor, StaticGray, or TrueColor. It is a definition of the color- 
map type but not its depth. 
widget The basic object in a toolkit, a widget includes both code and data, and can there- 
fore serve as an input or output object. 
window gravity 
When windows are resized, subwindows may be repositioned automatically by the 
server, relative to an edge, coner, or center of the window. This attraction of a 
subwindow to some part of its parent is known as window gravity. Window gravity 
is a window attribute. See also bit gravity. 
window manager 
The user manipulates windows on the screen using a window manager client. The 
window manager has authority over the arrangement of windows on the screen, and 
the user interface for selecting which window receives input. See also redirect. 

Glossary 549 



XYPixmap 
The data for an image is said to be in XYPixmap format if it is organized as a set of 
bitrnaps representing individual bit planes. This applies only to the server's inter- 
nal data format for images. It does not affect normal programming with pixmaps. 

ZPixmap 
The data for an image is said to be in ZP/xmap format if it is organized as a set of 
pixel values in scan line order. This applies only to the server's internal data for- 
mat for images. It does not affect normal programming with pixmaps. 

zoomed window 
Some applications have not only a normal size for their top-level window and an 
icon, but also a zoomed window size. This could be used in a painting program 
(similar to the MacPaint TM fat bits). The zoomed window size preferences can be 
specified in the window manager hints. 

550 

X Toolkit Intrinsics Programming Manual 



Master Index 

The Master Index combines Volumes Four and Five index entries, making it 
easy to look up the appropriate references to a topic in either volume. PM 
refers to the X Toolkit Intrinsics Programming Manual. RM refers to the X 
Toolkit Intrinsics Reference Manual. 



! (see modifiers) 
# directive (see translations) 
A 
accelerators about, PM:59, 152, 
193, 211-217, 265,531 
adding, PM:212 
and translations; conflicts with, 
PM:215; 
translation table limitations, 
PM:213 
compiling accelerator table, 
RM:274 
defining default table in code, 
PM:216 
event propagation, PM:213 
for gadgets, PM:383 
for menus, PM:379, 383 
installing, PM:211; RM:242-244; 
in multiple widgets, PM:215 
not usable in gadgets, PM:386 
(see also methods, disjglay_accel- 
erator; Xfl.nstallAccelerators.) 
accept_focus method PM:404; 
RM:387, 473 
accepts_objects field PM:394 
access contro! list PM:531 
action hooks PM:408 
actions PM:47, 49, 365,369,394, 
411 
about, PM:29, 32, 41-42, 531; 
RM:637 
action proc format, PM:48 
actions table; about, PM:531 ; 
XtActionProc, RM:374-375 
adding to widget, PM:46 
arguments to, PM: 114 

Index 

con,-asted with ,:allbacks, 
PM:49, 114 
defined in widget plementa- 
tion file, PM: 148-149 
gadget parent example, 
PM:393-394 
in gadgets, PM:386 
naming conventions, PM:45 
passing arguments to, PM: 114 
registering with Translation Man- 
ager, RM:63-64 
using event data, PM:229 
widget instance pointer, PM: 190 
widget/application conflicts, 
PM: 148 
(see also XtAddActions; XtAp- 
pAddActions; XtMenuPop- 
down; XtMenuPopup.) 
actions table adding, PM:46-47; 
RM:63-64, 81-82 
declaring/registering with 
Resource Manager, RM:81-82 
example, PM:48 
format, PM:48 
(see also actions.) 
active grab PM:364 
aliasing font names PM:457 
AlmostProc RM:439 
Alt key PM:202 
(see also modifiers.) 
ancestor PM:532 
anonymous ftp PM:36 
application applica- 
tionShellWidgetClass, 
RM:452-460 
application contexts PM:102 
about, PM:102, 410-413,532 
adding display, RM: 188-189 
creating, PM: 102; RM: 168 

Index 553 



class_part_initialize method 
PM:156, 339, 342, 394; 
RM:477 
client about, PM:6, 534 
client-server model, PM:6 
ClientMessage event 
RM:656-657 
clipping region PM:534 
color PM:58, 121,159-160, 
265-266, 290 
determining available, PM:450 
displaying, PM:450 
false, PM:291 
hexadecimal specification, 
PM:448 
names, PM:447 
RGB model, PM:449 
specifying, PM:447 
colorceli PM:450 
about, PM:534 
read-only, PM:451 
read/write, PM:451 
shared, PM:451 
(see also colormap.) 
colormap about, PM:58, 450 
installing, PM:290 
virtual, PM:290 
window attribute, PM: 159 
(see also events, ColormapNo- 
tify.) 
colormap about, PM:534 
colormap window attribute 
PM:291 
ColormapNotify event 
RM:656-658 
command buttons PM:424,426, 
436 
command line compiling, PM:36 
options (see options) 
Command widget PM:19, 39, 
41-44, 49, 69, 79, 106, 212, 
214-216, 365-371,374, 378, 
424-426, 436 
compiling Xt PM:36 
Composite XtOrderProc proto- 
type procedure, RM:407 
composite widgets about, PM:16, 
321,437, 534 
as parent and child, PM:332 
class, PM:16, 139; 
about, PM.'21, 65; 
XtNinsertPosition resource, 
PM:335 

general purpose, PM:429, 440 
importance, PM:428 
initial size, PM:325 
inserting children, PM:335 
management, PM:322 
menus and control areas, PM:437 
reasons for writing, PM:321 
resources, PM:ix; 
(see also resources.) 
subclass; XtlsComposite, 
RM:246 
using within other widgets, 
PM:322 
(see also methods, insert_child.) 
compound widgets PM:351-352 
compression filters (see events, 
event f'dters) 
ConfigureNotify event 
RM:659-660 
ConfigureRequest event 
RM:661-662 
connection PM:535 
constants (defined) XtCacheAll, 
RM:638 
XtCacheByDisplay, RM:638 
XtCacheNone, RM:638 
XtCacheRefCount, RM:638 
Constraint destroy method, 
RM:481 
initialize method, RM:496 
set_values method, RM:513-514 
constraint widgets PM:ix; 
RM:434-437, 434 
about, PM:72, 321,535; 
RM:434-437 
class, PM:139; 
about, PM:23; 
part, PM:340; 
refiguring child locations, 
PM:344-347 
management, PM:336-351,336 
part structure, PM:338 
resources, PM:73-74, 338; 
RM:434-437; 
example, PM:73-74 
writing, PM:336 
XtIsConstraint, RM:247 
(see also methods, Constraint 
destroy; methods, set_values; 
resources.) 
consulting PM:525 

556 X Toolkit Intrinsics Programming Manual 



containment PM:535 
conventions action function 
names, PM:45 
application-defaults file, PM:34, 
38 
callback function names, PM:45 
font naming, PM:453 
for Xtlnherit constants, PM:158 
gadget internals, PM:388 
instance variables order, PM: 142 
keysym naming, PM: 199 
public function names, PM: 116 
resource; class, PM: 147; 
names, PM:147, 248; 
representation types, PM: 147 
widget; internals, PM:138; 
source file names, PM: 138; 
structure declarations, PM: 143, 
164-165 
conversion caching PM:271 
converters PM:263-278,411 
color name to pixel value, 
PM:122, 265, 290 
Convert.h, PM:273 
explicitly invoking, PM:274-275 
fontname to font, PM:265 
function pointer to callback list, 
PM:270 
int to Boolean, PM:266 
mt to Dimension, PM:266 
mt to float, PM:266 
mt to font, PM:266 
mt to pixel, PM:266 
mt to pixmap, PM:266 
mt to Position, PM:266 
mt to short, PM:266 
mt to unsigned char, PM:266 
mt to XColor, PM:266 
Pixel to XColor, PM:266 
registering, RM:69, 83-85; 
case converter, PM:247; 
RM:290 

string 
strmg 
stung 
strmg 
strmg 
strmg 
strmg 
stung 
strmg 
strmg 
strmg 

to bitmap, PM:269 
to boolean, PM:265 
to cursor, PM:265,269 
to Dimension, PM:265 
to Display, PM:265 
to file descriptor, PM:265 
to float, PM:265 
to geometry, PM:265 
to initial state, PM:265 
to int, PM:265 
to orientation mode, 

PM:269 
string to Position, PM:265 
string to short, PM:265 
string to translation table, 
PM:265 
string-to-justify mode, PM:269 
widget name to widget ID, 
PM:269 
XColor to Pixel, PM:266 
(see also XtAppAddConverter; 
XtSetTypeConverter.) 
coordinate system PM:4, 535 
Core PM:152 
class part; fields, RM:484; 
initializing, PM: 151 - 153; 
initializing example, 
PM:151-152 
class structure; in gadgets, 
PM:388 
Core widget class, PM: 139; 
RM:438-442, 661-662; 
about, PM:535 
CoreClassPart structure, PM: 141 
CorePart structure, PM: 141 
fields, PM: 152; 
compress_enterleave, PM: 153, 
242; 
compress_exposure, PM: 153, 
176, 242; 
compress_motion, PM: 153, 
242; 
display_accelerator, PM: 152; 
extension, PM: 153; 
superclass, PM: 152; 
tin_table, PM: 153; 
version, PM: 153; 
visible_interest, PM: 153,237; 
widget_size, PM: 152; 
xrm_class, PM: 153; 
(see also methods, set_val- 
ues_hook.) 
instance record; height field, 
PM:325; 
width field, PM:325 
instance; setting size, PM:120 
methods, RM:442 
widget class, PM:17, 57; 
about, PM:20; 
class pointer, PM: 120; 
drawing into from application, 
PM:119-120; 
hidden superclasses, PM:158; 
instance default size, PM: 120; 

Index 557 



resources, PM:57; 
superclasses, PM:387; 
widgetClass class pointer, 
PM: 120 
(see also methods; methods, 
class_initialize; methods, 
class_part_initialize; methods, 
initialize.) 
Core widget PM:17, 118, 197 
drawing into, PM:119 
updating, PM: 122 
counter incrementing inside 
XtSetArg, PM:55 
CreateNotify event RM:663-664 
Ctrl key PM:202 
(see also modifiers.) 
cursor about, PM:159, 265,535 
hotspot, PM:539 
cursor window attribute 
PM: 159 
cut and paste (see selections) 
D 
data PM:546 
data transfer completion method, 
RM:412 
data types, RM:631 
(see also structures.) 
database obtaining for display, 
RM: 179 
(see also XtDatabase.) 
DECNet PM:295 
decoration PM:33, 293 
default multiple click timing 
PM:207 
default size PM:184 
delete_child method PM:322; 
RM:478 
depth PM:58, 173,535 
descendants PM:535 
destroy method PM:157, 169, 
187; RM:479 
about, PM: 187 
Constraint, PM:340 
example from BitmapEdit, 
PM: 187 
DestroyNotify event RM:665 
destructors PM:271 
details in translations (see trans- 

lations) 
device PM:536 
dialog boxes PM:384 
cascading, PM:384 
grabs in, PM:384 
without grabs, PM:384 
Dialog widget PM:21, 75, 79, 
351-352 
popping up, PM:75 
DirectColor PM:536 
directories font, PM:452 
display about, PM:6, 536 
adding; XtOpenDisplay, 
RM:266-267 
closing, RM: 139 
connecting to multiple displays, 
PM:413 
depth, PM:450 
display lists, RM:483 
initializing, RM: 188-189 
lists, PM:175 
XtCloseDisplay, RM: 139 
(see also XtDisplayIrtitialize.) 
DISPLAY environment variable 
PM:58 
display option (-display), PM:93 
display pointer returning for 
widget, RM: 187 
display_accelerator method 
PM:216; RM:482 
distributed processing PM:7 
DoesBackingStore Xiib macro 
PM: 159 
DoesSaveUnders Xlib macro 
PM:159 
double clicks PM:46, 206-207 
downward chaining PM:154 
drawing about, PM:121,142, 
153-155, 169, 175-178 
after Expose event, PM: 156 
bitmap cells, PM:163 
coordinate system, PM:4 
due to set_values method 
changes, PM: 180 
in expose method, PM:170 
into Core widget, PM: 119-120 
window attributes, PM:158-159 
drop-down menu PM:359, 371 
example, PM:373 
vs. spring-loaded, PM:360 

558 X Toolkit Intrinsics Programming Manual 



E 
elements (see array) 
encapsulation PM:31,536 
enter/leave compression 
PM:242 
EnterNotify event PM:200-201, 
242, 365-366; RM:666-671 
EnterWindow event PM:222 
environment variables DIS- 
PLAY, PM:58 
XAPPLRESD1R, PM:253 
XENV1RONMENT, PM:254 
error database obtaining, 
RM:96-98, 205-206 
error handling PM:96, 100, 
399-402 
and application contexts, PM:402 
calling fatal error handler, 
RM:193-195 
calling fatal error handler (high- 
level), RM:93-94 
error resource database, PM:401; 
obtaining, RM:95; 
XtAppGetErrorDatabase, 
RM:95; 
XtAppGetErrorDatabaseText, 
RM:96-98; 
XtGetErrorDatabase, RM:205; 
XtGetErrorDatabaseText, 
RM:206 
levels, PM:400 
method, RM:394 
procedure, RM:395-396 
redef'ming handlers, PM:401 
string conversion warnings, 
PM:402 
XtAppError, RM:92 
XtAppErrorMsg, RM:93-94 
XtAppGetErrorDatabase, RM:95 
XtAppGetErrorDatabaseText, 
RM:96-98 
XtAppSetErrorHandler, RM: 109 
XtAppSetERrorMsg Handler, 
RM:I10 
XtError, RM: 193 
XtErrorMsg, RM: 194-195 
XtGetErrorDatabase, RM:205 
XtGetErrorDatabaseText, 
RM:206 
XtSetErrorHandler, RM:314 
XtSetErrorMsgHandler, RM:315 

errors error procedure 
fatal error handler; calling (high- 
level), RM:93-94, 194-195 
fatal error procedure; calling 
(low-level), RM:92; 
registering, RM:109-110, 314 
listing, RM:703 
nonfatal error procedure; calling, 
RM:116; 
registering, RM:114-115,329 
string conversion error message, 
RM:333 
(see also XtAppError; XtAppEr- 
rorMsg; XtAppSetEr- 
rorHandler; XtAppSetEr- 
rorMsgHandler; 
XtAppSetWar- 
ningMsgHandler; XtError; 
XtErrorHandler; XtErrorMsg; 
XtErrorMsgHandler; XtSetEr- 
rorHand; XtSetErrorMsg- 
Hand; XtSetWar- 
ningMsgHandler.) 
event handlers PM:32, 222-227 
about, PM:30, 221,536 
adding, PM:222, 224-226; 
RM:398 
dispatching, RM: 186 
for nonmaskable events, 
PM:225-226 
procedure, RM:397-398, 
400-401 
raw, PM:227; 
registering raw, RM:76-77; 
removing raw, RM:302-303 
reasons to use, PM:222 
registering, RM:70-71 
removing, RM:298-299 
XtAddEventHandler, RM:70-71 
XtAddRawEventHandler, 
RM:76-77 
XtRemoveEventHandler, 
RM:298-299 
XtRemoveRawEventHandler, 
RM:302-303 
(see also XtDispatchEvent; 
XtEventHandler; Xtln- 
putCallbackProc.) 
event masks about, PM:222 
retrieving, RM:120-121 
XtBuildEventMask, RM: 120-121 

Index 559 



event processing RM:107 
XtAppProcessEvent, RM: 107 
events about, PM:10, 195 
accessing specific data, RM:649 
as argument of action, PM:49 
border crossing, RM:666-671 
ButtonPress, PM:201,366; 
RM:651-653 
ButtonRelease, PM:201,366; 
RM:651-653 
cancelling source, RM:301 
CirculateNotify, RM:654 
CirculateRequest, RM:654-655 
ClientMessage, RM:656-657 
ColormapNotify, RM:656-658 
ConfigureNotify, RM:659-660 
ConfigureRequest, RM:661-662 
CreateNotify, RM:663-664 
DestroyNotify, RM:663-665 
dispatching handlers, RM: 186 
EnterNotify, PM:200-201,242, 
365-366 
EnterWindow, PM:222 
event compression, PM:536 
event data; example of using in 
an action, PM:228 
event filters, PM:153, 178, 242 
event loop (see main loop) 
event masks; about, 
PM:536-537; RM:632 
event members; common, 
RM:650 
event propagation, PM:537 
event queue, PM:241 
event sequences, PM:210 
event source, PM:537 
event structure, PM:227 
event-driven programming, 
PM:IO-11 
event_mask window attribute, 
PM:159 
expose, PM: 10 
Expose, PM:25, 116, 123, 125, 
153, 156, 237, 242, 366; 
RM:672-673 
Focusln, PM:200, 222, 405,537; 
RM:674-679 
FocusOut, PM:200, 222, 405; 
RM:674-679 
frozen event, PM:538 
GraphicsExpose, PM:197, 226; 
RM:680-681 
GravityNotify, RM:682 

560 

in action routines, PM: 125 
in gadgets, PM:386 
input events; XtRemovelnput, 
RM:301 
KeymapNotify, RM:683 
KeyPress, PM:201,406; 
RM:684-686 
KeyRelease, PM: 198, 201 
LeaveNotify, PM:200-201,242, 
365-366; RM:666-671 
list of types and structure names, 
PM:229-230 
MapNotify, RM:687-688 
MappingNotify, RM:689-690 
MapRequest, RM:691 
mocking up from action, 
PM:175; RM:483 
MotionNotify, PM:201,207, 222, 
242, 366; RM:692-694 
next event; returning, RM:262 
NoExpose, PM: 197; 
RM:680-681 
nonmaskable, PM:195,213, 
224-226, 541; 
example of handlers, PM: 195, 
213,224 
processing, RM:243 
processing one event; XtPro- 
cessEvent, RM:283 
propagation, PM:213 
PropertyNotify, RM:695 
ReparentNotify, RM:696 
ResizeRequest, RM:697 
returning next event, RM: 103 
selecting, PM:213 
SelectionClear, PM:2940 304; 
RM:698 
SelectionNotify, PM:294, 305, 
310; RM:699 
SelectionRequest, PM:294, 296, 
305-306; RM:700 
structures, RM:650 
translation table abbreviations, 
PM:196-197 
using inside actions or event han- 
dlers, PM:227-228; RM:375 
VisibilityNotify, PM: 153, 197; 
RM:701-702 
XEvent; example, PM:228; 
RM:375; 
union, RM:649 
XtAppNextEvent, RM: 103 
XtAppPending, RM:106, 278 

X Toolkit Intrinsics Programming Manual 



unused Core fields in, 
PM:390-391 
games PM:234 
GCs (see graphics contexts) 
geometry management 
PM:69-70, 287, 322, 335; 
RM:431-433 
about, PM:35, 181,183-186, 
321-352, 538; RM:641 
border width, PM:322 
changes, RM:244-246 
changing (XtMakeGeometryRe- 
quest), PM:325; RM:244-246 
composite resource, PM:335 
compound widgets, PM:351-352 
constraint class part, PM:340 
constraint management, PM:336 
delaying recalculation, PM:351 
height, PM:325 
initial geometry negotiation, 
PM:324 
inserting children, PM:335 
minimal useful size, PM:330 
querying, RM:284-286; 
preferred geometry, 
PM:332-333; 
XtQueryGeometry, 
RM:284-286 
resizing, PM:321 
scope, PM:322 
size preferences, PM:333 
stacking order, PM:322, 352 
trickle-down, PM:333 
unmanaging widget, PM:332 
width, PM:325 
(see also methods; XtDes- 
troyWidget.) 
geometry option (-geometry), 
PM:93 
geometry_manager method 
RM:487 
get_values hook method 
PM:15-7, 216, 279, 479; 
RM:225, 491-492 
globalvarlables PM:79, 82 
glyph PM:538 
grabs about, PM:363,531,538; 
RM:641 
active vs. passive, PM:364 
adding or removing explicitly, 
PM:385 
exclusive vs. nonexclusive, 
PM:364, 377 

global, PM:364 
grab modes, PM:377 
in dialog boxes, PM:384 
keyboard, PM:363 
passive, PM:364, 542 
pointer, PM:363 
reasons for in menus, PM:365 
XtAddGrab, RM:73-74 
XtRemoveGrab, RM:300 
graphics PM:121 
graphics primitive, PM:538 
(see also graphics contexts.) 
graphics contexts about, 
PM:121,142, 159, 538 
caching, PM:170, 173 
changing, PM:173, 180 
creating, PM: 170, 172-174 
deallocating, RM:293 
destroying, RM: 181 
exclusive or logical function, 
PM:302 
freeing, PM:180, 187; RM:181 
hardcoding values in, PM:174 
obtaining, RM:207-208 
read-only, PM: 173 
reasons for, PM:121 
setting with resources, PM:174 
(see also XtDesla'oyGC; 
XtGetGC; XtReleaseGC.) 
GraphicsExpose event RM:72, 
680-681 
GraphicsExpose events PM:226 
gravity PM:538 
GravityNotlfy event RM:650, 
682 
GrayScale PM:538 
Grip widget PM:20, 70 
H 
hardcoding resources, PM:40, 
97, 99 
u'anslations, PM:51 
header files PM:32, 54, 59, 231, 
387, 464 
not included twice, PM: 141 
private, PM:543 
public, PM:543 
height PM:325 
checking in initialize method, 
PM:170 

562 X Toolkit Intrinsics Programming Manual 



IntrinsicP.h header file, PM: 145 
selection tirneout, RM: 112 

K 

key events (see events or transla- 
tions) 
key translation registering, 
RM:318 
XtKeyProc, RM:402-404 
XtSetKeyTranslator, RM:318 
keyboard (see also 
accept_focus.) 
keyboard focus PM:289; 
RM:473 
about, PM:288, 404-405 
accept/reject method, RM:387 
redirecting input, RM:316-317 
setting, PM:289 
styles, PM:289, 540 
window, RM:674 
(see also accept__focus; XtNinput 
resource; XtSetKeyboard- 
Focus.) 
keyboard grabbing (see grabs) 
keyboard mapping RM:689 
keyboard shortcuts (see acceler- 
ators) 
keycodes about, PM:198,406, 
540 
translating; keycode-to-keysym, 
RM:337-340; 
XtTranslateKey, RM:337-338; 
XtTranslateKeycode, 
RM:339-340 
KeymapNotify event RM:683 
KeyPress event PM:201 
KeyRelease event PM:201; 
RM:684-686 
keysyms about, PM:198, 406, 
540 
converting case, PM:205; 
RM:379-380 
determining case, RM:167 
key generated, PM:203 
keysymdef.h header file, 
PM: 199, 202 
naming conventions, PM: 199 
XtCaseProc, RM:379-380 
XtConvertCase, RM: 167 

Label widget PM:19, 30, 75, 118, 
181,248, 323,366, 464 
Label.h f'de, PM:31 
labels setting, PM:53 
language portability PM:52 
layout Form method PM:340 
LeaveNotify event PM:200-201, 
242, 365-366 
LeaveWindow event PM:222, 
374, 378 
lint PM:45 
List widget PM:20, 436 
class, PM:20, 222 
loose bindings PM:252, 540 

M 
macros PM:403-404 
main loop PM:32, 36 
customizing example, PM:241 
internals, PM:241 
XtAppMainLoop, RM: 102 
XtMainLoop, RM:243 
MapNotify event RM:687-688 
mapping PM:197 
about, PM:59, 540 
button, RM:689 
keyboard, RM:689 
pop-up shell; XtPopup, 
RM:280-281 
unmapping pop-up shell; XtPop- 
down, RM:279 
widgets; XtMapWidget, RM:252 
(see also MappingNotify event; 
widget, mapping.) 
MappingNotify event 
RM:689-690 
MapRequest event RM:691 
mechanism without policy 
PM:10, 283 
memory allocation PM:408 
for widget instance record, 
PM:152 
menus about, PM:36, 357-395, 
428 
accelerators in, PM:379, 383 
cascaded, PM:359, 374-379 
drop-down, PM:359, 371-373; 
example, PM:372-373 
operation of, PM:361 

564 X Toolkit Intrinsics Programming Manual 



panes in, PM:361 
pointer grabbing, PM:363, 365 
popping down, PM:363, 371, 
379; 
MenuPopdown, RM:253 
popping up, PM:369; 
MenuPopup, RM:254-255 
popping up with callbacks, 
PM:371 
pull-down, PM:359 
SirnpleMenu widget, example, 
PM:380, 382 
spring-loaded, PM:359, 363 
XtMenuPopdown action, 
PM:365 
XtMenuPopup action, PM:365 
messages about, PM:31,541 
OOP vs. Xt, PM:31 
Meta key PM:202 
methods about, PM:155-157, 541 
accept_focus, PM: 156, 404-405; 
RM:473; 
about, PM:531 
and instance structure, PM: 139 
change_managed, PM:322-324, 
332, 349; RM:474; 
about, PM:533; 
in constraint widgets, 
PM:349-350 
class_initialize, PM: 156, 270, 
394; RM:476; 
about, PM:534 
class_part_initialize, PM: 156; 
RM:477 
Constraint; destroy, RM:481; 
initialize, PM:342; RM:496 
Constraint set_values, 
RM:513-514 
constraint widgets; destroying, 
PM:340; 
initializing, PM:341; 
resizing, PM:347 
constraint_destroy, RM:437 
declarations in widget irnplemen- 
tation file, PM: 150 
delete_child, PM:322, 335; 
RM:478; 
about, PM:535 
destroy, PM:157, 169, 187, 340; 
RM:479; 
about, PM:536; 
example, PM: 187 
display_accelerator, PM:216; 

RM:482 
drawing; due to changes in 
set_values, PM: 180; 
in expose, PM:170 
expose, PM:31,156, 169-170, 
175-178, 226, 537; 
RM:484-485; 
in gadget parent, PM:391-392; 
in gadgets, PM:386, 391; 
XtExposeProc, RM:438, 
483-486 
Form layout, PM:340 
gadget; expose, PM:391; 
query_geometry, PM:391; 
set_values_almost, PM:391 
geometry_manager, 
PM:322-323, 343; RM:487 
get_values_hook, PM: 157, 216, 
279, 479; RM:491-492, 491, 
517; 
about, PM:538; 
example, PM:279; RM:491 
in OOP, PM:31 
inheritance; adding to super- 
class, PM: 160; 
of superclass, PM: 157 
initialize, PM:155, 169-174, 170, 
341; RM:493-495; 
about, PM:539; 
calling XlnternAtom, 
PM:169-174, 170, 328; 
example, PM:170, 172; 
in constraint widget, PM:341 
initialize_hook, PM: 155,279; 
about, PM:539 
insert_child, PM:322; RM:491, 
499; 
about, PM:539 
insert_position, PM:335; 
RM:499 
layout Form, PM:340 
not known to Xt, PM:340 
query_geometry, PM:157, 169, 
184-186, 322; RM:501; 
about, PM:169, 184-186, 322, 
544; 
in constraint widget, 
PM:329-330, 351; 
in gadgets, PM:350, 391 
realize, PM:156, 288, 328; 
RM:505-507; 
about, PM:544 
reconciliation, PM: 160 

Index 565 



PseudoColor PM:543 
public functions PM: 161 
about, PM: 107 
naming conventions, PM: 116 
reasons to use, PM:109 
public header file PM:32, 391 
BitmapEdit.h, PM: 138, 160-162 
public instance variables (see 
resources) 
public routines PM:351 
pull-down menu PM:359 
Q 
quarks PM:276, 543 
query_geometry method 
PM:157, 184-186, 391; 
RM:501 
about, PM: 184 
example from BitmapEdit, 
PM: 186 
gadgets in, PM:391 
in gadgets, PM:350-351 
R 
raise PM:544 
raw event handlers PM:227; 
RM:76-77 
(see also events.) 
realization PM:35 
about, PM:176, 180 
realize method PM:154, 159, 
288, 328, 480; RM:505-507 
about, PM:157 
RealizeProc RM:438 
rectangle PM:544 
RectObj class PM:158, 387, 390; 
RM:423, 448-451 
RectObjClass RM:450 
RectObjClassPart RM:449 
RectObjCiassRec RM:450 
RectObjPart RM:450 
RectObjRec RM:450 
redrawing windows PM:25, 175 
reference pages list, RM:617 
regions PM:178, 392; RM:72, 
485 
registering callbacks, RM:65-66; 
list, RM:67-68 
converters, PM:269-274; RM:69, 

568 

83-85,290 
event handlers, PM:224-226; 
RM:70-71 
fatal error condition procedure, 
RM:l10,314 
fatal error procedure, PM: 156, 
399-402; RM: 109 
file, RM:75, 86-87 
nonfatal error condition proce- 
dure, RM:114, 315, 329, 331 
nonfatal error procedure, 
PM:399-402; RM: 115 
raw event handler, RM:76-77 
work procedure, RM:79, 89 
registering/declaring actions 
(see actions) 
Release 4 (R4) PM:i, 36, 116, 
200, 289, 357, 359, 385, 414 
compared to R3, PM:467-493 
initialize_hook and set_val- 
ues_hook obsolescence, 
RM:491,497 
removing callbacks, 
RM:295-297 
grabs, RM:300 
input, RM:301 
raw event handlers, RM:302-303 
timeouts, RM:304 
reparenting PM:544 
about, PM:293, 373 
(see also window manager.) 
ReparentNotify event RM:696 
reply PM:544 
representation type PM:86, 88 
about, PM:247, 249, 545 
reslze method PM:169, 181-183, 
322; RM:508 
about, PM: 181 
example from BitmapEdit, 
PM: 183 
in gadgets, PM:393 
ResizeRequest event RM:697 
reslzlng PM:322 
about, PM:690 169, 181-183,321 
caching old size, PM: 183 
parent widget, RM:508 
(see also events, ResizeRequest; 
methods, resize.) 
resource conversion, RM:184 
resource database obtaining for 
display, RM: 179 
(see also XtDatabase.) 

X Toolkit Intrinsics Programming Manual 



resource list copying; from 
ArgList, RM:323-324 
copying to argument list, 
RM:223-224 
copying; (see also XtGetSub- 
values; XtSetSubvalues.) 
default values; retrieving, 
RM:211-212 
retrieving; (see also 
XtGetResourceList.) 
updating, RM:201-203; 
by name or class, RM:221-222 
(see also XtGetSubResources; 
XtGetApplicationResources.) 
Resource Manager (see actions) 
resources about, PM:23-24, 34, 
38, 52, 57, 59, 248-251,545; 
RM:431-432 
and set_values method, 
PM:178-181 
application, PM:85 
caching, PM:271 
changing value, PM: 178 
checking validity, PM: 170 
classes and instances, PM:88 
comment character in files, 
PM:253 
constraint, PM:73; RM:434-437 
copying; from ArgList to widget, 
RM:327-328; 
from widget to argument list, 
RM:225-226; 
XtGetValues, RM:225-226; 
XtSetValues, RM:327-328 
default address; interpreting, 
PM:251 
default value; converting, " 
PM:267; 
setting, PM:88,267 
def'med by Core, PM:57 
def'med in widget implementa- 
tion file, PM:145, 147-148 
def'ming characteristics, 
PM:88-89 
defining in widget, PM:145, 
147-148 
fallback, PM:258 
Form widget, PM:73,337 
format; of def'mitions, 
PM:252-253 
getting from application, PM:52 
hardcoding advantages, PM:40 
in instance record, PM: 142 

inheritance of, PM:52, 145, 
147-148 
interactions between, PM:60, 62; 
example, PM:60 
loading; from .Xdefaults file, 
PM:60; 
with xrdb, PM:60 
looking up values, PM:251-263 
loose bindings, PM:252 
name, PM:88 
naming conventions, PM:248 
precedence rules, PM:260-263 
representation types, PM:86, 88, 
249 
resource conversion, PM:88; 
converters in Xmu, PM:266; 
method, RM:408; 
registering, PM:270; 
XtConverter, RM:383-386; 
(see also XtResourceDe- 
faultProc.) 
resource database, PM:545; 
sources, PM:253 
resource file format, RM:709 
resource list; declaring, PM:248; 
example, PM:87-88; 
format, PM:88-89 
Resource Manager, PM:545 
resource setting, PM:545 
resource value; getting, PM:57 
retrieving; application resources, 
PM:90-91; 
resource default at run-time, 
PM:268 
RESOURCE_MANAGER property, 
PM:254 
setting; for multiple widgets, 
PM:68; 
for widget hierarchy, PM:68; 
in application, PM:52; 
with XtSetValues, PM:54; 
XtNinput, PM:290 
size, PM:251 
sources priority, PM:254 
specifications, PM:260-263,545; 
errors in, PM:39; 
format, PM:39-40; 
merging of duplicate, 
PM:253-255; 
wildcards in, PM:252 
symbolic constants, PM:40, 54 
tight bindings, PM:252 
type conversion, PM:40, 263-278 

Index 569 



type converter, XtConvert, 
RM:142-143 
types table, PM:249 
use of classes, PM:249 
XtN constants, PM:160 
XtNaccelerators (Core), PM:58 
XtNallowShellResize (Shell), 
PM:286 
XtNancestorSensitive (Core), 
PM:58 
XtNargc (Shell), PM:285-286 
XtNargv (Shell), PM:285-286 
XtNbackground (Core), PM:58 
XtNbackgroundPixmap (Core), 
PM:58 
XtNbaseHeight (Shell), 
PM:286-287 
XtNbasewidth (Shell), PM:286 
XtNbaseWidth (Shell), PM:287 
XtNborderColor (Core), PM:58 
XtNborderPixmap (Core), PM:58 
XtNborderWidth (Core), PM:58 
XtNcolormap (Core), PM:58 
XtNcreatePopupChildProc 
(Shell), PM:285 
XtNdefaultDistance (Form), 
PM:336 
XtNdepth (Core), PM:58 
XtNdestroyCallback (Core), 
PM:44, 58 
XtNgeometry (Shell), 
PM:285-286, 288 
XtNheight (Core), PM:58 
XtNheightlnc (Shell), 
PM:286-287 
XtNhorizDistance (Constraint), 
PM:336 
XtNiconic (Shell), PM:285, 287 
XtNiconMask (Shell), PM:286 
XtNiconName (Shell), PM:286, 
292 
XtNiconPixmap (Shell), PM:286, 
292 
XtNiconWindow (Shell), 
PM:286 
XtNiconX (Shell), PM:285,287 
XtNiconY (Shell), PM:285,287 
XtNinitialState (Shell), PM:286 
XtNinput (Shell), PM:286, 
288 -290 
XtNinsertPosition (Composite), 
PM:335 
XtNmappedWhenManaged 

(Core), PM:58, 332 
XtNmaxAspectX (Shell), 
PM:286-287 
XtNmaxAspectY (Shell), 
PM:286-287 
XtNmaxHeight (Shell), 
PM:286-287 
XtNmaxWidth (Shell), 
PM:286-287 
XtNminAspectX (Shell), 
PM:286-287 
XtNminAspectY (Shell), 
PM:286-287 
XtNminHeight (Shell), 
PM:286-287 
XtNminWidth (Shell), 
PM:286-287 
XtNoverrideRedirect (Shell), 
PM:285-286 
XtNpixmap (Core), PM: 118 
XtNpopdownCallback (Shell), 
PM:371 
XtNpopupCallback (Shell), 
PM:371,373 
XtNsaveUnder (Shell), PM:286 
XtNscreen (Core), PM:58 
XtNsensitive (Core), PM:58 
XtNtitle (Shell), PM:285,292 
XtNtransient (Shell), 
PM:285-286 
XtNtranslations (Core), PM:49, 
51, 58, 114 
XtNvertDistance (Constraint), 
PM:336 
XtNwaitForWm (Shell), 
PM:285-286 
XtNwidth (Core), PM:58 
XtNwidthlnc (Shell), 
PM:286-287 
XtNwindowGroup (Shell), 
PM:285-286 
XtNwmTimeout (Shell), 
PM:285-286 
XtNx (Core), PM:58 
XtNy (Core), PM:58 
(see also resource list.) 
resources conversion 
XtDirectConverk RM: 184 
reverse option (-rv/+rv) PM:93 

570 X Toolkit Intrinsics Programming Manual 



structure of Xt applications 
PM:32 
subclass PM:19 
about, PM:548 
submenus PM:377 
cascading, PM:379 
creating, PM:376 
popping up, PM:84, 375 
(see also XtPopup.) 
subparts PM:152, 157,278-280 
subresources PM:152, 157, 
278-280 
managing, PM:279-280 
Super key PM:202 
(see also modifiers.) 
superclass PM:152, 179 
about, PM:lg, 548 
class structure, PM: 140 
gadget, PM:390 
inheritance, PM:59 
of Core, PM:387 
synchronous option (-synchro- 
nous/+synchronous), PM:93 
syntax functions PM:96 
T 
TCP/IP PM:295 
Text widget PM:20-21, 79, 153, 
294, 433, 443 
tight bindings PM:252,548 
tilde PM:204 
tiling PM:58 
about, PM:548 
time PM:548 
timeouts about, PM:234 
adding, PM:234 
and visibility interest, PM:237 
callback method, RM:413 
example, PM:235-236 
invoking procedure after timeout, 
RM:88 
removing, PM:236-237 
selection timeout; setting, 
RM:321; 
value, RM:99, 112, 214 
XtAddTimeout, RM:78 
XtAppAddTimeOut, RM:88 
XtAppSetSelectionTimeout, 
RM:112 
XtGetSelectionTimeout, RM:99, 
214 

XtRemoveTimeOut, RM:304 
XtSetS electionTimeout, RM:321 
XtTimerCallbackProc, RM:413 
timing multiple clicks, PM:207 
title option (-rifle), PM:93 
toolkits initializing internals, 
RM:335 
initializing toolkit and display, 
RM:234-238 
Xtlnitialize, RM:234-238 
XtToolkitlnitialize, RM:335 
top-level 
topLevelShellWidgetClass, 
RM:452-460 
widget, PM:34; 
(see also Shell widget.) 
window, PM:548 
topLevelSheliWidgetCiass 
PM:284 
training PM:525 
TransientSheliWidgetClass 
PM:75 
transientSheliWidgetClass 
PM:79 
TransientSheliWidgetClass 
PM:284 
transientSheliWidgetClass 
RM:452-460 
Translation Manager (see 
actions) 
translations PM:213 
# augment directive, PM:50 
[ modifier symbol, PM:205 
# override directive, PM:50 
# replace directive, PM:50 
about, PM:29, 41, 46, 49, 59, 548 
augmenting, PM:50-51 
colon modifier symbol, 
PM:205-206 
compiling; table, RM:275-276; 
when widget class initialized, 
PM:149; 
XtParseTranslationTable, 
RM.'275-276 
defining; default in Core class 
part, PM:153; 
in source, PM:51 
details in, PM: 198-201 
differences between directives, 
PM:195 
double-clicks, PM:206 
event abbreviations, PM: 196-197 
event sequences, PM :206-208 

Index 573 



determining subclass, RM:235; 
obtaining, RM: 138; 
Shell widget subclass, RM:234; 
verifying, RM:137; 
XtCheckSubclass, RM: 137; 
XtClass, RM:138; 
XtlsComposite, RM:246; 
XtIsConstraint' RM:247; 
XtlsShell, RM:234; 
XtlsSubclass, RM:235 
composite, PM:21 
converting (R3 to R4), PM:467 
creating, PM:32, 85; 
RM:174-176; 
additional top-level widget, 
RM:90-91 
creating additional top-level 
widget, RM: 169 
creating; working window, 
RM: 177-178; 
(see also XtAppCreateShell; 
XtCreateApplicationShell; 
XtCreateMgdWidget; 
XtCreateWidget.) 
declaring class record pointer; 
example, PM: 157 
default size, PM:184 
def'ming conventions, PM: 138, 
252; 
summary, PM: 164 
destroying, PM:28, 84, 187; 
RM:182-183; 
XtDestroyWidget, 
RM:182-183 
display pointer, RM: 187; 
XtDisplay, RM: 187 
dragging, PM:20 
Exclusive and Nonexclusive, 
PM:426 
framework of code, PM: 137-165 
geometry (see geometry manage- 
ment) 
getting data, PM: 107; 
example, PM: 107 
hierarchy; creating, PM:67 
implementation file, PM: 138, 
143-160; 
actions table, PM: 148-149; 
declaration of methods, 
PM:150; 
resources, PM:145, 147-148; 
translation table, PM: 148-149 
installing accelerators (see accel- 

erators) 
instance structure, PM: 170 
internals, PM: 137-165 
Label, PM:270 
macros for, PM:403 
management, PM:65, 184-186; 
RM:248; 
XtlsManaged, RM:248; 
(see also XtManageChild; 
XtManageChildren.) 
managing child, PM: 170-174 
mapping, PM:59; 
changing map_when_managed 
field, RM:319; 
to display, RM:252 
mapping to display; 
XtMapWidget, RM:252 
mapping; windows, PM:36; 
XtSetMappedWhenManaged, 
RM:319 
merging translations, RM: 119 
modal widget; redirecting input, 
RM:73-74, 300; 
XtAddGrab, RM:73-74; 
XtRemoveGrab, RM:300 
moving; XtMoveWidget, 
RM:257 
moving/resizing, PM:58; 
RM:140-141; 
XtConfigureWidget, 
RM:140-141 
naming conventions, PM:463 
necessary include files, PM:138 
parent, PM:113 
parent widget; returning, 
RM:273; 
XtParent, RM:273 
popping down; Menupopdown, 
RM:253 
popping up, PM:80-81; 
Menupopup, RM:254-255 
private header file, PM: 138-143, 
138 
public header f-de, PM: 138, 
160-162 
realizing, PM: 180; RM:231, 
287-288; 
XtlsRealized, RM:231; 
XtRealizeWidget, RM:287-288 
record size, PM:152 
removing, PM:I 6; 
XtUnmanageChild, RM:346; 
XtUnmanageChildren, RM:347 

Index 575 



window manager PM:69-70, 
283-294, 321 
about, PM:11, 33,549 
and decoration, PM:293 
and icons, PM:292-293 
click-m-type, PM:288 
colormaps, PM:290-291 
focusing styles, PM:200 
hints, PM: 11,284-294 
input models, PM:288 
interacting with, PM:284-294 
keyboard focus, PM:288-290 
listener, PM:540 
pointer focus, PM:288 
real estate driven, PM:288, 544 
redirect, PM:544 
reparenting, PM:293,373,544 
save-set, PM:546 
screen layout, PM:287-288 
wrn timeout RM:455 
work procedures about, RM:79 
creating pop up in, example, 
RM:420 
registering, PM:239-240; RM:89 
removing, PM:239; RM:305 
XtAddWorkProc, RM:79 
XtAppAddWorkProc, RM:89 
XtAppRemoveWorkProc, 
RM:305 
(see also XtWorkProc.) 
X 
X about, PM:3 
X Consortium address, PM:526 
X protocol, PM:5, 295 
X source software, PM:521 
XView, PM:9 
X Toolkit (see toolkits) 
XA CLIPBOARD atom 
PM:303 
(see also selections.) 
XA_MULTIPLE property 
PM:316 
XAPPLRESDIR environment 
variable PM:253 
XA PRIMARY atom PM:296, 
303 
(see also selections.) 
XA SECONDARY atom 
PM:303 
(see also selections.) 

XA TARGETS atom PM:306 
(see also selections.) 
Xatom.h file PM:303,305 
Xawlibrary PM:17,38 
xbitmap application PM:106, 
497 
xbitmapl; example, 
PM:106-109 
xbitmap2; example, 
PM: 109-117 
xbitmap3; example, 
PM:118-124 
xbitmap4; example, 
PM:125-134 
XChangeGC Xlib function 
PM: 173 
XChangeKeyboardMapping 
RM:690 
XClearArea Xlib function 
PM:180 
xclipboard PM:315-317 
XConfigureWindow 
RM:661-662, 697 
XConfigureWindow Xlib func- 
tion PM:352 
XConvertSelection RM:699 
XCopyArea Xlib function 
PM:123, 178, 197; RM:485 
XCopyColormapAndFree Xlib 
function PM:291 
XCopyPlane Xiib function 
PM:123, 178, 197; RM:485 
XCreateGC Xlib function 
PM:121,170 
XCreateWindow Xlib function 
PM: 160 
Xdefaults file PM:60 
xedit PM:294 
XENVIRONMENT environment 
variable PM:254 
xev PM:203 
Xext library PM:38 
xfarewell.c example, PM:46-47 
xfd (font displayer) PM:455 
XFlush Xlib function PM:412 
XGCValues structure PM:173 
XGetlconSizes Xlib function 
PM:293 
XGetModifierMapping RM:690 
XGetMotionEvents RM:694 
XGetPointerMapping RM:690 

Index 577 



XtGetSelectionTimeout 
PM:318, 411; RM:214 
XtGetSelectionValue RM:215 
XtGetSelectionValueIncremental 
PM:317; RM:216 
XtGetSelectionValues PM:296, 
304-306, 313,318; 
RM:218-219 
XtGetSelectionValuesIncremen- 
tal RM:220 
XtGetSubresources PM:279; 
RM:221-224 
XtGetSubvalues PM:280; 
RM:223-224 
XtGetValues PM:24, 57, 80, 373; 
RM:225-226, 436 
XtGrabButton PM:365,409; 
RM:227-228 
XtGrabKey PM:365,409; 
RM:229-230 
XtGrabKeyboard PM:409; 
RM:231 
XtGrabNone grab mode 
PM:384 
XtGrabPointer PM:364, 409; 
RM:232 
XtHasCallbacks PM:404; 
RM:233 
XtlMAlternateInput constant 
PM:242 
Xtlmmedlate address mode con- 
stant PM:273 
XtlMTimer constant PM:242 
XtlMXEvent constant PM:242 
Xtlnherit constants, PM:154; 
XtlrtheritDeleteChild, PM:335; 
XtlrtheritGeometryManager, 
PM:333; 
X tlrtheritlnsertChild, PM:335; 
XtlnheritRealize, PM: 158; 
XtlrtheritSetValuesAlmost, 
PM:334 
XtlnheritlnsertChild RM:499 
Xtlnitlalize RM:234-238 
XtlnltlalizeWidgetClass 
RM:239 
XtlnputCallbackProc 
RM:400-401 
XtInsertEventHandler PM:224; 
RM:240 
arguments, PM:224 
when to call, PM:224 

XtInsertRawEventHandler 
RM:241 
XtInstallAccelerators PM:211; 
RM:242-243 
XtInstallAllAccelerators 
PM:211,215; RM:244 
XtInternAtom Xlib function 
PM:303 
XtIsApplicationShell RM:245 
XtIsComposite PM:403; RM:246 
XtIsConstraint RM:247 
XtIsManaged PM:403; RM:248 
XtIsObJect RM:229 
XtIsOverrideSheli RM:230 
XtIsRealized PM:176, 403-404; 
RM:231,484 
XtIsRectObJ RM:232 
XtIsSensitive PM:404; RM:233 
XtIsSheli RM:234 
XtIsSubclass PM:403; RM:235 
XtIsTopLevelShell RM:236 
XtIsTransientShell RM:237 
XtIsVendorShell RM:238 
XtIsWidget RM:239 
XtIsWMSheli RM:240 
XtKeyProc RM:402-404 
function prototype, PM:407 
XtKeysymToKeycodeList 
PM:407; RM:241 
XtLastTimestampProcessed 
RM:242 
XtLoseSelectionIncrProc 
PM:317; RM:405 
XtLoseSelectionProc PM:304; 
RM:406 
XtMainLoop PM:411; RM:243 
XtMakeGeometryRequest 
PM:333; RM:244-246 
XtMakeResizeRequest RM:247 
XtMalloc PM:187, 408; RM:248 
XtManageChild PM:35; RM:249 
XtManageChildren PM:32, 35; 
RM:250-251 
XtMapWidget PM:332; RM:252 
XtMenuPopdown RM:253 
XtMenuPopup PM:369; 
RM:254-255 
argument to, PM:370 
XtMergeArgLists PM:102; 
RM:256 

Index 581 



XtTranslateCoords PM:80, 
372-373; RM:336 
XtTranslateKey PM:407; 
RM:337-338 
XtTranslateKeycode PM:407; 
RM:339-340 
XtTypeConverter RM:414-418 
XtUngrabButton PM:409; 
RM:341 
XtUngrabKey PM:409; RM:342 
XtUngrabKeyboard PM:409; 
RM:343 
XtUngrabPointer PM:364, 409; 
RM:344 
XtUninstalITranslations 
RM:345 
XtUnmanageChild PM:332; 
RM:346 
XtUnmanageChildren PM:332; 
RM:347 
XtUnmapWidget PM.'332; 
RM:348 
XtUnrealizeWidget RM:349 
XtVaAppCreateShell PM'413; 
RM:350 
XtVaApplnitialize PM:32, 34; 
RM:351 
arguments, PM:35 
fallback resources in, PM:257 
shell created, PM:79 
XtVaCreateArgsList RM:352 
XtVaCreateManagedWidget 
PM:32, 35, 142, 251; RM:353 
XtVaCreatePopupShell PM:79, 
360; RM:354 
XtVaCreateW|dget PM:32, 67, 
142, 251; RM:355 
XtVaGetApplicationResources 
RM:356 
XtVaGetSubresources PM:279; 
RM:357 
XtVaGetSubvalues PM:280; 
RM:358 
XtVaGetValues PM:53, 138; 
RM:359 
XtVaSetSubvalues PM:280; 
RM:360 
XtVaSetValues PM:53, 138, 142, 
169-170, 178-181; RM:361 
XtVersion constant PM:153 
XtVersionDontCheck constant 

584 

PM: 153 
XtWarning PM:411; RM:362 
XtWarnlngMsg PM:411; 
RM:363 
XtWidgetBaseOffset address 
mode constant PM:273 
XtWldgetGeometry PM:332, 
335 
XtWidgetGeometry structure 
PM:184-185 
XtWidgetToApplicatlonContext 
PM:236; RM:364 
XtWlndow PM:180, 391; 
RM:365 
XtW|ndowOfObJeet PM:404; 
RM:366 
XtWlndowToWldget PM:404; 
RM:367 
XtWorkProe PM:411; 
RM:419-420 

X Toolkit Intrinsics Programming Manual 



NAME 
COMPANY 
ADDRESS 
CiTY 

STATE ZIP 

NO POSTAGE 
NECESSARYIF 
MAILEDIN THE 
UNITEDSTATES 

BUSINESS REPLY MAIL 

FIRST CLASS MAIL PERMIT NO. 80 SEBASTOPOL, CA 

POSTAGE WILL BE PAID BY ADDRESSEE 
O'Reilly &: Associates, Inc. 
632 Petaluma Avenue 
Sebastopol, CA 95472-9902 

NAME 
COMPANY 
ADDRESS 
CITY 

STATE ZIP 

NOPOSTAGE 
NECESSARYIF 
MAILEDIN THE 
UNITEDSTATES 

BUSINESS REPLY MAIL 

FIRST CLASS MAIL PERMIT NO. 80 SEBASTOPOL. CA 

POSTAGE WILL BE PAID BY ADDRESSEE 
O'Reilly & Associates, Inc. 
632 Petaluma Avenue 
Sebastopol, CA 95472-9902 



Overseas Distributors 

Effective January 1, 1990, customers outside the U.S. and Canada will be able to order Nutshell Hand- 
books, the Pick Series, and the X Window System Series through distributors near them. These overseas 
locations offer international customers faster order processing, more local bookstores and local distribu- 
tors, and increased representation at trade shows worldwide, as well as the high level, quality service our 
customers have always received. 

AUSTRALIA & NEW ZEALAND 
(orders and inquiries) 
Addison-Wesley Publishers, Pty. Ltd. 
6 Byfield Street 
North Ryde, N.S.W. 2113 
AUSTRALIA 
Telephone: 61-2-888-2733 
FAX: 61-2-888-9404 

ASIA inquiries (excluding Japan) 
Addison-Wesley Singapore Pte. Ltd. 
15 Beach Road #05-09/10 
Beach Centre 
Singapore 0718 
SINGAPORE 
Telephone: 65-339-7503 
FAX: 65-339-9709 

UNITED KINGDOM & AFRICA 
(orders and inquiries) 
Addison-Wesley Publishers, Ltd. 
Finchampstead Road 
Wokingham, Berkshire RG 11 2NZ 
ENGLAND 
Telephone: 44-734-794-000 
FAX: 44-734-794-035 

EUROPE & THE MIDDLE EAST 
(orders and inquiries) 
Addison-Wesley Publishers B.V. 
De Lairesscstraat 90 
1071 PJ Amsterdam 
THE NETHERLANDS 
Telephone: 31-20-764-044 
FAX: 31-20-664-5334 

ASIA orders (excluding Japan) 
Addison-Wesley Publishing Co., Inc. 
International Order Department 
Route 128 
Reading, Massachusetts 01867 U.S.A. 
Telephone: 1-617-944-3700 
FAX: 1-617-942-2829 

JAPAN 
(orders and inquiries) 
Toppan Company, Ltd. 
Ochanomizu Square B, 1-6 
Kanda Surugadai 
Chiyoda-ku, Tokyo 101 
JAPAN 
Telephone: 81-3-295-3461 
FAX: 81-3-293-5963 

Maruzen Company, Ltd. 
3-10 Nihonbashi 2-Chome 
Chuo-Ku, Tokyo, 103 
JAPAN 
Telephone: 81-3-272-7211 
FAX: 81-3-274-3238