ibm smalltalk: programmer's reference

550
IBM Smalltalk Programmer’s Reference Version 5.5

Upload: others

Post on 19-Nov-2021

17 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: IBM Smalltalk: Programmer's Reference

IBM Smalltalk

Programmer’s ReferenceVersion 5.5

���

Page 2: IBM Smalltalk: Programmer's Reference

Note

Before using this document, read the general information under “Notices” on page ix.

May 2001

This edition applies to Version 5.5 of the VisualAge Smalltalk products, and to all subsequent releases andmodifications until otherwise indicated in new editions. Make sure you are using the correct edition for the level ofthe product. The term “VisualAge,” as used in this publication, refers to the VisualAge Smalltalk product set.

Portions of this book describe materials developed by Object Technology International Inc. of Ottawa, Ontario,Canada. Object Technology International Inc. is a subsidiary of the IBM® Corporation.

If you have comments about the product or this document, address them to: IBM Corporation, Attn: IBM SmalltalkGroup, 621-107 Hutton Street, Raleigh, NC 27606-6324. You can fax comments to (919) 828-9633.

When you send information to IBM, you grant IBM a nonexclusive right to use or distribute the information in anyway it believes appropriate without incurring any obligation to you.

© Copyright International Business Machines Corporation 1994, 2000. All rights reserved.US Government Users Restricted Rights – Use, duplication or disclosure restricted by GSA ADP Schedule Contractwith IBM Corp.

Page 3: IBM Smalltalk: Programmer's Reference

Contents

Notices . . . . . . . . . . . . . . . ixTrademarks . . . . . . . . . . . . . . ix

About this book . . . . . . . . . . . xiWhat this book includes . . . . . . . . . . xiWho this book is for . . . . . . . . . . . xiAbout this product or feature . . . . . . . . xiConventions used in this book . . . . . . . . xiiReferences. . . . . . . . . . . . . . . xii

Common Language Data Types, CommonLanguage Implementation, and Common ProcessModel . . . . . . . . . . . . . . . xiiCommon File System . . . . . . . . . . xiiiCommon Graphics. . . . . . . . . . . xiiiCommon Widgets . . . . . . . . . . . xiiiCommon Printing . . . . . . . . . . . xivDynamic Data Exchange . . . . . . . . . xivNational Language Support. . . . . . . . xiv

Tell us what you think . . . . . . . . . . xiv

Chapter 1. IBM Smalltalk overview . . . 1Base subsystems . . . . . . . . . . . . . 1

Common Language Data Types . . . . . . . 1Common Language Implementation . . . . . 1Common Process Model . . . . . . . . . 1Common File System . . . . . . . . . . 1Common Graphics . . . . . . . . . . . 2Common Widgets . . . . . . . . . . . 2Extended Widgets . . . . . . . . . . . 2Drag and Drop . . . . . . . . . . . . 2Common Printing . . . . . . . . . . . 2

Design intent . . . . . . . . . . . . . . 2Architecture . . . . . . . . . . . . . . 3Industry-standard support . . . . . . . . . . 3Platform support . . . . . . . . . . . . . 4

Chapter 2. Common Language DataTypes . . . . . . . . . . . . . . . . 5Object behavior . . . . . . . . . . . . . 6

Basic dependents mechanism . . . . . . . . 6Behavior testing . . . . . . . . . . . . 6Class identity testing . . . . . . . . . . 6Copying . . . . . . . . . . . . . . . 6Printing and storing . . . . . . . . . . . 6Performing . . . . . . . . . . . . . . 7Error handling. . . . . . . . . . . . . 7Primitive accessing . . . . . . . . . . . 7Mutating . . . . . . . . . . . . . . 7Testing object equality or identity . . . . . . 7

Boolean classes . . . . . . . . . . . . . 7Boolean messages. . . . . . . . . . . . 7

Collection classes . . . . . . . . . . . . . 8Collection protocols . . . . . . . . . . . 9Common collection protocols . . . . . . . 10Unique collection protocol . . . . . . . . 12

Magnitude classes . . . . . . . . . . . . 13Magnitude comparing . . . . . . . . . . 14Association . . . . . . . . . . . . . 14Character . . . . . . . . . . . . . . 14Date . . . . . . . . . . . . . . . . 16Time. . . . . . . . . . . . . . . . 16Number . . . . . . . . . . . . . . 17Integer . . . . . . . . . . . . . . . 18Fraction . . . . . . . . . . . . . . 19Float. . . . . . . . . . . . . . . . 19ScaledDecimal . . . . . . . . . . . . 20

Graphical classes . . . . . . . . . . . . 20Point . . . . . . . . . . . . . . . 20Rectangle . . . . . . . . . . . . . . 21

Stream classes . . . . . . . . . . . . . 22Accessing . . . . . . . . . . . . . . 23Copying . . . . . . . . . . . . . . 23Enumerating . . . . . . . . . . . . . 23Positioning . . . . . . . . . . . . . 24Reading . . . . . . . . . . . . . . 24Testing . . . . . . . . . . . . . . . 24Truncating . . . . . . . . . . . . . . 24Writing . . . . . . . . . . . . . . . 24Creating instances . . . . . . . . . . . 24

Support classes . . . . . . . . . . . . . 24UndefinedObject. . . . . . . . . . . . 24Message and DirectedMessage . . . . . . . 25Block . . . . . . . . . . . . . . . 25

Exception handling classes . . . . . . . . . 25ExceptionalEvent . . . . . . . . . . . 25Signal . . . . . . . . . . . . . . . 25Creating new exceptions . . . . . . . . . 25Signaling an exception. . . . . . . . . . 26Handling of exceptions . . . . . . . . . 26ExceptionalEvent collections . . . . . . . . 28Completion blocks . . . . . . . . . . . 29Default exception handler . . . . . . . . 30System exceptions . . . . . . . . . . . 30Examples of exception handling . . . . . . 30

Chapter 3. Common LanguageImplementation . . . . . . . . . . . 33Behavior messages . . . . . . . . . . . . 34

Class queries . . . . . . . . . . . . . 34Compiling . . . . . . . . . . . . . . 34Creating instances . . . . . . . . . . . 34Enumeration . . . . . . . . . . . . . 35Instance accessing . . . . . . . . . . . 35Instance structure testing . . . . . . . . . 35Method accessing . . . . . . . . . . . 35Method adding and deleting . . . . . . . 36Method queries . . . . . . . . . . . . 36

Class messages . . . . . . . . . . . . . 36Class variable accessing . . . . . . . . . 37Instance variable accessing . . . . . . . . 37

© Copyright IBM Corp. 1994, 2000 iii

Page 4: IBM Smalltalk: Programmer's Reference

Shared pool accessing . . . . . . . . . . 37Class accessing . . . . . . . . . . . . 37Initializing and removing. . . . . . . . . 38Superclass accessing . . . . . . . . . . 38

Metaclass messages. . . . . . . . . . . . 38Accessing . . . . . . . . . . . . . . 38

Creating new classes . . . . . . . . . . . 38Creating fixed classes . . . . . . . . . . 39Creating variable classes . . . . . . . . . 39Creating variable byte classes . . . . . . . 39

Extended classes. . . . . . . . . . . . . 39Multiple instance accessing . . . . . . . . 40String converting . . . . . . . . . . . 40

Compiling and evaluating code. . . . . . . . 40Compiling . . . . . . . . . . . . . . 41Evaluating. . . . . . . . . . . . . . 41

CompiledMethod . . . . . . . . . . . . 42Accessing . . . . . . . . . . . . . . 42Testing . . . . . . . . . . . . . . . 42

EmSystemConfiguration . . . . . . . . . . 42

Chapter 4. Common Process Model . . 45Creating a process . . . . . . . . . . . . 45Suspending, resuming, and ending a process . . . 46Setting and modifying process priorities . . . . . 46Synchronization using semaphore and delay . . . 47

Block evaluation methods . . . . . . . . 48Process-related block methods . . . . . . . 49Process methods. . . . . . . . . . . . 49ProcessorScheduler methods. . . . . . . . 50Delay class and instance methods . . . . . . 50Semaphore class and instance methods . . . . 51

Chapter 5. Common File System. . . . 53Accessing the capabilities of the Common FileSystem . . . . . . . . . . . . . . . . 53

Basic file protocols . . . . . . . . . . . 53Stream protocols. . . . . . . . . . . . 53Portability protocols . . . . . . . . . . 53Error handling protocols . . . . . . . . . 53CfsConstants pool dictionary . . . . . . . 54Basic classes . . . . . . . . . . . . . 54

Specifying file names and paths . . . . . . . 54Portable file names . . . . . . . . . . . 54File system roots . . . . . . . . . . . 55Path separators . . . . . . . . . . . . 55

Managing files and directories . . . . . . . . 55Current working directory . . . . . . . . 55Creating and removing directories . . . . . . 55Deleting files . . . . . . . . . . . . . 56Renaming files . . . . . . . . . . . . 56Copying files . . . . . . . . . . . . . 56Startup directory . . . . . . . . . . . 57

Obtaining volume information . . . . . . . . 57Volume name and type . . . . . . . . . 57File names and directory path case . . . . . 57File name length. . . . . . . . . . . . 57Volumes with different file name lengths . . . 58

Searching directories . . . . . . . . . . . 58Opening a directory for searching . . . . . . 58

Reading directory entries . . . . . . . . . 59Closing the directory descriptor . . . . . . 61

Using file streams . . . . . . . . . . . . 61File stream classes . . . . . . . . . . . 61Opening and closing file streams . . . . . . 61Reading and writing file streams . . . . . . 62Characters versus bytes . . . . . . . . . 63Line delimiters . . . . . . . . . . . . 63

Using low-level file operations . . . . . . . . 64Opening files . . . . . . . . . . . . . 64Closing file descriptors . . . . . . . . . 65Reading and writing data . . . . . . . . 66Changing the file offset . . . . . . . . . 66Other low-level operations . . . . . . . . 67

Mixing streams and file descriptors . . . . . . 67Using access modes and flags with file streams 67Performing low-level file operations on streams 68

File locking and share modes . . . . . . . . 68File locking . . . . . . . . . . . . . 68Share modes . . . . . . . . . . . . . 70

Handling errors . . . . . . . . . . . . . 71Suppressing system error dialogs . . . . . . 73

Testing existence and obtaining other file properties 74Obtaining a CfsStat instance . . . . . . . . 74

Mixing platform-specific and Common File Systemoperations . . . . . . . . . . . . . . . 76

Performing a platform-specific call with aCfsFileDescriptor . . . . . . . . . . . 76Converting a platform file descriptor into aCfsFileDescriptor . . . . . . . . . . . 76Obtaining platform-specific error information . . 76

Chapter 6. Common Graphics . . . . . 79X Window system graphics library compatibility . . 79Core Common Graphics class hierarchy . . . . . 80Seldom-used and abstract classes . . . . . . . 82A simplified drawing process overview . . . . . 83

Before drawing . . . . . . . . . . . . 83During drawing . . . . . . . . . . . . 83After drawing . . . . . . . . . . . . 83A simple example of the drawing process . . . 83CgConstants pool dictionary. . . . . . . . 83

Using graphics contexts . . . . . . . . . . 84Basic graphics context methods . . . . . . . 84Creating graphics contexts . . . . . . . . 85Copying graphics contexts . . . . . . . . 88Changing graphics contexts . . . . . . . . 89Freeing graphics contexts . . . . . . . . . 89Using graphics contexts with other drawables . . 89

Drawing operations . . . . . . . . . . . 89Drawing points . . . . . . . . . . . . 90Drawing lines . . . . . . . . . . . . 90Drawing rectangles . . . . . . . . . . . 91Drawing polygons . . . . . . . . . . . 92Drawing arcs and circles . . . . . . . . . 92Drawing pie slices and chords using filled arcs 93

Using fonts . . . . . . . . . . . . . . 93A simplified view of the font process . . . . . 94Querying the system for fonts . . . . . . . 95Loading fonts. . . . . . . . . . . . . 97Assigning fonts for use in drawing operations 100

iv IBM Smalltalk: Programmer’s Reference

Page 5: IBM Smalltalk: Programmer's Reference

String drawing operations with fonts . . . . 101Releasing CgFonts and CgFontStructs frommemory . . . . . . . . . . . . . . 102Obtaining the current font from a graphicscontext . . . . . . . . . . . . . . 102

Using cursors . . . . . . . . . . . . . 103The process for using cursors . . . . . . . 103Font cursors . . . . . . . . . . . . . 103Glyph cursors . . . . . . . . . . . . 104Pixmap cursors . . . . . . . . . . . . 105Changing the color of a cursor . . . . . . 105Platform cursors . . . . . . . . . . . 106

Using pixmaps . . . . . . . . . . . . . 106Creating a pixmap using createPixmap:. . . . 107Creating a pixmap usingcreatePixmapFromBitmapData: . . . . . . 107Copying pixmaps to and from windows . . . 108Getting pixmap geometry . . . . . . . . 108Creating a bitmap from bitmap data. . . . . 109Creating stipples using bitmaps . . . . . . 109Writing bitmaps to files . . . . . . . . . 110Reading bitmaps from files . . . . . . . . 111Displaying bitmaps . . . . . . . . . . 111

Common Graphics image support . . . . . . 112Specifying colors . . . . . . . . . . . . 113

Specifying colors as RGB intensities . . . . . 113Specifying colors by name . . . . . . . . 113Parsing a color-specification string . . . . . 114

Using palettes . . . . . . . . . . . . . 114The default palette . . . . . . . . . . 115Creating indexed palettes . . . . . . . . 116From pixel values to colors and back . . . . 116Selecting and drawing with palettes . . . . . 117Direct palettes . . . . . . . . . . . . 120

Device-independent images . . . . . . . . 120Creating and manipulating images . . . . . 121Displaying images. . . . . . . . . . . 122Direct color images . . . . . . . . . . 122Copying images from a drawable . . . . . 123

Icons . . . . . . . . . . . . . . . . 124Creating icons . . . . . . . . . . . . 124Drawing icons . . . . . . . . . . . . 125Loading icons from DLLs . . . . . . . . 125Using operating system icons . . . . . . . 126

Image and icon file formats . . . . . . . . 126Loading images from files . . . . . . . . 127Handling errors . . . . . . . . . . . 127Loading icons from files . . . . . . . . . 128Unloading images into files . . . . . . . 129Unloading icons into files . . . . . . . . 129Unloading images and icons into ByteArrays 130Loading images and icons from ByteArrays . . 130Determining the format of a file . . . . . . 131Extra file format information . . . . . . . 131

Resource management summary . . . . . . . 133

Chapter 7. Common Widgets. . . . . 135OSF/Motif compatibility . . . . . . . . . 135Common Widgets class hierarchy. . . . . . . 135Overview of Common Widgets user interfaceconcepts . . . . . . . . . . . . . . . 137

The parent-child widget tree . . . . . . . 138The widget lifecycle . . . . . . . . . . 138Mapping and unmapping widgets . . . . . 140Managing and unmanaging widgets. . . . . 141Widget resources and functions . . . . . . 141CwConstants pool dictionary . . . . . . . 144Example code to create a widget tree . . . . 144Widget event handling and callbacks . . . . 146Example of using an event handler and acallback . . . . . . . . . . . . . . 146

Creating and using widgets . . . . . . . . 148Widget creation convenience methods . . . . 148Callbacks . . . . . . . . . . . . . . 150Event handlers . . . . . . . . . . . . 154

Shell widgets . . . . . . . . . . . . . 158Top-level shell widgets . . . . . . . . . . 158Scrolled-window widgets . . . . . . . . . 160Main-window widgets . . . . . . . . . . 161

Main windows and geometry management . . 161Text widgets. . . . . . . . . . . . . . 162Drawing area widgets . . . . . . . . . . 164

Adding an event handler to a drawing area . . 166Layout widgets. . . . . . . . . . . . . 167

Form widgets . . . . . . . . . . . . 167Row-column widgets . . . . . . . . . . 169

Button and label widgets . . . . . . . . . 171Static label widgets . . . . . . . . . . 172Push-button widgets . . . . . . . . . . 172Toggle-button widgets . . . . . . . . . 173Radio-button groups . . . . . . . . . . 174Check boxes . . . . . . . . . . . . . 175Icon and pixmap label and button widgets . . 176Application-drawn buttons . . . . . . . . 177

Menus. . . . . . . . . . . . . . . . 178Greying out buttons . . . . . . . . . . 178Simple menus and menu bars . . . . . . . 179Creating a menu bar and pull-down menuusing simple menu protocol . . . . . . . 180Creating a secondary menu using simple menuprotocol . . . . . . . . . . . . . . 181Creating a pop-up menu using simple menuprotocol . . . . . . . . . . . . . . 183Non-simple menus and menu bars . . . . . 184Non-simple menu example . . . . . . . . 184

List widgets . . . . . . . . . . . . . . 185Single selection lists . . . . . . . . . . 186Multiple selection lists . . . . . . . . . 187Scrolled lists . . . . . . . . . . . . . 188

Combo-box widgets . . . . . . . . . . . 189Composite-box widgets . . . . . . . . . . 190

MessageBox widgets . . . . . . . . . . 191SelectionBox widgets . . . . . . . . . . 193Dialog convenience methods . . . . . . . 196

Creating and using prompters . . . . . . . . 197Message prompter. . . . . . . . . . . 198Text prompter . . . . . . . . . . . . 200File selection prompter . . . . . . . . . 200

Extended widgets . . . . . . . . . . . . 201Writing an extended widget . . . . . . . 202Example: a primitive extended widget . . . . 203Example: a composite extended widget. . . . 207

Contents v

Page 6: IBM Smalltalk: Programmer's Reference

Fonts . . . . . . . . . . . . . . . . 211Using the system browser font . . . . . . 212

Colors . . . . . . . . . . . . . . . . 213Clipboard operations . . . . . . . . . . . 213

Examples for using the clipboard . . . . . . 214Platform-integrated drag and drop . . . . . . 215

Target types . . . . . . . . . . . . . 216Transferring data . . . . . . . . . . . 216Drag and drop objects . . . . . . . . . 217Procs . . . . . . . . . . . . . . . 217Common Widgets drag and drop classes . . . 217Drag source widgets and the CwDragContextobject . . . . . . . . . . . . . . . 217Drop site widgets and CwDropSite objects . . 219Data transfer and the CwDropTransfer object 223

The user interface process model . . . . . . . 225The system view . . . . . . . . . . . 226The application programmer’s view . . . . . 228Examples of applications with long-runningoperations . . . . . . . . . . . . . 231

Chapter 8. Extended Widgets . . . . 233Extended Widgets class hierarchy . . . . . . 233EwConstants pool dictionary . . . . . . . . 233Creation convenience methods . . . . . . . 234Extended list widgets. . . . . . . . . . . 234Common resources . . . . . . . . . . . 235Scrolled lists . . . . . . . . . . . . . . 235Drawn list widget . . . . . . . . . . . . 236Icon list widgets . . . . . . . . . . . . 237

Renderables . . . . . . . . . . . . . 238Direct editing of labels . . . . . . . . . 239

Flowed icon list widget . . . . . . . . . . 240Icon area widget . . . . . . . . . . . . 241Table list widget . . . . . . . . . . . . 241

Table list resources . . . . . . . . . . 242Table columns . . . . . . . . . . . . 243Direct editing of cell values. . . . . . . . 245Edit policies . . . . . . . . . . . . . 246

Tree widgets. . . . . . . . . . . . . . 247Icon trees. . . . . . . . . . . . . . 248Table trees . . . . . . . . . . . . . 249

Notebook widgets . . . . . . . . . . . . 250Creating pages . . . . . . . . . . . . 250Callbacks . . . . . . . . . . . . . . 250PM notebook widget . . . . . . . . . . 251WIN notebook widget . . . . . . . . . 253

Progress bar widget . . . . . . . . . . . 253Slider widget . . . . . . . . . . . . . 254Spin button widget . . . . . . . . . . . 256Split window widget . . . . . . . . . . . 257Tool bar widget . . . . . . . . . . . . 259

Creating tools . . . . . . . . . . . . 259Using tools . . . . . . . . . . . . . 260

Chapter 9. Drag and Drop . . . . . . 263Drag and drop adapters . . . . . . . . . . 263Sequence of events . . . . . . . . . . . 264

Voting and cursors . . . . . . . . . . 267Source vote and image changes . . . . . . 268

Leaving a target . . . . . . . . . . . 268Dropping. . . . . . . . . . . . . . 268Canceling a drag . . . . . . . . . . . 269

System configuration . . . . . . . . . . . 269Simple drag and drop . . . . . . . . . . 270Widget limitations . . . . . . . . . . . . 270

Chapter 10. Common Printing . . . . 273Common Printing classes . . . . . . . . . 273Printing process overview . . . . . . . . . 274

Selecting a printer . . . . . . . . . . . 274Configuring print job attributes . . . . . . 275Creating a print job . . . . . . . . . . 275

Using the printer prompter . . . . . . . . . 275Print job attributes. . . . . . . . . . . 276

Using a printer shell . . . . . . . . . . . 276Creating a shell. . . . . . . . . . . . 277Adding callbacks . . . . . . . . . . . 277Starting a job . . . . . . . . . . . . 278Producing a page . . . . . . . . . . . 278Ending a job. . . . . . . . . . . . . 279CwPrinterShell resources and conveniencemethods . . . . . . . . . . . . . . 279

Printing with Common Graphics . . . . . . . 279A complete example . . . . . . . . . . . 280Setting up printers and queues on UNIX platforms 282

Configuring printer setup options . . . . . 283Printer configuration information. . . . . . 284

Chapter 11. IBM Smalltalk VirtualMachine API . . . . . . . . . . . . 285Who should read this chapter . . . . . . . . 285

Conventions . . . . . . . . . . . . . 285IBM Smalltalk C programming model . . . . . 286

Defined types . . . . . . . . . . . . 286Object types . . . . . . . . . . . . . 286Macros versus functions . . . . . . . . . 288

External language interface . . . . . . . . . 288Parameter types . . . . . . . . . . . 288Calling a PlatformFunction . . . . . . . . 290Inline external function calls . . . . . . . 290PlatformFunction protocols . . . . . . . . 291PlatformLibrary protocols . . . . . . . . 293

Entry points . . . . . . . . . . . . . . 294Parameter types and return types . . . . . 295Calling an EsEntryPoint . . . . . . . . . 296EsEntryPoint protocols . . . . . . . . . 297

Asynchronous callouts . . . . . . . . . . 298Calling a Platform Function asynchronously . . 298Locking resources for an asynchronous call . . 301ACO errors and error cases. . . . . . . . 301Walkbacks . . . . . . . . . . . . . 302ACO errors . . . . . . . . . . . . . 302Parameter types and return types . . . . . 303Managing resources . . . . . . . . . . 303Extensions to platform function protocols . . . 305ACO resource manager protocols. . . . . . 306Resource future protocols . . . . . . . . 307Static future protocols . . . . . . . . . 308ACO error protocols . . . . . . . . . . 308

vi IBM Smalltalk: Programmer’s Reference

Page 7: IBM Smalltalk: Programmer's Reference

OSObjects . . . . . . . . . . . . . . 308OSObject subclasses . . . . . . . . . . 308OSObject protocols . . . . . . . . . . 310OSImmediate protocols . . . . . . . . . 310OSBaseType, OSObjectPointer, and OSStructureprotocols . . . . . . . . . . . . . . 311OSStructure protocols . . . . . . . . . 315OSVariableStructure protocols . . . . . . . 315OSBaseType protocols . . . . . . . . . 315ObjectPointer protocols . . . . . . . . . 316Methods available in other classes . . . . . 317

User primitives . . . . . . . . . . . . . 318User primitive tables . . . . . . . . . . 319Functions available in user primitives . . . . 320

Asynchronous messages (interrupts). . . . . . 327Using user primitive functions outside userprimitives . . . . . . . . . . . . . . 328Sample user primitives for IBM Smalltalk . . . . 328Sample callback for OS/2 and Microsoft Windows 330

Example callback code . . . . . . . . . 330Smalltalk code that uses the primitive above 332

Platform requirements . . . . . . . . . . 333OS/2 . . . . . . . . . . . . . . . 333Microsoft Windows 95, Windows 98, andWindows NT . . . . . . . . . . . . 334Pascal16 and cdecl16 PlatformFunctions . . . 334Pascal16 and cdecl16 pointer conversion . . . 335UNIX platforms . . . . . . . . . . . 335Solaris platforms . . . . . . . . . . . 336

Primitive error codes . . . . . . . . . . . 336

Chapter 12. Dynamic data exchange 339Introduction . . . . . . . . . . . . . . 339DDE concepts and definitions . . . . . . . . 339DDE classes . . . . . . . . . . . . . . 342

DdeClient class . . . . . . . . . . . . 342DdeServer class . . . . . . . . . . . 343DdeServerManager class. . . . . . . . . 343DdeCallbackData class . . . . . . . . . 343

Building a DDE server . . . . . . . . . . 344Building a DDE server that uses defaultprocessing . . . . . . . . . . . . . 344Building a DDE server that does not use defaultprocessing . . . . . . . . . . . . . 347Discussion of the DdeServerManager . . . . 352

Building a DDE client . . . . . . . . . . 357An example DDE client . . . . . . . . . 358Discussion of the DdeClient . . . . . . . 359

Formats of data transferred between DDE serversand clients . . . . . . . . . . . . . . 362Callbacks for handling DDE events . . . . . . 362

Return values . . . . . . . . . . . . 363DDE protocols . . . . . . . . . . . . . 364

DdeServerManager public class methods . . . 364DdeServerManager public instance methods . . 364DdeClass public instance methods . . . . . 367DdeServer public instance methods . . . . . 368DdeClient public instance methods . . . . . 369Protocols common to DdeServer and DdeClient 371

Converting Smalltalk objects to a ByteArray andback . . . . . . . . . . . . . . . . 372

Test cases. . . . . . . . . . . . . . . 372Spreadsheet . . . . . . . . . . . . . 373Spreadsheet window coordinates . . . . . . 373Two windows exchanging data . . . . . . 373Updating time and date . . . . . . . . . 374Updating time in the String format . . . . . 374

Platform-specific support . . . . . . . . . 374

Chapter 13. National LanguageSupport . . . . . . . . . . . . . . 377Overview of IBM Smalltalk National LanguageSupport . . . . . . . . . . . . . . . 377

NLS concepts and definitions . . . . . . . 377The POSIX locale model . . . . . . . . . 379Overview of internationalization . . . . . . 379Overview of localized messages . . . . . . 380Overview of message catalogs . . . . . . . 382Locating message catalogs . . . . . . . . 382National Language Support classes . . . . . 383Support for double-byte characters . . . . . 383Obtaining Locale, LCCType, and LCCollateobjects. . . . . . . . . . . . . . . 384Obtaining LCMessages, LCMonetary,LCNumeric, and LCTime objects . . . . . . 385NLS-enabled classes . . . . . . . . . . 386Locale-specific sorting . . . . . . . . . 387Number formatting . . . . . . . . . . 387Locale change notification and the imagestartup sequence . . . . . . . . . . . 388

Tools for developing international software . . . 389Loading externalization tools . . . . . . . 389Using message templates . . . . . . . . 389Referencing and initializing localized messages 391Overview of the message localization process 392Using message catalogs . . . . . . . . . 393Using external message dictionaries . . . . . 394Using indexed external messages . . . . . . 397Deleting locales from a message catalog file . . 398Support for extended locales . . . . . . . 399Compatibilities . . . . . . . . . . . . 400Compression . . . . . . . . . . . . 402Limitations . . . . . . . . . . . . . 403Error detection and description . . . . . . 403Support for platform resource formats . . . . 405Localization support API . . . . . . . . 408

IBM Smalltalk locale names. . . . . . . . . 411Manual localization . . . . . . . . . . . 412

LCCollate . . . . . . . . . . . . . 412LCMessages . . . . . . . . . . . . . 413LCMonetary. . . . . . . . . . . . . 413LCNumeric . . . . . . . . . . . . . 414LCTime . . . . . . . . . . . . . . 414Locale . . . . . . . . . . . . . . . 414

Locales and platform representation . . . . . . 415OS/2 Presentation Manager . . . . . . . 415Microsoft Windows . . . . . . . . . . 418AIX, HP-UX, and Solaris . . . . . . . . 420

Chapter 14. Inter-processcommunication . . . . . . . . . . 425

Contents vii

Page 8: IBM Smalltalk: Programmer's Reference

UNIX environment . . . . . . . . . . . 425Method specification . . . . . . . . . . 425Usage example . . . . . . . . . . . . 426

UNIX process . . . . . . . . . . . . . 427Method specification . . . . . . . . . . 428Usage example . . . . . . . . . . . . 430

UNIX pipe stream . . . . . . . . . . . . 431UNIX read pipe stream method specification 431UNIX write pipe stream method specification 434

Chapter 15. Object Linking andEmbedding (OLE) . . . . . . . . . 437OLE concepts and definitions . . . . . . . . 438OLE classes . . . . . . . . . . . . . . 440

OleMainWindow . . . . . . . . . . . 440OlePrimitive. . . . . . . . . . . . . 441OleClient . . . . . . . . . . . . . . 441OleControl . . . . . . . . . . . . . 442OleAutomationObject . . . . . . . . . 442OleFile . . . . . . . . . . . . . . 442

Building an OLE document container . . . . . 442Creating an OLE main window . . . . . . 443Creating OLE clients . . . . . . . . . . 444Enabling clipboard operations . . . . . . . 449Creating an object verb menu . . . . . . . 451Invoking the Links dialog . . . . . . . . 454Saving and retrieving an OLE client . . . . . 455

Using OLE automation . . . . . . . . . . 457Creating OLE Automation Objects . . . . . 458Invoking methods of OLE automation objects 458

Getting and setting properties . . . . . . . 459Releasing an OLE automation object. . . . . 460

Using OLE custom controls (OCXs) . . . . . . 460Creating the OLE main window . . . . . . 461Creating OCXs . . . . . . . . . . . . 461Implementing an ambient-property handler . . 462Using automation aspects of an OCX . . . . 463Implementing event handlers . . . . . . . 464Wrapping OCXs with extended widgets . . . 466Using licensed OCXs . . . . . . . . . . 467

Appendix A. Widget resources andcallbacks . . . . . . . . . . . . . 469

Appendix B. Extended widgetsresources and callbacks . . . . . . 491

Appendix C. Drag and drop resourcesand callbacks . . . . . . . . . . . 513

Appendix D. Common graphicsplatform differences . . . . . . . . 515

Appendix E. Common widgetsplatform differences . . . . . . . . 517

Index . . . . . . . . . . . . . . . 525

viii IBM Smalltalk: Programmer’s Reference

Page 9: IBM Smalltalk: Programmer's Reference

Notices

References in this publication to IBM products, programs, or services do not implythat IBM intends to make these available in all countries in which IBM operates.Any reference to an IBM product, program, or service is not intended to state orimply that only that IBM product, program, or service may be used. Anyfunctionally equivalent product, program, or service that does not infringe any ofthe intellectual property rights of IBM may be used instead of the IBM product,program, or service. The evaluation and verification of operation in conjunctionwith other products, except those expressly designated by IBM, are theresponsibility of the user.

IBM may have patents or pending patent applications covering subject matter inthis document. The furnishing of this document does not give you any license tothese patents. You can send license inquiries, in writing, to the IBM Director ofLicensing, IBM Corporation, 500 Columbus Avenue, Thornwood, NY, USA 10594.

IBM may change this publication, the product described herein, or both.

TrademarksThe following terms are trademarks of the IBM Corporation in the United States orother countries or both:

AIX® IBM International Business MachinesOS/2® VisualAge® Presentation Manager®

The following terms are trademarks of other companies:

HP-UX Hewlett PackardMicrosoft® Microsoft CorporationOCX Microsoft CorporationOLE Microsoft CorporationSun Solaris Sun MicrosystemsWindows® Microsoft CorporationWindows NT® Microsoft Corporation

Windows is a trademark of Microsoft Corporation.

UNIX® is a registered trademark in the United States and other countries licensedexclusively through X/Open Company Limited.

© Copyright IBM Corp. 1994, 2000 ix

Page 10: IBM Smalltalk: Programmer's Reference

x IBM Smalltalk: Programmer’s Reference

Page 11: IBM Smalltalk: Programmer's Reference

About this book

This book provides reference information for the IBM Smalltalk developmentenvironment.

What this book includesThis book is designed to explain the concepts and functionality of the IBMSmalltalk subsystems. Some subtle or seldom-used aspects of each subsystem arenot described in this book.

“Chapter 1. IBM Smalltalk overview” on page 1 provides you with a generalunderstanding of how IBM Smalltalk is structured, and should be read first. Eachof the remaining chapters describes a specific IBM Smalltalk subsystem and can beread in any order.

Because IBM Smalltalk is based on several industry standard programminginterfaces, familiarity with these standards is helpful, although not essential, tounderstanding the IBM Smalltalk subsystems. An understanding of the X WindowSystem Xlib graphics model is helpful when programming Common Graphicsoperations. Similarly, familiarity with the X Toolkit Intrinsics (Xt) and theOSF/Motif Widget set (Xm) is helpful when programming Common Widgets. TheCommon File System is based on POSIX.1 (UNIX) file system interfaces. TheCommon Language Data Types, Common Language Implementation, andCommon Process Model are primarily based on the interfaces described in theSmalltalk-80 ″Blue Book″ and IBM ″Red Book.″

Who this book is forThis book is intended to be used by programmers who want to do the following:v Become familiar with the base functionality provided by IBM Smalltalk.v Interface to other languages or write custom primitive operations.v Exchange data between applications in the style of a client/server architecture.v Develop international software.

It is assumed that the reader has previous programming experience and a workingknowledge of the following:v Object-oriented programming conceptsv The Smalltalk programming languagev The IBM Smalltalk programming environment

About this product or featureVisualAge enables you to quickly make client/server applications.

VisualAge makes you more productive by providing interactive visualprogramming tools and a set of parts that represent the client/server spectrum.You create applications by assembling and connecting parts. In many cases, you donot even have to write code.

If you do need to write code, VisualAge provides a state-of-the-art, integrateddevelopment environment. The programming language you use is Smalltalk, anindustry-standard, highly productive, pure object-oriented language.

© Copyright IBM Corp. 1994, 2000 xi

Page 12: IBM Smalltalk: Programmer's Reference

Conventions used in this bookThis book uses several conventions that you might not have seen in other productmanuals.

Tips and environment-specific information are flagged with icons:

Shortcut techniques and other tips

VisualAge for OS/2

VisualAge for Windows

VisualAge for UNIX platforms

These highlighting conventions are used in the text:

Highlightstyle Used for Example

Boldface New terms the first time they areused

VisualAge uses construction fromparts to develop software byassembling and connecting reusablecomponents called parts.

Items you can select, such as pushbuttons and menu choices

Select Add Part from the Optionspull-down. Type the part’s class andselect OK.

Italics Special emphasis Do not save the image.

Titles of publications Refer to the VisualAge Smalltalk User’sGuide.

Text that the product displays The status area displays Category:Data Entry.

VisualAge programming objects, suchas attributes, actions, events, compositeparts, and script names

Connect the window’saboutToOpenWidget event to theinitializeWhereClause script.

Monospacefont

VisualAge scripts and other examplesof Smalltalk code

doSomething| aNumber aString |aNumber := 5 * 10.aString := 'abc'.

Text you can enter For the customer name, type JohnDoe

ReferencesThe following are suggested references for IBM Smalltalk programmers.

Common Language Data Types, Common LanguageImplementation, and Common Process Model

A. Goldberg and D. Robson, Smalltalk-80: The Language and Its Implementation (the″Blue Book″), Addison-Wesley, 1983

xii IBM Smalltalk: Programmer’s Reference

Page 13: IBM Smalltalk: Programmer's Reference

Giffin Lorimer, Dieter Neumann, Rick DeNatale, and Yen-Ping Shan, SmalltalkPortability: A Common Base (the ″Red Book″), IBM International Technical SupportCenters, 1992, GG24-3903 (proposed as a draft ANSI Smalltalk standard)

Common File SystemFred Zlotnick, The POSIX.1 Standard, A Programmer’s Guide, Benjamin/Cummings,Redwood City, Calif., 1991

Common GraphicsJames L. Conger, Windows API Bible: The Definitive Programmer’s Reference, NewYork, N.Y., Waite Group Press, 1992

Brian Myers and Eric Hamer, Mastering Windows NT Programming, New York, N.Y.,SyBex, 1993

Ney ed., Xlib Programming Manual, Volume One, O’Reilly & Associates, Inc.,Sebastopol, Calif., 1988

Nye ed., Xlib Reference Manual, Volume Two, O’Reilly & Associates, Inc., Sebastopol,Calif., 1988

Scheifler and Gettys, X Windows System, 2nd ed., Digital Press

Steve Rimmer, Bit-Mapped Graphics, 2nd ed., New York, N.Y.: Wincrest/McGraw-Hill, 1993

Steve Rimmer, Supercharged Bitmapped Graphics, 1st ed., New York, N.Y.,Wincrest/McGraw-Hill, 1992

An Aldus/Microsoft Techinical Memorandum, revision 5.0 Redmond, Wash., AldusCorporation and Microsoft Corporation, 1988

Frieze Graphics Technical Reference Manual (including information for Publisher’sPaintbrush, PC Paintbrush Plus, and PC Paintbrush), ZSoft Corporation

Presentation Manager Programming Reference Volume III, OS/2 2.0 Technical Library,IBM, 1992

X11R4 and X11R5 reference manuals

Any other manuals discussing the X Window System’s graphics capabilities (Xlib).

Common WidgetsAsente and Swick, X Window System Toolkit, Digital Press

Eric F. Johnson and Kevin Reichard, Power Programming... Motif (Second Edition),New York, N.Y., MIS Press, 1993

Nye and O’Reilly, X Toolkit Intrinsics Programming Manual — OSF/Motif Eidtion,Volume Four, Sebastopol, Calif., O’Reilly & Associates, Inc., 1990

Nye and O’Reilly, X Toolkit Intrinsics Reference Manual, Volume Five, Sebastopol,Calif., O’Reilly & Associates, Inc., 1990

About this book xiii

Page 14: IBM Smalltalk: Programmer's Reference

Open Software Foundation, OSF/Motif Programmer’s Reference — Revision 1.1,Englewood Cliffs, N.J., Prentice Hall, 1990–1991

Open Software Foundation, OSF/Motif Programmer’s Guide— Revision 1.1,Englewood Cliffs, N.J., Prentice Hall, 1990–1991

Common PrintingAxel Deininger, ″An X Print Server-Bringing WYSIWYG to X,″ The X Resource, X(April 1994), 141

Uniforum, CDE Snapshot #1 CD-ROM, October 1993

Uniforum, CDE Snapshot #1 CD-ROM, April 1994

Dynamic Data ExchangeIBM OS/2 Programming Guide

Microsoft Win32 Application Programming Reference

National Language SupportDonald Lewine, POSIX Programmer’s Guide: Writing Portable UNIX Programs,Sebastopol, Calif., O’Reilly & Associates, Inc., 1991

National Language Design Guide, Designing Enabled Products, Volume 1, 2nd ed., IBMreference SE09–8001–01

National Language Support Reference Manual, Volume 2, 2nd Ed., IBM referenceSE09–8001–01

X/Open Portability Guide, XSI Supplementary Definitions, X/Open Company Ltd.,Englewood Cliffs, N.J., Prentice Hall, 1989

Tell us what you thinkThe VisualAge Smalltalk web site has a comment form. Please take a few momentsto tell us what you think about this book. The only way for us to know if you aresatisfied with our books or if we can improve their quality is through feedbackfrom customers like you.

xiv IBM Smalltalk: Programmer’s Reference

Page 15: IBM Smalltalk: Programmer's Reference

Chapter 1. IBM Smalltalk overview

VisualAge is a development environment designed to support the easy creation ofsoftware applications on multiple platforms. IBM Smalltalk provides aplatform-independent application program interface (API) based on industrystandards. VisualAge was built using IBM Smalltalk.

Comprising nine subsystems, IBM Smalltalk encompasses the functionalityrequired by most Smalltalk applications. Applications programmed entirely inaccordance with the IBM Smalltalk interface specification run without modificationon all supported platforms, yet adopt the native look and feel of the particularplatform. This enables applications to be produced from a single code base acrossmultiple platforms, while still providing a high degree of platform integration.

IBM Smalltalk directly utilizes the native functionality provided by each platform.IBM Smalltalk emulates API functionality not directly supported by a particularplatform in order to support a complete and consistent interface across allsupported platforms. As part of the implementation of IBM Smalltalk, access toplatform-specific functionality is also provided.

Base subsystemsIBM Smalltalk comprises nine subsystems:

Common Language Data TypesThe Common Language Data Types (CLDT) subsystem contains the classes andassociated methods for working with standard Smalltalk objects such as Collection,Magnitude, Boolean, and Stream.

Common Language ImplementationThe Common Language Implementation (CLIM) subsystem contains the classesand associated methods which, together with the virtual machine, implement theSmalltalk class and message mechanisms. In most cases, the implementation ofCLIM is inseparably tied to the virtual machine and includes Behavior, Class,Compiler, and CompiledMethod. (The virtual machine is the program that providesthe Smalltalk execution environment on a single machine. It maps data and logic tothe executing machine architecture, isolating the Smalltalk code from thearchitecture of the machine.)

Common Process ModelThe Common Process Model (CPM) subsystem contains the classes and associatedmethods that facilitate the execution and arbitration of multiple execution contexts,or Smalltalk processes.

Common File SystemThe Common File System (CFS) subsystem contains the classes and associatedmethods for performing file and directory operations.

© Copyright IBM Corp. 1994, 2000 1

Page 16: IBM Smalltalk: Programmer's Reference

Common GraphicsThe Common Graphics (CG) subsystem contains the classes and associatedmethods for performing low-level graphics operations, such as drawing lines,circles, and rectangles and for manipulating device independent images, fonts, andcolors.

Common WidgetsThe Common Widgets (CW) subsystem contains the classes and associatedmethods for constructing application user interfaces through the composition ofuser interface components called widgets.

Extended WidgetsThe Extended Widgets (EW) subsystem contains the classes and associatedmethods for expanding on graphical user interfaces built using the CommonWidgets subsystem.

Drag and DropThrough the Drag and Drop (DD) subsystem, pluggable drag and drop support isprovided for the widgets in both Common Widgets and Extended Widgetssubsystems without requiring modifications to the widgets. The Drag and Dropsubsystem uses the portable CG and CW subsystems.

Common PrintingThe Common Printing (CP) subsystem contains the classes and associated methodsfor performing printer job and page control, setup, and graphical and text output.

Design intentThe increasing number of platforms supporting graphical user interfaces hasresulted in a demand for simultaneous deployment of applications on multipleplatforms. At the same time, applications are expected to adopt platform look andfeel standards in order to be accepted by end users. One-shot porting is not aviable option, because maintenance becomes very difficult if applications cannot besingle sourced. Applications need to meet the following requirements:v It must be possible to single source applications across diverse platforms.v Applications must conform to the look and feel standards of each platform.v For maximum performance and platform integration, applications must leverage

native functionality wherever possible.v Programmers capable of developing portable applications are in increasing

demand. It is expensive for organizations to move their development teams tonew, non-standardized software technologies. There is a growing emphasis onsoftware standards as a means to maximize the return on investment whentraining developers.

IBM Smalltalk addresses these requirements by providing a fully documented APIthat supports the same functionality on all platforms. This environment offers acommon interface through which developers can make use of API functionalityregardless of the operating system or hardware in use. Using IBM Smalltalk,software developers can create applications that are fully portable betweensupported platforms and that provide full support for platform look and feel.

2 IBM Smalltalk: Programmer’s Reference

Page 17: IBM Smalltalk: Programmer's Reference

ArchitectureThe following diagram provides a conceptual view of the IBM Smalltalkarchitecture. The lowest level represents the specific target platform. The targetplatform consists of a particular hardware platform and operating system. Theoperating system might have built-in capabilities for graphical user interfaces, or itmight be augmented by support packages such as OSF/Motif and the X WindowSystem.

IBM Smalltalk provides the virtual machine layer implemented for the targetplatform. IBM Smalltalk is built on the native capabilities of the platform, togetherwith additional platform-specific classes and methods developed in order tosupport the full IBM Smalltalk API.

Developers working in the IBM Smalltalk environment have the capabilities of alllayers at their disposal to use as the needs of the product and organization dictate.Of course, developers sacrifice portability when they make use of the layers belowthe common classes and methods. However, even in such cases, they can use thedevelopment environment to identify and control non-portable parts of theapplication.

IBM Smalltalk virtual machine

Application classes andmethods Development environment

Platform interface classes and methods

Common classes and methods

Platform-specific classes and methods

AIXOSF/Motif

OS/2PM

MicrosoftWindows

...platforms

Industry-standard supportUnlike most Smalltalk class libraries that were developed in the absence ofstandards, IBM Smalltalk was developed based on existing industry software andhardware standards. The use of these standards is a major benefit to developmentteams because it means that Smalltalk developers can use the same terminologyand application protocols used in other languages. This reduces the need forvendor-specific Smalltalk documentation and training for the base class libraries,window systems, file systems, and graphics and process models. It also leverages acorporation’s investment in standards training and documentation.

IBM Smalltalk is based on the following industry standards:v The X Window Systemv OSF/Motifv POSIX.1v Smalltalk-80: The Language and Its Implementation (commonly referred to as the

“Blue Book” because of its distinctive cover)v Smalltalk Portability: A Common Base(proposed as a draft ANSI Smalltalk standard

and often referred to as the “Red Book”)

Chapter 1. IBM Smalltalk overview 3

Page 18: IBM Smalltalk: Programmer's Reference

The following table lists the subsystems and the standards upon which they arebased.

Table 1. Industry Standards

IBM Smalltalk Subsystem Based on These Industry Standards

Common Language Data Types Smalltalk-80 Blue Book and IBM Red Book

Common Language Implementation Smalltalk-80 Blue Book and IBM Red Book

Common Process Model Smalltalk-80 Blue Book

Common File System POSIX.1 and Smalltalk-80 Blue Book

Common Graphics X Window System

Common Widgets OSF/Motif

Common Printing X Window System

Although not essential, familiarity with the above standard interfaces is helpful tounderstanding and using the IBM Smalltalk subsystems.

Platform supportIBM Smalltalk supports a wide variety of hardware and operating systems. In eachcase, the implementation emphasizes those capabilities of the platform that arestandardized, efficiently implemented, or essential to achieving native look andfeel. For example, the native widgets provided by OSF/Motif are used as theunderlying implementation of the standard widgets on those platforms supportingOSF/Motif. Similarly, Windows controls are used on the Microsoft Windowsplatform.

Wherever possible, the required functionality is mapped directly to the equivalentplatform capability. Where the specified functionality is not provided by theplatform, it is emulated to support portability.

4 IBM Smalltalk: Programmer’s Reference

Page 19: IBM Smalltalk: Programmer's Reference

Chapter 2. Common Language Data Types

The Common Language Data Types subsystem (CLDT) provides aplatform-independent interface and implementation for the basic data types thatform the building blocks of the Smalltalk programming environment. Forconvenience the CLDT classes have been grouped into seven categories: Boolean,collection, magnitude, graphical, stream, support, and exception handling.

The specification for CLDT is based primarily on two sources:v Smalltalk-80: The Language and Its Implementation (the “Blue Book”)v Smalltalk Portability: A Common Base (the “Red Book”)

All data types in the CLDT subsystem are concrete classes, that is, they are meantto be instantiated and used directly in programs. To avoid constrainingimplementations, no inheritance hierarchy has been defined for CLDT. However,there is a set of basic messages that all the CLDT data types are assumed tosupport. Because in all existing implementations this common behavior isimplemented in class Object, it will be referred to as “Object behavior”. It isconvenient to include a description of Object behavior in this section, even thoughObject itself is not a CLDT data type because it is an abstract class.

Our aim in this section is to provide an overview of CLDT, assuming that readersare generally familiar with Smalltalk.

Note: One of the primary motivations in the design of CLDT was to achievemaximum functionality with minimum complexity. Most inexperiencedSmalltalk developers complain that the class library is too large, needlesslycomplicated, and consequently difficult to learn. There is clearly a trade-offbetween the utility and additional functionality provided by a large library,and the steep learning curve that it entails. The methods in CLDT have beenchosen because they provide real added value, by which we mean that theytruly save developers both time and effort.

In addition, we will occasionally provide some tips to developers who alreadyknow the base Smalltalk/V or Objectworks\Smalltalk dialects, and want to leveragethat knowledge to get up to speed quickly on CLDT. Because these tips areespecially useful when you are porting some existing code to IBM Smalltalk, theseparagraphs are marked by the legend Porting tip.

Porting tip: These tips compare and contrast CLDT with the base classes in theunmodified versions of Smalltalk/V or Objectworks\Smalltalk asshipped by the vendors. Differences between CLDT messages andthose supported in Smalltalk/V or Objectworks\Smalltalk are noted.Many of these differences result from different strategies for errorhandling and other implementation-dependent features. While CLDTsometimes omits a method that is included in either Smalltalk/V orObjectworks\Smalltalk, in most cases the omitted method is eitherrarely used or has a trivial implementation. The preferred Smalltalkprogramming style is to in-line trivial methods; accordingly we havenot cluttered the CLDT class libraries with methods that are seldom ornever used.

© Copyright IBM Corp. 1994, 2000 5

Page 20: IBM Smalltalk: Programmer's Reference

Object behaviorAs noted above, all CLDT classes (indeed, all classes in IBM Smalltalk), arerequired to support the basic Object behavior described in the sections that follow.

Basic dependents mechanismaddDependent:, broadcast:, broadcast:with:, changed, changed:, dependents, release,removeDependent:, update:

Note: For details on the dependents mechanism see Chapter 14 of the Blue Book.The dependents mechanism is really a legacy from earlier Smalltalk graphicsimplementations. It was used to force updates in cases where severalwindows provided views on the same object or several closely relatedobjects. It is no longer used in modern GUI systems like Common Graphicsand Common Widgets. Consequently, we have included only the basicprotocol in CLDT.

Porting tip: All Smalltalk dialects use the same basic messages to implement thedependents mechanism, with one exception: Smalltalk/V does notsupport removeDependent:. Both Smalltalk/V and Objectworks\Smalltalkprovide a number of additional (and different) messages that extendthe basic mechanism.

Behavior testingclass, isKindOf:, isMemberOf:, isNil, notNil, respondsTo:

Class identity testingisCharacter, isClass, isFloat, isInteger, isMetaclass, isDBString, isSBString, isString,isSymbol

Porting tip: The class identity testing messages are all short (and often optimized)forms of:"self class = {NameOfClass}""self isKindOf: {NameOfClass}"

Each Smalltalk dialect has its own list of short forms; the choices areusually driven by implementation details. Smalltalk/V has a largenumber of such methods, while Objectworks\Smalltalk uses only a few.In CLDT we have chosen a middle course. Note that Smalltalk/V usesthe spelling MetaClass rather than the Blue Book spelling Metaclass,which is used in CLDT and Objectworks\Smalltalk.

Copyingcopy

Note: Unlike other Smalltalk implementations, CLDT does not provide a publicdefault version of either deepCopy or shallowCopy in Object protocol. Thesemantics of both these messages are normally specific to each class, andoften to an application.

Printing and storingprintOn:, printString, storeOn:, storeString

6 IBM Smalltalk: Programmer’s Reference

Page 21: IBM Smalltalk: Programmer's Reference

Performingperform:, perform:with:, perform:with:with:, perform:with:with:with:,perform:withArguments:

Porting tip: You should avoid using these methods because they adversely affectthe packaging process. Refer to the guidelines in the packagingmaterials of IBM Smalltalk User’s Guide for more information.

Error handlingdoesNotUnderstand:, error:, primitiveFailed, halt, halt:, shouldNotImplement,subclassResponsibility

Porting tip: These methods provide only the most basic error handling.Smalltalk/V uses implementedBySubclass n place of the Blue Bookmethod subclassResponsibility, and does not support shouldNotImplementor halt:. All Smalltalk dialects provide additional error handlingmethods that are system- and operating system-specific.

Primitive accessingbasicSize, instVarAt:, instVarAt:put:

Mutatingbecome:

Porting tip: The exact semantics of become: (and Array>>multiBecome:) are notconsistent across different Smalltalk platforms, particularly in the useof the two-way become (in which the receiver and argument actuallyswitch identities) and the one-way become (in which the receiver isde-referenced and garbage collected). IBM Smalltalk uses a one-waybecome. See the Blue Book for more complete information on become:.

Testing object equality or identity=, =, ==, , hash, yourself

Boolean classesThe Boolean classes are True and False. Booleans are used in Smalltalk toimplement both standard and application-defined control constructs. Although itmight seem strange that Smalltalk does not provide any built-in mechanisms forcontrolling program running, this turns out not to be a limitation. Indeed, it adds asurprising degree of flexibility to the language.

Boolean messages&, and:, eqv::, ifFalse:, ifFalse:ifTrue:, ifTrue:, ifTrue:ifFalse:, not, or:, xor:, |

Porting tip: All Smalltalk dialects implement the same set of Boolean messages.Users should be aware that in some cases the compiler can optimizeby in-lining control operations rather than implementing them asmessage sends. This is usually transparent unless there is an attemptto subclass or modify one of the Boolean classes.

Chapter 2. Common Language Data Types 7

Page 22: IBM Smalltalk: Programmer's Reference

Collection classesThe CLDT collection classes are Array, Bag, ByteArray, DBString, Dictionary,IdentityDictionary, Interval, LookupTable, OrderedCollection, Set, SortedCollection, Stringand Symbol. They are described in Chapters 9 and 10 of the Blue Book.

Note: Three seldom-used Blue Book collection classes have been excluded fromCLDT, namely LinkedList, MappedCollection, and RunArray. The design ofLinkedList betrays too much of its implementation and is not anindustrial-strength List abstract data type. RunArray was used mainly in theoriginal Smalltalk graphics system to store bitmaps. MappedCollection allowsfor one level of indirection in Dictionary accesses and is seldom used inpractice. Moreover, in most cases, the Dictionary message at:ifPresent: can beused to achieve the same effect.

A collection is a group of objects that can be manipulated and operated on eitherindividually or as a whole. The objects contained by a collection are called itselements. The number of elements in a collection is its size. Most collections aregeneric containers that can hold any kind of object, but five collections (ByteArray,DBString, Interval, String, and Symbol) place restrictions on the class of theirelements. As a rule, developers should use care when defining recursivecollections, that is, collections that have themselves, directly or indirectly, as one oftheir own elements. In a recursive collection there are operations, for example, =,that can fail in some implementations.

The elements of a collection can be operated on as a whole using enumerationmethods that traverse each element of the collection. The canonical enumerationmethod is do:. These enumeration methods replace the for, while, or do constructsused in traditional programming languages to build iterative procedures. Anycollection that is ordered has a standard enumeration order, that is, a standardorder in which elements are traversed by the do: operation. They are in facttraversed in order of monotonically increasing indices. This ordering is guaranteedto be maintained from traversal to traversal. Unordered collections by definitionhave no standard traversal order and are therefore traversed in an undefined order.In particular, subsequent traversals of the same unordered collection are notguaranteed to access elements in the same order.

Collections can be indexed or nonindexed. Indexed collections allow individualelements to be accessed by means of an external key. The key can be either aninteger or an arbitrary object, depending on the collection.

Bag and Set are the simplest kinds of collections, because they are unordered anddo not support an indexing mechanism. Bags can contain duplicate elements, whileSets cannot. Otherwise, their behavior is identical. Neither Bags nor Sets cancontain an instance of UndefinedObject (usually referred to as nil); that is, attemptsto add nil to a Bag or Set are ignored. The elements of a Bag or Set cannot beindividually accessed, because only group operations are supported.

A Dictionary is an unordered collection whose elements are accessed by anexplicitly assigned external key. Keys are often strings or symbols, but in principleany object can be used as a Dictionary key. Key matching for storing or accessingelements is based on the equality operation =. Consequently, keys must be uniquewith respect to the equality operation, that is, two elements cannot be associatedwith the same key nor can two keys be equal. There are no restrictions on theelements stored in a Dictionary.

8 IBM Smalltalk: Programmer’s Reference

Page 23: IBM Smalltalk: Programmer's Reference

IdentityDictionary is a specialization of Dictionary, that uses the equivalenceoperation (==) rather than equality (=) to match keys. In practice, the keys of anIdentityDictionary are usually symbols, although it is not a requirement.

LookupTable has the same protocols as Dictionary but does not contain anyassociations. This makes LookupTable faster than Dictionary for everything exceptassociationsDo:. It also requires less space.

The elements of the ordered collections are all indexed by integer keys that beginat 1 and increase. The ordered collections are Array, ByteArray, DBString,OrderedCollection, SortedCollection, String, and Symbol. OrderedCollection offersthe most comprehensive protocol of any of the collection classes, and isconsequently the one used most often by developers. OrderedCollections do nothave a fixed size, but can grow as needed to hold additional elements. Theelements of an OrderedCollection can be any class of object. SortedCollection is similarto OrderedCollection, except that the elements are held in sorted order. The sortordering is determined by the sort block associated with the SortedCollection. A sortblock is a block with two formal parameters, which answers a Boolean value whenprovided with any two elements of the collection. If the answer is true then metershould be sorted before the second, whereas false indicates that the opposite orderis correct.

The size of Array, ByteArray, DBString, String, and Symbol collections is fixedwhen they are created, and cannot be changed. Fixed-size collections are normallyimplemented as contiguous blocks of memory; consequently they can usuallysupport efficient accessing, copying, and traversing operations. While the elementsof an Array can be any object, the elements of a ByteArray can be integers between0 and 255 (in other words, bytes). The elements of DBString, String and Symbolmust be characters. The elements of String must be characters ranging in valuefrom 0 to 255, whereas the elements of DBString can be characters in the range 0 to65535, that is, double-byte characters. A Symbol is distinguished from a String inthat it is immutable, that is, a Symbol is a read-only object once it has been created.

Note: Symbols cannot contain characters whose value exceeds 255.

Porting tip: The class DBString is analagous to the class TwoByteString inObjectworks\Smalltalk, and to the class DoubleByteString inSmalltalk/V. Because CLDT does not support Symbols that containdouble-byte characters, the Objectworks\Smalltalk class TwoByteSymbol,and Smalltalk/V class DoubleByteSymbol have no CLDT equivalent.

An Interval is not really a collection at all, but a generator that represents ageometric progression. The elements of an Interval must be numbers (integers,fractions, or floats). Rather than store its elements, an Interval computes them whenrequired, using the start, stop, and increment values provided when it is created.

Collection protocolsThe collection classes support a very rich protocol—so rich that at times it can beconfusing. To help structure the following section, the method names are groupedin loosely defined functional categories. The protocol categories are described inthe following section, and the table shows a cross-reference mapping betweenclasses and the protocols they support. A difficulty arises in cases where two ormore classes support the same message name, but the semantics of the message arenot identical. Usually, one message is just a refinement of the other, that is, itimposes additional restrictions on the implementation of the message. A more

Chapter 2. Common Language Data Types 9

Page 24: IBM Smalltalk: Programmer's Reference

serious problem arises when the messages have completely different meanings butshare the same name. This document will identify such cases explicitly.

Common collection protocolsThese same protocols are supported by many different types of collections.

The following table describes protocols supported by CLDT collection classes.

Accessingafter:, at:, basicAt:, before:, findFirst:, findLast:, first, indexOf:, indexOf:ifAbsent:,indexOfSubCollection:startingAt:, indexOfSubCollection:startingAt:ifAbsent:, last

Porting tip: Smalltalk/V does not support indexOfSubCollection:startingAt: orindexOfSubCollection:startingAt:ifAbsent:.

Addingadd:, addAll:

Byte accessingbyteAt:, byteAt:put:

Porting tip: Smalltalk/V does not support byteAt: and byteAt:put:.

ConvertingasArray, asBag, asByteArray, asOrderedCollection, asSet, asSortedCollection,asSortedCollection:

Copying,, copyFrom:to:, copyReplaceAll:with:, copyReplaceFrom:to:with:,copyReplaceFrom:to:withObject:, copyReplacing:withObject:, copyWith:, copyWithout:,reverse

Note: copyReplaceFrom:to:withObject: and copyReplacing:withObject: are not in theBlue Book, but we have found them to be useful.

Porting tip: Smalltalk/V does not support the following:v copyReplaceAll:with:v copyReplaceFrom:to:withObject:v copyReplacing:withObject:

Objectworks/Smalltalk does not support the following:v copyReplaceFrom:to:withObject:v copyReplacing:withObject:

Smalltalk/V uses reversed instead of reverse. Smalltalk/V uses differentsemantics for copyWithout:. In Smalltalk/V, only the first element equalto the argument is omitted from the copy, while in IBM Smalltalk (allplatforms) and Objectworks\Smalltalk, all elements equal to theargument are left out.

Creating instances (class methods)new, new:, with:, with:with:, with:with:with:, with:with:with:with:

Creating dictionaries (class methods)new, new:

10 IBM Smalltalk: Programmer’s Reference

Page 25: IBM Smalltalk: Programmer's Reference

Dictionary accessingadd:, addAll:, associationAt:, associationAt:ifAbsent:, at:, at:ifAbsent:, at:ifAbsentPut:,at:ifPresent:, at:put:, includesKey:, keyAtValue:, keyAtValue:ifAbsent:, keys,removeAllKeys:, removeAllKeys:ifAbsent:, removeKey:, removeKey:ifAbsent:, values

Note: Several messages in this protocol have the same names as messages in otherprotocols but have different semantics: add:, addAll:, at:, and at:put:. The useof these names is well established in the Smalltalk community and has notbeen changed in CLDT. The messages at:ifAbsentPut:, at:ifPresent:,removeAllKeys:, and removeAllKeys:ifAbsent: are not in the Blue Book, but havebeen included in CLDT because their use results in more compact andreadable code.

Porting tip: The messages at:ifAbsentPut:, at:ifPresent:, removeAllKeys:, andremoveAllKeys:ifAbsent: are not supported in Smalltalk/V orObjectworks\Smalltalk.

Dictionary enumeratingassociationsDo:, keysAndValuesDo:, keysDo:

Enumeratingcollect:, conform:, detect:, detect:ifNone:, do:, inject:into:, reject:, select:

Note: The message conform: checks if each element of a collection satisfies acondition, expressed as a one-argument block. Even though conform: is notdefined in the Blue Book, it has been included because it seems to be anatural complement to the other Blue Book enumeration methods.

Porting tip: The conform: message is not supported in Smalltalk/V orObjectworks\Smalltalk.

Ordered enumeratingdoWithIndex:, from:to:do:, from:to:doWithIndex:, reverseDo:, with:do:

Note: The semantics of both of these operations require that the receiver collectionbe ordered.

Porting tip: The doWithIndex:, from:to:do″, and from:to:doWithIndex:, messages arenot supported in Smalltalk/V or ObjectWorks\Smalltalk.

Ordered removingremoveAtIndex:, removeFirst, removeLast

Rehashingrehash

Note: It is customary for collections such as Set, Dictionary, IdentityDictionary, andLookupTableto use the hash of elements to implement efficient access andstore operations. The use of element hash values to locate elements creates aproblem if the hash values of the elements change for some reason. Forexample, if a copy of the collection is passed to another platform in adistributed system that uses different hash functions for objects in thecollection, the collection will not function correctly. The rehash messageenables implementers to guarantee that hash-based accessing is safe.

Removingremove:, remove:ifAbsent:, removeAll:

Chapter 2. Common Language Data Types 11

Page 26: IBM Smalltalk: Programmer's Reference

String accessing and converting<, <=, >, >=, asLowercase, asNumber, asString, asSymbol, asUppercase,indexOf:matchCase:startingAt:, match:, nullTerminated, sameAs:, subStrings, subStrings:

Note: Implementations of the messages <, <=, >, and >= use the U.S. Englishcollation sequence and do not necessarily reflect the collation sequence usedby the underlying platform. The message is needed for practical stringsearching.

Porting tip: Smalltalk/V does not support match: and sameAs:. It also usesasLowerCase and asUpperCase rather than the Blue Book (and IBMSmalltalk) spelling asLowercase and asUppercase. Neither Smalltalk/Vnor Objectworks\Smalltalk support indexOf:matchCase:startingAt:.Collating sequences vary from platform to platform (for example, casesensitivity) and from language to language (for example, somelanguages treat certain combinations of letters as a single character).String comparison results can therefore differ between platforms. Themessages <, <=, >, and >= perform case insensitive comparison, whilethe = message is case sensitive. This means, for example, that <= isnot the “logical or” of < and =. Use sameAs: instead of = for caseinsensitive equality comparison.

Storingat:put:, atAll:put:, atAllPut:, basicAt:put:, replaceFrom:to:with:,replaceFrom:to:with:startingAt:, replaceFrom:to:withObject:

Note: The message replaceFrom:to:withObject: is not in the Blue Book but has beenincluded in CLDT for symmetry and completeness.

Porting tip: The method replaceFrom:to:withObject: is supported in Smalltalk/V butnot in Objectworks\Smalltalk.

Testingincludes:, isEmpty, notEmpty, occurrencesOf:, size

Unique collection protocolIn addition to the protocols supported by CLDT collection classes, several of thecollection classes have unique protocols that are not shared with any other class.

ArraymultiBecome:

Note: This message is not in the Blue Book but has been included in CLDT inorder to provide an efficient means of mutating multiple objects.

Porting tip: The multiBecome: message is not supported in Smalltalk/V orObjectworks\Smalltalk.

Bagadd:withOccurrences:

Intervalincrement

Interval classfrom:to:, from:to:by:

12 IBM Smalltalk: Programmer’s Reference

Page 27: IBM Smalltalk: Programmer's Reference

OrderedCollectionadd:after:, add:afterIndex:, add:before:, add:beforeIndex:, addAll:after:, addAll:afterIndex:,addAll:before:, addAll:beforeIndex:, addAllFirst:, addAllLast:, addFirst:, addLast:

Porting tip: The add:afterIndex:, add:beforeIndex:, addAll:afterIndex:, andaddAll:beforeIndex: messages are not supported in Smalltalk/V orObjectworks\Smalltalk.

SortedCollectionsortBlock, sortBlock:

SortedCollection classsortBlock:

String and DBStringaddLineDelimiters, asDBString, asSBString, bindWith:, bindWith:with:,bindWith:with:with:, bindWith:with:with:with:, bindWithArguments:, trimBlanks,trimSeparators

Note: These String and DBStringmessages are not in the Blue Book. They havebeen added to IBM Smalltalk based on feedback from developers.

Porting tip: The only one of these String and DBString messages that is supportedby Smalltalk/V is trimBlanks. Smalltalk/V also provides asInteger andasFloat which are similar to asNumber. Objectworks\Smalltalk supportsonly asNumber, byteAt:, and byteAt:put:. Objectworks\Smalltalk countsNull (ASCII 0) as a separator in trimSeparators, but IBM Smalltalk andSmalltalk/V do not.

SymbolargumentCount

Note: This method is not in the Blue Book, but is needed to extract the number ofexpected arguments from a selector.

Porting tip: In Objectworks\Smalltalk this method is called numArgs. It is notincluded in the Smalltalk/V image.

Magnitude classesThe CLDT magnitude classes are Association, Character, Date, Float, Fraction, Integer,and Time. Magnitude classes represent objects to which a linear ordering can beapplied, such as characters, numbers, dates, and times. Magnitude classes supportthe capability to compare, query, and determine ranges of these ordered objects.

A ScaledDecimal class also exists, and DM is its application. Although nottechnically part of CLDT, the ScaledDecimal class is associated with the magnitudeclasses of CLDT. Unlike the Float class, the ScaledDecimal class is used for exactrepresentation of real numbers so that there is no round-off error.

Numbers are a major subset of the magnitude classes. The different number classes(Float, Fraction, and Integer) provide concrete representations for integer, rational,and real numbers. Numbers can only be created by the evaluation of an expressionor by literal declaration.

All of the magnitude classes support the basic magnitude protocol for comparingvalues.

Chapter 2. Common Language Data Types 13

||||

Page 28: IBM Smalltalk: Programmer's Reference

Magnitude comparing<, <=, =, >, >=, between:and:, max:, min:

AssociationAn Association represents a binary relation between two objects, called the key andthe value.

Note: Technically, the semantics of the magnitude comparing operations aredifferent for Associations, because the messages <, <=, >, and >= are definedin terms of the key only, while the = message is defined in terms of both thekey and the value. This means, for example, that <= is not the “logical or”of < and =. Despite this, Association has been grouped with the magnitudeclasses because that is where it is traditionally implemented in the Smalltalkenvironment.

Accessingkey, key:, key:value:, value, value:

Porting tip: Both IBM Smalltalk and Objectworks\Smalltalk define the = message interms of both the key and the value. Smalltalk/V defines = in terms ofthe key only. Smalltalk/V does not provide the message key:value:.

Creating instances (Association class)key:value:

CharacterThe class Character is an abstraction for character data. Characters have valuesbetween 0 and 65535, and are unique objects that represent code points. A codepoint is simply a numeric value—the format and graphical appearance of acharacter are defined by the currently selected character set. All vendors agree thatthe characters with values from 0–127 correspond to the ASCII standard characterset. However, there is no agreement on the interpretation of other characters.Groups of characters can be composed into either a String or a DBString dependingupon the values of the characters being composed.

Note: Many of the original Smalltalk implementations supported only charactersthat could be represented by a single byte (characters in the range 0 to 255).Currently, implementations of Objectworks\Smalltalk and Smalltalk/Vprovide for characters whose value exceeds 255. Characters whose valuesexceed 255 require two bytes of storage, and are often referred to asdouble-byte characters. Double-byte character support is critical for thedevelopment of applications for the international market place becausemany languages use more than 256 characters.

Accessingvalue, digitValue

Porting tip: CLDT does not support the Blue Book method asciiValue because it isnot appropriate for characters whose value exceeds 127, the range ofvalues converted by the ASCII standard. Rather, the asciiValue messageis replaced by the more general message value. Objectworks\Smalltalkdoes not support the message value, but uses asInteger as theequivalent message. Smalltalk/V does not support the message value,but uses asciiValue as the equivalent message.

14 IBM Smalltalk: Programmer’s Reference

Page 29: IBM Smalltalk: Programmer's Reference

ConvertingasLowercase, asSymbol, asUppercase, asString

Porting tip: Smalltalk/V uses the spelling asLowerCase and asUpperCase, and doesnot support asSymbol. Character conversions outside the ASCII rangeof values (0 to 127) vary from platform to platform and from languageto language. Character conversion results might differ betweenplatforms. Objectworks\Smalltalk does not support asString.

Creating instances (Character class)digitValue:, value:

Note: The Blue Book specifies that class Character should support messages thatprovide access to several of the standard ASCII nonprinting characters usedfor text formatting: backspace, cr, esc, newPage, space, and tab.Objectworks\Smalltalk adopts this approach, and extends it to supportseveral additional characters. The approach taken by IBM Smalltalk is tosupply all of the nonprinting ASCII characters in a pool dictionary calledCldtConstants as shown in Table 2.

Porting tip: Smalltalk/V does not support the message value:.

Table 2. The CldtConstants pool dictionary. (ASCII character values)

Key ASCII Character Value Key ASCII Character Value

Ack 6 Ff 12

Bell 7 Fs 28

Bs 8 Gs 29

Can 24 Lf 10

Cr 13 Nak 21

Dc1 17 Nul 0

Dc2 18 Rs 30

Dc3 19 Si 15

Dc4 20 So 14

Del 127 Soh 1

Dle 16 Space 32

Em 25 Stx 2

Enq 5 Sub 26

Eot 4 Syn 22

Esc 27 Tab 9

Etb 23 Us 31

Etx 3 Vt 11

Table 3. The CldtConstants pool dictionary. (LineDelimiter values)

Key Value

LineDelimiter The platform-specific line delimiter string

PMLineDelimiter The string consisting of Cr followed by Lf

WINLineDelimiter The string consisting of Cr followed by Lf

Chapter 2. Common Language Data Types 15

Page 30: IBM Smalltalk: Programmer's Reference

TestingisAlphaNumeric, isDigit, isLetter, isLowercase, supplantation, isSeparator, isUppercase,isVowel

Porting tip: Smalltalk/V uses the spelling isLowerCase and isUpperCase. Characterclassifications outside the ASCII range of values (0 to 127) vary fromplatform to platform and from language to language. Characterconversion results might differ between platforms. NeitherObjectworks\Smalltalk nor Smalltalk/V support isPunctuation forCharacters.

DateDate represents an abstraction for a given day of a given year. The Blue Bookspecifies the instance protocol of Date in functional form, but does not actuallydefine method names for most operations. Consequently, although all Smalltalkvendors provide basically the same functionality, there is some variation betweenthe message names used. The general form is that Date provides protocol formanipulating dates, while Date class supports instance creation and general queries.

AccessingdayName, dayOfMonth, dayOfYear, dayIndex, monthIndex, monthName, year

Porting tip: Objectworks\Smalltalk does not support dayName or dayIndex.Smalltalk/V supports the dayIndex message with the days of the weeknumbered starting with Monday as day 1. However, because CLDTprovides National Language Support features based on the POSIX.1standard, the CLDT dayIndex message answers Sunday as day 1.

CalculatingaddDays:, asSeconds, daysFromBaseDay, daysInMonth, daysInYear, daysLeftInMonth,daysLeftInYear, firstDayOfMonth, subtractDate:, subtractDays:

Porting tip: Objectworks\Smalltalk does not support daysLeftInMonth. NeitherObjectworks\Smalltalk nor Smalltalk/V support daysFromBaseDay forDate.

Creating InstancesdateAndTimeNow, fromDays:, newDay:month:year:, newDay:monthIndex:year:,newDay:year:, today

Porting tip: Neither Objectworks\Smalltalk or Smalltalk/V supportnewDay:monthIndex:year:.

QueryingdaysInMonth:forYear:, daysInYear:, indexOfDay:, indexOfMonth:, nameOfDay:,nameOfMonth:

TimeTime represents an abstraction for a time of day, based on a 24-hour clock. Incontrast to Date, class Time is much more clearly specified in the Blue Book, andconsequently there is much less variation between the vendor implementations.Smalltalk/V adds additional protocol to Time class to control the real-time clock ona personal computer. As with Date, the form is that Time provides protocol formanipulating Time instances, while Time class supports instance creation andgeneral queries.

16 IBM Smalltalk: Programmer’s Reference

|

Page 31: IBM Smalltalk: Programmer's Reference

Accessinghours, minutes, seconds

CalculatingaddTime:, asSeconds, subtractTime:

Creating instancesdateAndTimeNow, fromSeconds:, now

QueryingmillisecondsPerDay, millisecondsToRun:, millisecondClockValue

Porting tip: Neither Objectworks\Smalltalk or Smalltalk/V supportmillisecondsPerDay.

NumberThe number classes currently supported in CLDT are Integer, Fraction, and Float,which provide abstractions for the mathematical concepts of integers, rationalnumbers (fractions), and real numbers (floating point). The CLDT number classesdo not deal explicitly with precision or other properties of numbers that depend onimplementation. Another class, Decimal, deals explicitly with precision. Decimalclass is a subclass of Number and is defined in DecimalMath.

For example, a platform might support two or more implementations of a numberclass that have identical behavior, except that they represent numbers withdifferent precisions or different signs. These classes would not be distinguished inCLDT. In contrast, most other Smalltalk systems support several different integerclasses, such as SmallInteger, LargeInteger, LargePositiveInteger, andLargeNegativeInteger. Each class is constrained regarding the size or sign of theintegers that it can represent. However, each of these classes supports the sameInteger protocol defined in CLDT.

Developers do not usually need to be aware of the distinctions between thedifferent representations of number classes, but at the same time the distinctionscannot be completely ignored. Some applications depend on knowledge of theplatform-specific implementation of a number class and so are unlikely to beportable. An example is a numerical application in which the results depend onwhether floating point numbers use single or double precision.

Porting tip: Besides these implementation issues, Smalltalk/V includes a numberof messages in the Number classes designed to support calculations forits particular graphics and windowing system. These are notsupported in IBM Smalltalk.

All number classes support the following basic protocol:

Arithmetic*, +, -, /, //, \\, abs, negated, quo:, rem:

Converting@, asFloat, asFraction, asInteger, degreesToRadians, radiansToDegrees

Porting tip: Smalltalk/V does not support asFraction.

Testingnegative, positive, strictlyPositive

Chapter 2. Common Language Data Types 17

Page 32: IBM Smalltalk: Programmer's Reference

Enumeratingto:, to:by:, to:by:do:, to:do:

GeneralitylessGeneralThan:, moreGeneralThan:

Note: Some developers working with numerical operations applicationsoccasionally need to determine the class of the return value when thereceiver and the operand have different classes. The Blue Book specifies thatthe messages coerce:, generality, and retry: support explicit coercion (that is,type conversion, or casting) between numerical classes. These messages areused to perform the type checking required to ensure that the arguments ofprimitive methods have the correct type. For more details, see Chapter 8 ofthe Blue Book. In general, we believe that type checking and coercionshould be regarded as a private implementation detail, and not exposed inapplication programming. lessGeneralThan: and moreGeneralThan: aredesigned to supply this information without revealing any details as to howthe information is derived. In particular, there is no guarantee that numberclasses support an explicit integer-valued generality.

Porting tip: Smalltalk/V and Objectworks\Smalltalk use different approaches thanIBM Smalltalk. Objectworks\Smalltalk follows and extends the BlueBook model, adding a large number of messages designed to supportcoercion and double dispatch. Smalltalk/V, on the other hand, hidesmost of the type checking inside primitive methods.

Math functionsarcCos, arcSin, arcTan, cos, exp, floorLog:, ln, log:, raisedTo:, raisedToInteger:, reciprocal,sign, sin, sqrt, squared, tan

Porting tip: Smalltalk/V does not support floorLog:, and adds the messagetimesTwoPower:, which is not included in IBM Smalltalk.

Truncating and roundingceiling, floor, rounded, roundTo:, truncated, truncateTo:

IntegerIn addition to supporting the basic protocol, the class Integer supports thefollowing messages.

Manipulating bitsallMask:, anyMask:, bitAnd:, bitAt:, bitInvert, bitOr:, bitShift:, bitXor:, clearBit:, highBit,isBitSet:, noMask:, setBit:

Note: The CLDT messages clearBit:, isBitSet:, and setBit: are not in the Blue Bookbut have been added to make bit-level manipulation easier.

Porting tip: Objectworks/Smalltalk does not support clearBit:, isBitSet:, or setBit. Itsupports its own methods named anyBitto:, maskClear:, and maskSet:,which are not in the Blue Book. Smalltalk/V does not supportallMask:, anyMask:, clearBit:, isBitSet:, highBit, noMask:, or setBit:.

EnumeratingtimesRepeat:

Testingeven, odd

18 IBM Smalltalk: Programmer’s Reference

Page 33: IBM Smalltalk: Programmer's Reference

Porting tip: Smalltalk/V and Objectworks\Smalltalk define even and odd for allnumbers, not just Integer. This leads to surprising and inconsistentresults due to round-off error and other problems.

PrintingprintOn:base:, printOn:base:showRadix:, printStringRadix:, printStringRadix:padTo:,printStringRadix:showRadix:

Porting tip: All Smalltalk dialects support the message printOn:base:.Objectworks\Smalltalk also supports printStringRadix:, which isspecified in the IBM Red Book. The additional CLDT integer printingmessages are specific to IBM Smalltalk. In some cases the othervendors supply functionally equivalent messages.

Integer math functionsfactorial, gcd:, lcm:

ConvertingasCharacter:, asScaledDecimal

FractionCLDT assumes that a Fraction is always reduced to its lowest commondenominator. Using unreduced instances of Fraction can cause errors with currentimplementations.

Accessingdenominator, numerator

Creating instancesnumerator:denominator:

Note: This message has been included to comply with the Blue Book and RedBook, but its use is strongly discouraged. It is possible to create anunreduced instance of Fraction with this method, which could lead to errors,because reduced Fractions are expected. The recommended way to create aFraction is with the division message (/) or with conversion messages.

ConvertingasScaledDecimal

FloatAdditional supported protocols for Float are:

AccessingfractionPart, integerPart

Porting tip: The fractionPart and integerPart messages are not supported inSmalltalk/V.

Creating instancespi

Note: The irrational number Π is singled out because this message is in both theBlue Book and Red Book, and is supported by all vendors.

ConvertingasScaledDecimal

Chapter 2. Common Language Data Types 19

|

|

|

Page 34: IBM Smalltalk: Programmer's Reference

ScaledDecimalThe ScaledDecimal class represents fixed point decimal data exactly with precisionsof up to 31 digits. It also performs the arithmetic on such data when combinedwith any other numeric type.

Decimals are represented as in the following example:3.4s

The number is interpreted as having a value of 3.4, with a precision of 2 digits,and a scale of 1. Precision is defined as the number of digits. Scale is defined asthe number of digits needed to represent the fractional part.

Instances of ScaledDecimal can be used in normal Smalltalk arithmetic operations.Scaled Decimals are considered to be higher in generality than Integers andFractions but lower than Floats. For example:3.4s + 1.0 ==> 4.4 (Float)3.4s + ( 1/3 ) ==> 3.73333333333333333333333333333d30.29 (Decimal)

Precisions and scales do not follow the same arithmetic rules as values. Forexample:Precision = 3 Precision = 2 Precision = 4Scale = 2 Scale = 1 Scale = 29.99s + 2.3s = 12.29s

ConvertingasScaledDecimal, asFloat, asFraction, asInteger

AccessingfractionPart, integerPart, scale, significantDigits

PrintingprintOn:showDigits:Pad:

Creating instancesfromString:

The DM application also provides the method asScaledDecimal to the class String.The following illustrates two ways of creating the same ScaledDecimal:'3.4' asScaledDecimalScaledDecimal fromString: '3.4'

Graphical classesThe CLDT graphical classes are Point and Rectangle, which are abstractionsrepresenting the plane geometrical concepts of point (two-dimensional) andrectangle. They are described in the Blue Book. Point and Rectangle are heavilyused in the implementation of graphics routines, both in the Common Widgets andCommon Graphics subsystems, and in applications.

PointIn Smalltalk, Points are commonly written as “A@B”, where A and B are numbers.

Note: This proves to be a convenient denotation because it also evaluates to aPoint instance.

20 IBM Smalltalk: Programmer’s Reference

|

|

|||

||

|||

|

||

||

Page 35: IBM Smalltalk: Programmer's Reference

Smalltalk conforms to the usual convention in plane geometry in that the first, orx-coordinate of a Point represents the horizontal dimension, and the second ory-coordinate represents the vertical dimension.

Note: A CLDT convention is that the point 0@0 (the origin) is in the upper leftcorner of the screen. The x-coordinate increases as a Point moves to theright, and the y-coordinate increases as it moves down. In some cases thisdoes not conform to the usual conventions for the platform GUI (forexample, in OS/2 Presentation Manager the origin is the lower left corner).CLDT imposes a uniform definition of origin to facilitate portability.

Accessingx, x:, y, y:

Arithmetic*, +, -, /, //, abs, negated

Porting tip: The arithmetic messages quo:, rem:, and \\ are defined inObjectworks\Smalltalk, but they are not specified by the Blue Book,and have not been included in IBM Smalltalk.

Creating instancesx:y:

Magnitude comparing<, <=, =, >, >=, between:and:, max:, min:

Point functionsdotProduct:, dist:, normal, transpose

Note: While not often used, these messages have been included because they aredefined in the Blue Book. Objectworks\Smalltalk provides an even moreextensive library of such functions, and support for polar coordinates,presumably to support complex computational geometry algorithms. Giventhe tendency in modern systems to use platform graphics routines, or evengraphics processors, these functions have not been included in CLDT.

Porting tip: Smalltalk/V does not support dist: or normal.

Creating rectanglescorner:, extent:

Truncating and Roundingrounded, truncated, truncatedGrid:, truncateTo:

Porting tip: Smalltalk/V does not support truncatedGrid: or truncateTo:.

RectangleRectangle supports an extensive accessing protocol for getting and setting points onthe boundary of a rectangle. Most of the other messages are provided to facilitategraphics calculations.

Porting tip: While CLDT Rectangles are similar to those defined inObjectworks\Smalltalk, there are many differences from theSmalltalk/V implementation. This is likely because CLDT andObjectworks\Smalltalk are both based on the Blue Book.

Chapter 2. Common Language Data Types 21

Page 36: IBM Smalltalk: Programmer's Reference

Accessingbottom, bottom:, bottomCenter, bottomLeft, bottomLeft:, bottomRight, bottomRight:, center,corner, corner:, extent, extent:, height, height:, left, left:, leftCenter, origin, origin:,origin:corner:, origin:extent:, right, right:, rightCenter, top, top:, topCenter, topLeft,topLeft:, topRight, topRight:, width, width:

Porting tip: Objectworks\Smalltalk omits the accessors bottomLeft: and topRight:. Weinclude them because all the other corners had a set message, andtopRight: is specified in the Red Book. Smalltalk/V reverses the namesof the corner accessors, that is bottomLeft becomes leftBottom,bottomRight becomes rightBottom, and so forth. Smalltalk/V does notsupport the accessors (or functional equivalents) bottom:, bottomLeft:,bottomCenter, left:, leftCenter, origin:, right:, rightCenter, top:, topCenter, ortopRight:.

Geometric functionsamountToTranslateWithin:, area, areasOutside:, contains:, containsPoint:, expandBy:,insetBy:, insetOriginBy:cornerBy:, intersect:, intersects:, merge:, moveBy:, moveTo:,scaleBy:, translateBy:

Porting tip: Objectworks\Smalltalk calls the scaleBy: and translateBy: messagesscaledBy: and translatedBy:. We have used the names specified by theBlue Book and Red Book. Smalltalk/V does not support the messagesamountToTranslateWithin:, area, areasOutside:, contains:, andinsetOriginBy:cornerBy:, which are all in the Blue Book.

Creating instances (rectangle class)left:right:top:bottom:, origin:corner:, origin:extent:

Porting tip: Objectworks\Smalltalk includes several messages that enable users tointeractively define Rectangles on the display screen. CLDT does notsupport such messages, which are not consistent with Blue Book orRed Book usage. Smalltalk/V does not support left:right:top:bottom:.

Truncating and roundingrounded, truncated

Stream classesThe stream classes are ReadStream, ReadWriteStream, and WriteStream. Described inChapter 12 of the Blue Book, streams provide an abstraction that enables store andretrieve operations to be performed on the elements of an underlying compositedata structure, usually an indexed collection. In particular, a stream remembers theposition of the last element in the data structure to be read or written. Streams arepositionable, that is, the current read/write position can be changed using thestream’s public interface. This allows elements to be accessed in either a sequentialor nonsequential fashion.

It is implicit in stream semantics that the elements of the underlying data structureare sequentially ordered. With respect to the CLDT classes, a ReadWriteStream orWriteStream can stream over a String, DBString, ByteArray, or Array. A ReadStreamcan stream over the same set of classes plus Interval, OrderedCollection,SortedCollection, or Symbol.

Note: One significant change has been made to Blue Book streams—each CLDTstream has an instance variable that holds a string called a line delimiter. Byfar the most common use of streams in practice is to read or write String

22 IBM Smalltalk: Programmer’s Reference

Page 37: IBM Smalltalk: Programmer's Reference

data. Every platform uses a sequence of one or two characters to mark theend of a line in a multiline string or text file. This character sequence isreferred to as the platform line delimiter. Platforms use different linedelimiters. For example, the AIX line delimiter is a Line Feed, whileWindows uses the sequence Carriage Return followed by Line Feed. Theplatform line delimiters that are supported by CLDT are all available in thepool dictionary CldtConstantsand are listed in Table 3 on page 15. When anew CLDT stream is created, its line delimiter is always set to be the correctline delimiter for the platform. However, the line delimiter can also bechanged dynamically, and it is not necessary to always use the platform linedelimiter. This allows developers to easily read or write a String obtainedfrom or intended for other platforms, and eliminates a serious obstacle toportability.

The following table lists protocols supported by Stream classes.

Table 4. Protocols supported by Stream classes

Accessing CopyingEnumer-

atingPosition-

ing Reading Testing TruncatingWriting

ReadStream X X X X X X

ReadWrite-Stream

X X X X X X X X

WriteStream X X X X

Accessingclose, lineDelimiter, lineDelimiter:, size, contents

Note: As discussed above, the access methods lineDelimiterand lineDelimiter: makeit possible to read and write Strings in a portable manner by ensuringcorrect semantics for the messages cr and nextLine. The Blue Book methodreverseContents was omitted, because it is equivalent to sending contentsreverse. The message close is included to support polymorphic programmingusing CLDT streams and Common File System file streams. Sending close toa CLDT stream has no effect. The message size is not in the Blue Book butthe need seems obvious.

Porting tip: The messages lineDelimiter and lineDelimiter: are not supported byeither Objectworks\Smalltalk or Smalltalk/V.

CopyingcopyFrom:to:

Note: This is not a Blue Book message. However, it provides an efficient way tocopy a subset of elements from a stream without being forced to create anintermediate collection.

Porting tip: Not supported by Objectworks\Smalltalk.

Enumeratingdo:

Chapter 2. Common Language Data Types 23

Page 38: IBM Smalltalk: Programmer's Reference

Positioningposition, position:, reset, setToEnd, skip:

Readingnext, next:, nextLine, nextMatchFor:, contents, peek:, peekFor:, skipTo:, skipToAll:, upTo:,upToAll:, upToEnd

Note: The messages skipToAll:, upToAll:, and upToEnd are not in the Blue Book butprovide needed functionality.

Porting tip: The messages skipToAll:, upToAll:, and upToEnd are not supported inSmalltalk/V.

TestingatEnd, isEmpty

Truncatingtruncate

Note: This is not a Blue Book message but has been added because it is needed inpractice.

Porting tip: Not supported by Objectworks\Smalltalk.

Writingflush, nextPut:, nextPutAll:, next:put:, cr, space, tab

Porting tip: The Blue Book methods crTab: and crTab: were omitted because theycan be easily composed using cr and tab. They are not included in theRed Book. The message flush is included to support polymorphicprogramming using CLDT streams and CFS file streams. Sending flushto a CLDT stream has no effect.

Creating instancesReadStream class supports the Blue Book instance creation messages on: andon:from:to:. WriteStream class supports the Blue Book messages on:, with:, andwith:from:to:. Instances of ReadWriteStream can be created by sending any of theabove messages to ReadWriteStream class.

Support classesThe support classes are UndefinedObject, Message, DirectedMessage, and Block.

UndefinedObjectThe class UndefinedObject is discussed in Chapter 14 of the Blue Book. It describesthe behavior of a special object called nil, which is used to represent the value ofan unassigned variable or an undefined result. There is only a single instance ofUndefinedObject in the system. The messages isNil and notNil, inherited from Objectprotocol, are redefined in UndefinedObject to always return the values true and false.In addition, nil supports a protocol to create new Smalltalk classes, and to permitthe creation of new classes that have no superclass.

24 IBM Smalltalk: Programmer’s Reference

Page 39: IBM Smalltalk: Programmer's Reference

Message and DirectedMessageThe concept of a Message class is briefly discussed in the Blue Book, but no detailsare provided about its protocol. CLDT defines both a Message class and aDirectedMessage class. Both are used in error handling and to supportcommunication between the virtual machine and the rest of the system. A Messagerepresents a Smalltalk message. It supports the basic accessors arguments,arguments:, selector, and selector:. A DirectedMessage is a Message that also knowsabout its receiver. It supports the basic accessors plus receiver, receiver:, and send.

Porting tip: In Objectworks\Smalltalk a DirectedMessage is called a MessageSend.Smalltalk/V has no equivalent of Message, but has a class Message thatis equivalent to DirectedMessage. Messages are created using the classmessage new. DirectedMessages in IBM Smalltalk can be created bysending the class messages new and selector:arguments:receiver:.

BlockA Block represents a lexical closure, that is, a piece of compiled code that can berun on demand and need not be associated with a message in any class. Instancesof Block support two messages, whileTrue: and whileFalse:, which are used toconstruct while loops. Additional Block protocol is defined in “Exception handlingclasses”, “Block evaluation methods” on page 48, and “Process-related blockmethods” on page 49.

Exception handling classesThe exception handling classes, ExceptionalEvent and Signal, provide an elegantmeans of handling exceptional events and error conditions.

ExceptionalEventInstances of this class represent an exceptional condition. Instances are signaled tocause an exception handler to be invoked.

SignalInstances of this class represent a signaled exception and are passed as anargument to the exception handler.

Tip: As with the goto: statement of conventional languages, this can createproblems with code maintenance, and it is therefore recommended thatexception handling only be used for handling exceptional circumstances orerror conditions.

Creating new exceptionsExceptions are instances of the class ExceptionalEvent and are created by sendingthe message newChild to an existing, or “parent,” exception. The most generalexception is an instance of ExceptionalEvent called ExAll, which has no parent. Allother exceptions are “children” of exactly one other (more general) exception. Thiscreates a hierarchy of exceptions. Instances of ExceptionalEvent maintain thefollowing state:

descriptionA String that describes the general circumstances where the exceptionarises (the “error message”).

parent The exception’s parent, nil for ExAll.

Chapter 2. Common Language Data Types 25

Page 40: IBM Smalltalk: Programmer's Reference

resumableA Boolean that is true if running can be resumed at the place where theexception was signaled. It is copied from parent to child on creation, and isfalse for ExAll.

defaultHandlerA one-argument block that is fired if the exception is not explicitlyhandled. The default handler block is passed the instance of Signal thatdescribes the exception that was signaled. If nil, the parent’s defaultHandleris applied. The defaultHandler in ExAll sends error:.

The following examples create a couple of types of exception:

Example: creating an end of file exception| anEndOfFileException |(anEndOfFileException := ExAll newChild)

description: 'end of file'.

Example: creating a message not understood exception| aMessageNotUnderstoodException |(aMessageNotUnderstoodException := ExAll newChild)

description: 'message not understood'.

Signaling an exceptionExceptions are signaled by sending one of the following methods to theappropriate instance of ExceptionalEvent:signal Invokes the exception with no arguments.signalWith:

Invokes the exception with a single argument.signalWith:with:

Invokes the exception with two arguments.signalWithArguments:

Invokes the exception with anArray of arguments

The following examples signal a couple of types of exception:

Example: signaling end of file| anEndOfFileException |(anEndOfFileException := ExAll newChild)

description: 'end of file'.anEndOfFileException signal.

Example: signaling message not understood| aMessageNotUnderstoodException |(aMessageNotUnderstoodException := ExAll newChild)

description: 'message not understood'.aMessageNotUnderstoodException

signalWith: (DirectedMessage selector: #halt arguments: #() receiver: self)

When an exception is signaled, an instance of class Signal is created that containsinformation describing the circumstances where the exception occurred.

Handling of exceptionsYou construct exception handlers by sending the message when:do: to a block. Youcan install multiple handlers simultaneously by using repeated forms of when:do:(that is, when:do:when:do:, when:do:when:do:when:do:, and so on) for up to five

26 IBM Smalltalk: Programmer’s Reference

Page 41: IBM Smalltalk: Programmer's Reference

handlers. Because the handlers are tried in order, more general handlers should beplaced later in the list. You can use nesting to allow more than five handlers ifabsolutely required.

The first argument to when:do: is an instance of class ExceptionalEvent. The secondargument is a one-argument handler block that is passed the instance of Signalthat describes the exception.

When an exception is signaled, the most recent when:do: matching the exception isevaluated first. When a when:do: message is found with either the exception or amore general exception (one of the exception’s ancestors) as the when argument, itshandlerBlock is run.

Within the handler block, the following methods can be sent to an instance ofSignal:

argumentAnswers the first argument that was passed to the signal message, or nil ifnone.

argumentsAnswers a collection containing any arguments that were passed to thesignal message.

exitWith:Immediately returns an object instance as the value of the when:do:exception.

resumeWith:Returns key and value as the result of the signal message.

signal Indicates that the current handler is finished handling, or is not going tohandle, the exception and that a search for another handler should begin.Notice that this is not the same semantics as sending signal to an instanceof ExceptionalEvent.

signalWith:Same as signal, but modifies the arguments which are passed on.

signalWith:with:Same as signal, but modifies the arguments which are passed on.

signalWithArguments:Same as signal, but modifies the arguments which are passed on.

retry Runs the block that the when:do: message was sent to. All handlers arereinstated.

handlesByDefaultRuns the default handler for the exception.

descriptionAnswers a description of the exception. Returns the string ′an exceptionhas occurred’ if no description was set in the ExceptionalEvent.

exceptionAnswers the exception that was signaled. Access to the exception is notnormally required by handlers. However, this method is provided forspecial purpose applications.

Assuming that ThatException is a global variable, an application could have thefollowing code:

Chapter 2. Common Language Data Types 27

Page 42: IBM Smalltalk: Programmer's Reference

"Initialization code."(ThatException := ExAll newChild)

description: 'That exception occurred.'.thatMethod

"Answer true if thatTest completes without error,otherwise signal ThatException."self thatTest failed

ifTrue: [ ThatException signal ].|true

Note: The application has determined that an exceptional condition has occurredand signals an exception.

anyMethod"The application can then do something like the following.Answer true if thatMethod completes without exception,and false otherwise."

|[ self thatMethod ]when: ThatExceptiondo: [:signal |

"Handle the exception in some way: increment a counter,print a message, fix a problem, ... and then exit the handler."signal exitWith: false].

Note: From do: [:signal to the end is the handler block.

Note that ″dropping off the end″ of a handler block is equivalent to sendingresumeWith: (Association

key: #resumevalue: valueOfTheBlock

where valueOfTheBlock is the value of the handler block.

Note: Neither the handler block nor the block that receives when:do: can contain areturn (|) expression. Although this is not a significant limitation, it shouldbe kept in mind when automatic code generation techniques are used,because arbitrary code fragments cannot be wrapped with exceptionhandlers without first checking for return expressions.v It is possible to signal another exception within the body of the handler.v The handler block should not contain a return (|) expression. Returning

from an exception handler can cause unpredictable results.

ExceptionalEvent collectionsOccasionally, it is desirable to use a single handler for several nonhierarchicallyrelated exceptions. To handle this situation, the when:do: syntax has been extendedto allow an ExceptionalEvent collection as the when argument. ExceptionalEventcollections are created by sending the vertical bar (|) message to an instance ofExceptionalEvent as follows:

In class ExceptionalEvent:| anExceptionalEvent

"Answer a new ExceptionalEvent collectioncontaining the receiver and anExceptionalEvent."

In the ExceptionalEvent collection:| anExceptionalEvent

"Add anExceptionalEvent to the exceptions stored in the receiver."

Given these definitions, it is possible to write the following:

28 IBM Smalltalk: Programmer’s Reference

Page 43: IBM Smalltalk: Programmer's Reference

[ "Some code that could cause several exceptions" ]when: Type1Exception | Type2Exception | Type3Exceptiondo: [ :signal | signal exitWith: 'I expected this exception'].

ExceptionalEvent collections can be stored in a variable and later referred to:ExpectedExceptions :=

Type1Exception | Type2Exception | Type3Exception.[ "Some code that could cause several exceptions"[

when: ExpectedExceptionsdo: [ :signal | signal exitWith: 'I expected this exception'].

ExceptionalEvent collections cannot be signaled.

Within the body of a handler block, sending exception to the passed-in instance ofSignal always answers the particular exception that was signaled.

Completion blocksThe syntax codeBlock whenExceptionDo: completionBlock runs the completion block ifany exception occurs during the running of the code block. The completion blockis not considered to have handled the exception. That is, a further exception handleris looked for after the completion block is run.codeBlock whenExceptionDo: completionBlock

is equivalent to:codeBlock

when: ExAlldo: [ :signal |

completionBlock value.signal resumeBlock: nilsignal signal ].

The syntax codeBlock atEndOrWhenExceptionDo: completionBlock causes thecompletion block to be run whether an exception occurs during the running of thecode block, or the code block successfully runs to completion. As above, thecompletion block is not considered to have handled the exception. That is, afurther exception handler is looked for after the completion block is run.codeBlock atEndOrWhenExceptionDo: completionBlock

is equivalent to:| cleanedUp |cleanedUp := false.codeBlock

when: ExAlldo: [ :signal |

completionBlock value.cleanedUp := true.signal resumable: false.signal signal ].

cleanedUp ifFalse: [ completionBlock value ]

Note that completion blocks are not passed any arguments.

Note: After a completion block has been run because of an exception, theexception (actually the instance of Signal) is marked as being nonresumablebefore another handler is searched for. This prevents the completion blockfrom being run multiple times.

Chapter 2. Common Language Data Types 29

Page 44: IBM Smalltalk: Programmer's Reference

Default exception handlerInstances of ExceptionalEvent can have a default handler block that is run if theexception occurs outside of a when:do expression.| anException |(anException := ExAll newChild)

defaultHandler: [:signal |self error: 'The exception was not expected at this time.'].

anException signal.

If desired, the default handler block can be run from inside of a handler block bysending handlesByDefault to the handler’s signal argument.

Note: The exitWith: and retry messages cannot be used in the default handler blockunless the expression that caused the exception was run inside the receiverblock of a when:do: expression.

System exceptionsGlobally accessible exceptions are stored in the pool dictionary namedSystemExceptions. By convention, the names of the exceptions in this pool beginwith ‘Ex.’ SystemExceptions is a pool dictionary belonging to Object and is thereforeaccessible by all subclasses of Object.

The following table lists system exceptions in the SystemExceptions pool dictionary.

Table 5. SystemExceptions pool dictionary

Pool variable name Description

ExAll The most general exception.

ExError The exception signaled by Object>>error:. This exception issignaled with the string passed to error:.

ExHalt The exception signaled by Object>>halt. This exception issignaled with the string passed to halt:. Note that Object>>haltsends halt:.

ExUserBreak The exception signaled by the system default break handler.

The system exceptions ExError, ExHalt, and ExUserBreak use the first argument forthe error string when opening a debugger. If you create a child of these exceptions,you must follow the same convention. Alternatively, you can provide adefaultHandler in the child, which sends error: with an appropriate error message.The defaultHandler for the system exceptions uses the description of the exceptionas the error string if the first argument is not a string. If you are using exceptionsto return non-string values in the arguments of the signal (a reasonable use) thenyou should provide a default handler for your exceptions that knows that thearguments will not be strings. For example:| anErrorException |(anErrorException := ExError newChild)

description: 'a demonstration error occurred';defaultHandler: [:sig |

self error: 'My error occurred with arguments: ',sig arguments printString].

anErrorException signalWith: 1 with: 2.

Examples of exception handlingThe follow examples show how to handle various situations:

30 IBM Smalltalk: Programmer’s Reference

Page 45: IBM Smalltalk: Programmer's Reference

Example: printing an object"Assume that printString will call self error: if it encounters an error condition."| anObject |

[ anObject printString ]when: ExErrordo: [:signal |

signalexitWith: 'Exception: ', signal argument, 'while printinga ', anObject class name ].

Example: trapping user break[ "Unbreakable code"

1000 timesRepeat: [String new: 100000]]when: ExUserBreakdo: [:signal |

System confirm: 'Caught user break'.signal resumeWith: nil ].

Example: growing a stack"Assume that a Stack class with a push: method exists in the application."(OverflowException := ExAll newChild)

description: 'stack overflow'.[aStack push: anInteger]

when: OverflowExceptiondo: [ :signal |

aStack grow.signal retry ].

Example: propagating a different exception| aDifferentException |(aDifferentException := ExAll newChild)

description: 'this is a different exception'.

[1 error: 'demonstration' ]when: ExErrordo: [:signal |

aDifferentException signal].

Example: top-level loop| loopExitException |loopExitException := ExAll newChild.

[ [ true ] whileTrue: ["Body of loop. Can only be exited by saying'loopExitException signal'."(System confirm: 'Signal the loopExitException')

ifTrue: [loopExitException signal].

"Create a doesNotUnderstandException."1 error: 'This is for demonstration purposes'.

]]

when: loopExitExceptiondo: [ :signal |

signal exitWith: 'bye' ]when: ExAlldo: [ :signal |

System message: 'An Exception has occurred: ', signal description.signal retry ].

Chapter 2. Common Language Data Types 31

Page 46: IBM Smalltalk: Programmer's Reference

Example: close stream at end or on error"If an error occurs, it is reported normally, but aStream is closed first."| aStream |

aStream := ReadStream on: 'This is a test'.

[ [ aStream atEnd ]whileFalse: [ Transcript nextPut: aStream next. ]

]atEndOrWhenExceptionDo: [

Transcript show: '...Closing the stream'.aStream close ].

32 IBM Smalltalk: Programmer’s Reference

Page 47: IBM Smalltalk: Programmer's Reference

Chapter 3. Common Language Implementation

The Common Language Implementation (CLIM) subsystem provides aplatform-independent interface that is primarily intended to describe the sharedbehavior of IBM Smalltalk classes. A class in Smalltalk is an abstraction thatdescribes a kind of object. We have already encountered a large number of IBMSmalltalk classes in the previous section on CLDT: Integer, SortedCollection, Date,and so on. One of the fundamental symmetries of the Smalltalk environment isthat every object is an instance of a class. That includes classes themselves, whichare instances of special classes called metaclasses.

Unless you are already an experienced Smalltalk programmer, both the idea ofmetaclasses and the role that they play in the language are probably unclear. TheBlue Book contains a discussion that might help to sort out the subject. The goodnews is that most developers, even those who write very sophisticated Smalltalkprograms, never have to deal explicitly with metaclasses. They exist only in thebackground, part of the hidden machinery that makes things work.

CLIM is intended to be used by application developers who are implementingSmalltalk development tools. CLIM complements the messages described in CLDT,most of which define either instance behavior, or class behavior that is specific toone or a few related classes. CLIM consists of the concrete classes Class, Metaclass,Compiler, ClimCompilerError, CompiledMethod, and EmSystemConfiguration. Inaddition, it adds several messages for creating classes to the CLDT classUndefinedObject, and extends the classes Array, String and DBString. In the sameway that it is convenient to include the abstract class Object in CLDT, we have alsoincluded the class Behavior in CLIM. Behavior describes a number of messages thatare shared by Class and Metaclass, and through inheritance, by all of the classes inIBM Smalltalk. The class hierarchy is:

BehaviorClassDescription

ClassMetaclass

CLIM does not provide a complete definition of Class or Metaclass. What it does dois define a number of common class messages that are supported by all classes inIBM Smalltalk. As might be guessed, CLIM has rather specific objectives. It isintended to support:v Browsingv Creating or modifying class structuresv Compilationv Adding and deleting methods to classes (with some restrictions)

It is not intended to support:v Meta-level programmingv Writing compilers, image builders, or other tools that depend on, or modify, the

fundamental mechanisms of Smalltalk

It is expected that developers who want to add, modify, or delete methods to IBMSmalltalk classes will normally do so using the source code management facilities.However, there are cases where it might be necessary to add or delete methodsoutside the control of the source code manager. An example might be behavior that

© Copyright IBM Corp. 1994, 2000 33

Page 48: IBM Smalltalk: Programmer's Reference

is defined by an application at run time, compiled into a method that is added tosome class, run, and then deleted. (However, CLIM classes are not included in theruntime environment.) This is how the Execute command in text menus is oftenimplemented. CLIM provides a minimal set of messages intended to address thisspecific requirement. It does not, however, include any messages that store sourcecode. Developers are cautioned that when they are adding or deleting methodsoutside the control of the source code manager, it is their responsibility to leave thesystem in a well-defined and consistent state.

Behavior messagesThe messages described in this section provide access to the properties andattributes of a class, including the methods it defines. Behavior messages aremainly intended to support browsing by allowing developers to perform queriesover class structures.

Class queriesallSubclasses, allSuperclasses, inheritsFrom:, name, subclasses, superclass, symbol,whichClassIncludesSelector:, withAllSubclasses, withAllSuperclasses

Note: The Blue Book defines all of these messages except symbol andwithAllSuperclasses. We added symbol to provide a platform-independentmessage that returned a symbol equal to the class name, andwithAllSuperclasses because it is the obvious complement of withAllSubclasses.

Porting tip: Smalltalk/V does not support whichClassIncludesSelector:, and it returnsa string when name is sent. Objectworks\Smalltalk returns a symbolwhen name is sent, and does not support symbol.

Tip: If name is sent to a class, a Symbol is answered. If name is sent to a metaclass,a String is answered.

Compilingcompiler

Note: This message returns the compiler that is appropriate for a particular class.There might be more than one compiler supported by the system, and eachclass needs a way to find its own.

Porting tip: Not supported by Smalltalk/V and Objectworks\Smalltalk, which bothprovide a similar message called compilerClass. Both Smalltalk/V andObjectworks\Smalltalk provide a set of compilation messages forclasses, based loosely on the Blue Book. We have not included suchmessages in this release, because they intrude on source codemanagement. The usual way to compile methods and add code to thedatabase for developers using IBM Smalltalk is to use the facilitiesprovided by IBM Smalltalk.

Creating instancesbasicNew, basicNew:

Note: The standard messages used in Smalltalk to create new instances of classesare new, basicNew, new:, and basicNew:. These messages are defined inBehavior in the Blue Book, but this causes them to be inherited by many

34 IBM Smalltalk: Programmer’s Reference

Page 49: IBM Smalltalk: Programmer's Reference

classes for which one or more are not appropriate. CLIM and CLDT take amore careful approach. Only the message basicNew is defined for all classes.As specified in the Blue Book, basicNew and basicNew: are intended to be theprimitive object creation messages and are not intended to be overridden,because the other instance creation messages are often defined in terms ofthis one. Other instance creation messages are inherited as specified in theclass messages for each CLDT and CLIM class.

EnumerationallMethodsDo:, methodsDo:, allSubclassesBreadthFirstDo:, allSubclassesDepthFirstDo:,allSubclassesDo:, allSuperclassesDo:, withAllSubclassesBreadthFirstDo:,withAllSubclassesDepthFirstDo:, withAllSubclassesDo:, withAllSuperclassesDo:

Note: The Blue Book defines only the messages allSubclassesDo: andallSuperclassesDo:. These messages do not provide any control over the orderin which classes are traversed, which is important for some applications.The messages prefixed by with include the receiver class in the classes thatare being enumerated.

Porting tip: None of these messages are supported in Smalltalk/V.Objectworks\Smalltalk supports only allSubclassesDo:.

Instance accessingallInstances, basicAllInstances

Note: allInstances is a Blue Book message. It is defined in IBM Smalltalk to returnall live instances of a class. Live instances are those that are beingreferenced by another (referenced) object, and so will not be reclaimed bythe next pass of the garbage collector. (Garbage collection is a Smalltalkprocess for periodically identifying unreferenced objects and deallocatingtheir memory.) Sending allInstances usually forces a garbage collection toensure that only live instances are returned. The message basicAllInstances isnot in the Blue Book, but experience indicates it is necessary. It is generallyfaster because it does not require the garbage collection; however, all of thereturned instances are not guaranteed to exist.

Porting tip: Neither Smalltalk/V nor Objectworks\Smalltalk supportsbasicAllInstances, although Smalltalk/V does have a message withsimilar semantics called allInstancesPrim. Smalltalk/V supportsallInstances. Objectworks\Smalltalk also has a message namedallInstances, but it has the semantics of basicAllInstances.

Instance structure testinginstSize, isBits, isBytes, isFixed, isPointers, isVariable

Note: These messages are all defined in the Blue Book.

Porting tip: Objectworks\Smalltalk does not support isBytes.

Method accessing>>, allSelectors, compiledMethodAt:, compiledMethodAt:ifAbsent:, methodDictionary,selectors, sourceCodeAt:, sourceCodeAt:ifAbsent:

Chapter 3. Common Language Implementation 35

Page 50: IBM Smalltalk: Programmer's Reference

Note: The messages allSelectors, compiledMethodAt:, selectors, and sourceCodeAt: aredefined in the Blue Book. Note that methodDictionary has been carefullydefined so it does not imply that a real method dictionary is used to storemethods. Requiring an actual method dictionary seems to be anunreasonable restriction on implementors. For the same reason we haveomitted the Blue Book message methodDictionary:.

Porting tip: Smalltalk/V supports only compiledMethodAt:, selectors, andsourceCodeAt:. Smalltalk/V uses multiple method dictionaries anddefines the messages methodDictionaries and methodDictionaries: tosupport them. Objectworks\Smalltalk supports all messages except theaccessors >>, sourceCodeAt:ifAbsent:, and methodDictionary, although itdoes support the corresponding set method methodDictionary:,following the Blue Book in this practice.

Method adding and deletingaddCompiledMethod:, deleteAllSelectors:, deleteSelector:, deleteSelector:ifAbsent:

Note: The Blue Book messages addSelector:withMethod: and removeSelector: areintegrated with source code management systems on most platforms.Changing the semantics of these messages to remove this dependencywould have broken too much existing code. We decided instead to add newmessages that are neutral regarding source code management; that is, theyare intended to exist outside the source code management system.

Porting tip: Neither Smalltalk/V nor Objectworks\Smalltalk supports thesemessages.

Tip: Using addCompiledMethod:, deleteAllSelectors:, deleteSelector:, ordeleteSelector:ifAbsent: might make the image inconsistent with the source codemanagement system. These methods should only be sent by experienceddevelopers who are certain of the outcome. Objectworks\Smalltalk supportthese messages.

Method queriesallMethodsNamed:, allMethodsReferencingInstVarName:, allMethodsReferencingLiteral:,allMethodsSending:, allMethodsSendingAll:, canUnderstand:, hasMethods,includesSelector:, whichMethodsReferenceInstVarName:, whichMethodsReferenceLiteral:,whichMethodsSend:, whichMethodsSendAll:, whichMethodsReferenceInstVarName:,whichMethodsReferenceLiteral:, whichMethodsSend:, whichMethodsSendAll:

Note: The Blue Book only defines the messages canUnderstand:, hasMethods, andincludesSelector:. We decided to provide a richer set of method querymessages so that it would be possible to hide implementation detailswithout losing functionality.

Porting tip: Smalltalk/V only supports canUnderstand: and includesSelector:, as wellas several messages designed to query methods about instance andclass variable references. Objectworks\Smalltalk supports only the BlueBook messages canUnderstand:, hasMethods, and includesSelector:.

Class messagesThe class Class describes the representation and behavior of objects.

36 IBM Smalltalk: Programmer’s Reference

Page 51: IBM Smalltalk: Programmer's Reference

Class variable accessingaddClassVarName:, allClassVarNames, classPool, classVarNames, removeClassVarName:,setClassPool:

Note: These are all Blue Book messages except setClassPool:. The messagesetClassPool: is a basic accessor that works outside the source code manager.

Porting tip: All supported by both Smalltalk/V and Objectworks\Smalltalk exceptsetClassPool:.

Instance variable accessingaddInstVarName:, allInstVarNames, instVarNames, removeInstVarName:

Note: These are all Blue Book messages. Note that it is not possible to addinstance variables to variable byte classes.

Porting tip: Smalltalk/V does not support addInstVarName: andremoveInstVarName:.

Shared pool accessingaddSharedPoolName:, allSharedPoolNames, removeSharedPoolName:, setSharedPoolNames:,sharedPoolNames

Note: The Blue Book defines the messages addSharedPool:, allSharedPools,removeSharedPool:, and sharedPools, but it takes an inconsistent approach toidentifying the shared pool dictionary, referencing it sometimes by name andother times by value. We decided to standardize on reference by name, andappended the suffix Name to the messages to reinforce this point. Theaggregate message setSharedPoolNames: is a basic accessor that works outsidethe source code manager. There is no Blue Book equivalent tosetSharedPoolNames:.

Porting tip: Not supported by Smalltalk/V or Objectworks\Smalltalk. Smalltalk/Vprovides instead the messages addSharedPool:, removeSharedPool:,sharedPool, and sharedPool:. Objectworks\Smalltalk provides the BlueBook messages noted above in the Rationale; however, it changes theBlue Book semantics to always use reference by value.

Tip: Using setSharedPoolNames: will make the image inconsistent with the sourcecode management system. This method should only be sent by experienceddevelopers who are certain of the outcome.

Class accessingcomment, comment:, definitionString, setClassName:

Note: The message setClassName: is a basic accessor that works outside the sourcecode manager. No renaming messages aside from setClassName: are includedin this release of CLIM. Under normal circumstances renaming should beunder the control of the source code manager.

Porting tip: Smalltalk/V and Objectworks\Smalltalk both support comment andcomment:. Objectworks\Smalltalk has a message named definition that isthe same as definitionString, while Smalltalk/V has no such message.

Chapter 3. Common Language Implementation 37

Page 52: IBM Smalltalk: Programmer's Reference

Neither supports setClassName:. Both Smalltalk/V andObjectworks\Smalltalk provide other messages for renaming classes.

Tip: Using setClassName: will make the image inconsistent with the source codemanagement system. This method should only be sent by experienceddevelopers who are certain of the outcome.

Initializing and removinginitialize, removeFromSystem

Note: The message removeFromSystem is integrated with the source code manager,and therefore safe to use.

Superclass accessingconnectToSuper, disconnectFromSuper

Note: These messages both operate outside the scope of the source code manager.

Porting tip: Smalltalk/V and Objectworks\Smalltalk provide other messages thathave the same effect.

Tip: Using connectToSuper or disconnectFromSuper will make the image inconsistentwith the source code management system. This method should only be sentby experienced developers who are certain of the outcome.

Metaclass messagesThe class Metaclass provides protocol for accessing the metaclass’s primaryinstance.

AccessingprimaryInstance, primaryInstance:

Note: Needed to access the class that is the primary instance of the metaclass.

Porting tip: Not supported in Smalltalk/V. Objectworks\Smalltalk provides theaccessor only, calling it soleInstance rather than primaryInstance.

Creating new classesCLIM defines several messages for creating new classes. A class is usually createdby defining it as a subclass of an existing class; in that case, the class creationmessage is sent to the superclass. This message actually results in two classes beingadded to the system, not one. First, a metaclass is created that describes the newclass, and then the metaclass is instantiated to create the class itself.

A few restrictions apply when creating new classes. Any subclass of a variableclass, that is, a class like Array that has indexed instance variables, must also be avariable class. Similarly, any subclass of a variable byte class, that is, a class likeString that has indexed instance variables that are bytes, must also be a variablebyte class. Variable byte classes cannot have named instance variables, and anyclass with a named instance variable cannot have variable byte subclasses.

38 IBM Smalltalk: Programmer’s Reference

Page 53: IBM Smalltalk: Programmer's Reference

Sometimes developers need to create classes that are not subclasses of an existingclass. To support this, the special object nil, described in the previous section onCLDT, is extended so that it also understands the class creation messages.

We refer to a class that has no indexed instance variables, that is, only namedinstance variables, as a fixed class.

Creating fixed classessubclass:classInstanceVariableNames:instanceVariableNames:classVariableNames:poolDictionaries:,subclass:instanceVariableNames:classVariableNames:poolDictionaries:

Note: These messages can only be sent to another fixed class.

Porting tip: Smalltalk/V supports the second message, but not the first, whileObjectworks\Smalltalk supports neither. Neither Smalltalk/V norObjectworks\Smalltalk provide Class messages for creating classes withclass instance variables, although it is possible to build such classes.Objectworks\Smalltalk uses different subclass creation messages thatalso specify the category.

Creating variable classesvariableSubclass:classInstanceVariableNames:instanceVariableNames:classVariableNames:-poolDictionaries:,variableSubclass:instanceVariableNames:classVariableNames:poolDictionaries:

Note: These messages can only be sent to a fixed class or another variable class.

Porting tip: Smalltalk/V supports the second message, but not the first, whileObjectworks\Smalltalk supports neither. Neither Smalltalk/V norObjectworks\Smalltalk provide Class messages for creating classes withclass instance variables, although it is possible to build such classes.Objectworks\Smalltalk uses different subclass creation messages thatalso specify the category.

Creating variable byte classesvariableByteSubclass:classInstanceVariableNames:classVariableNames:- poolDictionaries:,variableByteSubclass:classVariableNames:poolDictionaries:

Note: These messages can only be sent to another variable byte class.

Porting tip: Smalltalk/V supports the second message, but not the first, whileObjectworks\Smalltalk supports neither. Neither Smalltalk/V norObjectworks\Smalltalk provide Class messages for creating classes withclass instance variables, although it is possible to build such classes.Objectworks\Smalltalk uses different subclass creation messages thatalso specify the category.

Extended classesCLIM extends the classes Array, String, and DBstring.

Chapter 3. Common Language Implementation 39

Page 54: IBM Smalltalk: Programmer's Reference

Multiple instance accessingMultiple Instance Accessing

The following methods are Array instance methods.

basicMultiAllInstances, MultiAllInstances

Note: Neither method is in the Blue Book, but they have been included in CLIMas an efficient way of accessing multiple instances.

Porting tip: Neither Smalltalk/V nor Objectworks support multiAllInstances orbasicMultiInstances.

String convertingThe following methods are String and DBString instance methods.

asClassPoolKey, asGlobalKey, asPoolKey

Note: The messages asClassPoolKey, asGlobalKey, and asPoolKey are not in the BlueBook. They have been added to IBM Smalltalk to provide developers with away to ensure that class variables, global variables, and pool dictionary keyshave the class that is correct for the platform (usually either String orSymbol). IBM Smalltalk will not accept class variables, global variables, orpool dictionary keys containing characters whose value exceeds 255;consequently asClassPoolKey, asGlobalKey, and asPoolKey messages will not beuseful if sent to a DBString that contains these characters.

Porting tip: Neither Smalltalk/V nor Objectworks\Smalltalk support asClassPoolKey,asGlobalKey, or asPoolKey.

Compiling and evaluating codeAlthough the Blue Book describes the Smalltalk compiler, it does not actuallyspecify any of the messages that it should support. The various Smalltalk dialectsare not consistent on whether to access the compiler through Compiler classmethods, or to create a compiler instance and access compilation facilities throughinstance methods. IBM Smalltalk takes the first approach, but the choice iscompletely arbitrary.

A key question is how to handle compile errors. CLIM defines an object thatencapsulates all of the error information that a compiler might return. ACompilerError is required to support the following accessor messages, each of whichreturns one of the attributes of the error object:

context Answers the class in whose context the source code was compiled

messageAnswers the compiler error or warning message

sourceStringAnswers the source code string that was compiled

startPositionAnswers the position in the source code string of the first character of thetoken at which the error or warning was detected

40 IBM Smalltalk: Programmer’s Reference

Page 55: IBM Smalltalk: Programmer's Reference

stopPositionAnswers the position in the source code string of the last character of thetoken at which the error or warning was detected

Compiler error handling in CLIM works as follows:1. Several of the class messages defined for Compiler accept as a parameter a

one-argument block, called the fail block.2. If the compilation is successful, these messages return an instance of

CompiledMethod, described in the next section.3. However, if a compiler warning or error occurs, a CompilerError describing the

error is created.4. It is then passed as an argument to the fail block, which is evaluated.5. The result of evaluating the fail block is returned.

Note that CLIM does not define how the CompilerError is created, or how itsattributes are set. These are assumed to be platform-specific operations. Thismechanism was chosen because it provides a fairly general way to handlewarnings and errors, but does not require a complex runtime infrastructure.

The compilation facilities provided in CLIM support two distinct activities:compiling and evaluating.

Compilingcompile:inClass:, compile:inClass:ifFail, compile:inClass:warningLevel:onWarning:ifFail:

Note: Each of these messages compiles the source code provided in the firstparameter in the context of the second parameter, which must be a class. Tocompile in the context of a class means that the compiler will try to interpretvariable references as instance, class, or pool variables of the designatedclass. These messages return a CompiledMethod if they are successful. Thecompile:inClass: message uses default error handling that returns nil if awarning or error is detected. The compile:inClass:ifFail: message accepts a failblock as the third parameter, and answers the result of evaluating the failblock if a warning or error is detected. Thecompile:inClass:warningLevel:onWarning:ifFail: message accepts a warninglevel, warning block, and fail block as parameters. If an error is detected, theresult of evaluating the fail block as answered. If a warning is detected, thewarning block is evaluated with an instance of CompilerError. If that answerstrue, the compile fails, and the CompilerError is answered. Otherwise thecompile continues.

Porting tip: Not supported in Smalltalk/V and Objectworks\Smalltalk, which eachprovide their own different messages to support compiling.

Evaluatingevaluate:, evaluate:for:, evaluate:for:ifFail:, evaluate:for:warningLevel:onWarning:ifFail:

Note: Each of these messages evaluates source code in the context of an object. Toevaluate in the context of an object means that the compiler will try to interpretvariable references as instance, class, or pool variables of the designatedobject’s class, and that instance variable references is bound to the values ofthe object’s instance variables when the compiled code is run. The firstparameter of each of these messages is always the source code to beevaluated. The message evaluate: evaluates in the context of the special object

Chapter 3. Common Language Implementation 41

Page 56: IBM Smalltalk: Programmer's Reference

nil. Error handling follows the same model as for compiling, that is, if awarning or error is detected during compilation, either a CompilerError orthe result of evaluating a fail block is returned.

Porting tip: Smalltalk/V and Objectworks\Smalltalk each support evaluate:, butotherwise they provide their own different messages to supportevaluating.

CompiledMethodA CompiledMethod is an abstraction for compiled code. CompiledMethod is describedin the Blue Book, but no protocol is actually defined for them. The exactrepresentation of a compiled method is, of necessity, platform-specific. CLIMdefines only those basic accessing and testing messages that do not need to makeany assumptions about structure or representation.

AccessingmethodClass, methodClass:, selector, selector:, sourceString, symbolLiterals

Porting tip: Smalltalk/V supports only selector, selector:, and sourceString.Objectworks\Smalltalk does not support any of these messages, butdoes provide equivalent ways to access the same information.

Testingequals:, isPrimitive, isUserPrimitive, referencesLiteral:, sendsSelector:, getsInstVar:,setsInstVar:, referencesInstVar:

Porting tip: Smalltalk/V does not support any of these messages.Objectworks\Smalltalk supports only sendsSelector:, although it also hasa message called refersToLiteral: that is similar to referencesLiteral:. BothSmalltalk/V and Objectworks\Smalltalk redefine =. We decided todefine an equals: message with the correct semantics instead.

EmSystemConfigurationEach IBM Smalltalk system includes a single instance of the classEmSystemConfiguration, accessed through the global variable System. System servestwo functions: It provides access to useful information about how the image isconfigured, and it also accepts messages to save the image and shut down thesystem.

The current system configuration can be obtained by sending System the messageconfiguredSubsystems. This returns a dictionary showing which variant of each IBMSmalltalk subsystem is configured, keyed by the subsystem name. The keys mustinclude one of the following strings: ‘CLDT,’ ‘CLIM,’ ‘CPM,’ ‘CFS,’ ‘CG,’ ‘CW,’ or‘CP.’

Typical values for each subsystem key are shown in the following table. This tablemight not be complete. Other values might be supported in subsequent releases.

Table 6. Typical values for subsystem keys

Key Typical values

‘CLDT’ ‘ES’

‘CLIM’ ‘ES’

42 IBM Smalltalk: Programmer’s Reference

Page 57: IBM Smalltalk: Programmer's Reference

Table 6. Typical values for subsystem keys (continued)

Key Typical values

‘CPM’ ‘ES’

‘CFS’ ‘POSIX,’ ‘OS/2,’ ‘WIN32s’

‘CG’ ‘X,’ ‘PM,’ ‘WIN32s’

‘CW’ ‘MOTIF,’ ‘PM,’ ‘WIN32s’

‘CP’ ‘PM,’ ‘WIN32s’

If a platform is not supported, the value for its key is ‘UNSUPPORTED’. If anysubsystem is not configured, the value for its key is nil. This might be the case, forexample, for a packaged Smalltalk system that has no file subsystem loaded. Themessage setSubsystemType:to: can be used to set or change the system configuration.The first parameter is the name of the subsystem, which must be one of thesubsystem key strings listed above. The second parameter is one of the allowedvalues for the subsystem, or nil, in which case the image has no configuration forthat subsystem.

It is also possible to use the message subsystemType: to make a specific queryregarding the configuration of a particular subsystem. The parameter is once againone of the subsystem names, and the return value is one of the allowed values ornil.

Other accessing messages supported are copyright and vmType. The messagecopyright answers the system’s copyright message, while vmType answers thevirtual machine type for the system.

As mentioned, EmSystemConfiguration also provides support for exiting and savingthe image. The message exit ends the Smalltalk system. Sending saveImage causes asnapshot to be taken of the current state of the image and writes it to disk. Theexact mechanisms used, such as dialogs invoked, options supported, and name ofthe saved file, are platform-specific. When the Smalltalk system is next invoked,the most recent image snapshot is restored.

Chapter 3. Common Language Implementation 43

Page 58: IBM Smalltalk: Programmer's Reference

44 IBM Smalltalk: Programmer’s Reference

Page 59: IBM Smalltalk: Programmer's Reference

Chapter 4. Common Process Model

The Common Process Model (CPM) subsystem provides a process model (sharedmemory threads) for IBM Smalltalk. Standard operations include process creationand destruction, as well as process scheduling operations including suspend, resume,and change priority. Simple synchronization mechanisms are provided bysemaphores. CPM is essentially an implementation of the process model describedin the Blue Book (where you can find more details). Note that CPM does notinclude the Blue Book class SharedQueue.

Please refer to “The user interface process model” on page 225 (in this book) for adiscussion of the input event processing model on which the Common Widgetsuser interface is based.

CPM supports the running of multiple independent processes using four classesnamed Process, ProcessorScheduler, Delay, and Semaphore. An instance of Processrepresents a sequence of message sends that has an independent thread ofexecution. A unique instance of the class ProcessorScheduler, the global variableProcessor, is responsible for scheduling these processes for execution by the virtualmachine. Instances of Semaphore class provide a mechanism for processsynchronization and (indirectly) communication. The class Delay enables processesto synchronize with the real-time clock and to control their execution with fixedtime delays.

Creating a processA process is normally created by sending the fork or forkAt: message to a block asshown in the following example. This process is immediately scheduled forexecution. The fork message schedules the new process at the same priority as theprocess running the fork, while forkAt: allows the priority to be explicitly specified.When the new process runs, it evaluates the block. A reference to the new processcan be retained by assigning it to an instance or temporary variable.| process |process := [Transcript show: 'The rain in Spain'; cr] fork.

A process can be created in a suspended state by sending the newProcess messageto a block as shown in the next example. The new process is not scheduled forexecution until it is sent the resume message.| process |process := [Transcript show: 'The rain in Spain'; cr] newProcess.process resume.

Protocol also exists for creating a process and passing its creation block a set ofarguments as shown in the following example. Here a string value is passed to aone-argument block. The number of arguments passed to the block must match thenumber of formal block parameters.| process |process := [:value | Transcript show: value; cr]

newProcessWith: #('The rain in Spain').process resume.

© Copyright IBM Corp. 1994, 2000 45

Page 60: IBM Smalltalk: Programmer's Reference

Suspending, resuming, and ending a processOnce a process is created, it can be suspended, resumed, or ended. A process istemporarily halted by sending it the suspend message. The process can be restartedlater by sending it the resume message. A process is stopped permanently, that is,placed in a state from which it cannot be resumed, when it is sent the terminatemessage.

Setting and modifying process prioritiesProcessorScheduler implements a round-robin with priorities scheduler. In other words,a running process will hold the CPU until one of the following occurs:v It performs an operation that causes it to suspend (see Table 7 on page 47 for a

list of the primary operations that cause a process to suspend).v Another process of higher priority is resumed.v The process is ended.

At that point, the scheduling algorithm ensures that the highest priority processthat is ready to run next. If there is more than one process satisfying this criterion,then the process that has been waiting longest is selected for execution.

Consequently, the order in which processes run can be influenced by changing thepriority assigned to a process. There are seven preassigned priority levels. Thepriority constants in increasing order are as follows:

1. systemBackgroundPriorityThe priority of a system background process

2. userBackgroundPriorityThe priority of a user background process

3. userSchedulingPriorityThe priority of the user interface process (also the default priority of anyprocess forked by the user interface process)

4. userInterruptPriorityThe priority of any process forked by the user interface that should be runimmediately

5. lowIOPriorityThe usual priority for input/output processes

6. highIOPriorityThe priority of the process monitoring the local network devices

7. timingPriorityThe priority of the process monitoring the real-time clock

On many platforms the priorities are actually mapped to the integers 1 through 7;however, it is poor programming style to reference the priorities directly as integralvalues. The preferred approach is to use the priority accessors provided byProcessorScheduler. You can query a process priority and modify its value asrequired. In the next example, the priority and priority: messages are used to queryand modify the priority of the process. Note, however, that if a priority is changed,the change has no effect on scheduling until the next process switch.

46 IBM Smalltalk: Programmer’s Reference

Page 61: IBM Smalltalk: Programmer's Reference

| process |process := [Transcript show: 'The rain in Spain'; cr] newProcess.Transcript show: process priority printString; cr.process priority: Processor userBackgroundPriority.Transcript show: process priority printString; cr.

Table 7. Primary operations that cause a process to suspend

Operation Relevant method Method’s class

Directly suspend a process suspend Process

Wait on a semaphore wait Semaphore

Wait on a delay wait Delay

Open a debugger on anactive process

reportError:resumable:startBP EtWindowSystemStartUp

Debug an active processfrom within a debugger

addProcess EtDebugger

Use execLongOperation toevaluate a block in thebackground (causes theregular UI process tosuspend)

execLongOperation: EtWindow

Resume another process ofhigher priority

resume Process

Create another process ofhigher priority (when thenext context switch occurs)

forkAt: Block

Change the priority ofanother process to be greaterthan this process (when thenext context switch occurrs)

priority: Process

Synchronization using semaphore and delayInstances of class Semaphore are used for interprocess synchronization. Semaphorescan be thought of as containers for signals. (Signals are not on/off switches;multiple signals can be queued up.) Sending the message signal to a semaphoreadds a signal, while sending the message wait removes a signal. If a semaphorethat has no signals is sent the wait message, the process running the wait issuspended until the semaphore is sent a signal message. If more than one processis waiting on a semaphore when a signal is sent, the longest waiting process isresumed.

The following example illustrates the use of Semaphores. A process is forked at ahigh priority. It blocks, waiting on a Semaphore. Each time the user interface signalsthe Semaphore the forked process unblocks, increments a counter, and blocks on theSemaphore again. The user interface process then prints the counter value. After theexample is run, the Semaphore becomes garbage, and the original processdisappears with the Semaphore.| count aSemaphore testProcess output |output := WriteStream on: String new.count := 1.aSemaphore := Semaphore new.testProcess := [

[true] whileTrue: [aSemaphore wait.output nextPutAll: 'Process has acquired the Semaphore. ',

Chapter 4. Common Process Model 47

Page 62: IBM Smalltalk: Programmer's Reference

'Incrementing count.'; cr.count := count + 1.]

] forkAt: Processor timingPriority.

aSemaphore signal.output nextPutAll: 'After First signal, count = ', count printString; cr.aSemaphore signal.output nextPutAll: 'After Second signal, count = ', count printString; cr.Transcript show: output contents

Transcript Output:

Process has acquired the Semaphore. Incrementing count.After First signal, count = 2Process has acquired the Semaphore. Incrementing count.After Second signal, count = 3

Instances of class Delay are used to effect synchronization with the real-time clock,and to postpone process execution for a specified time period. Postponement canbe specified in milliseconds, seconds, or until a specific time. Each Delay has aresumption time specified in milliseconds since midnight. When the Delay is sent thewait message, the process running the wait operation is suspended until thereal-time clock advances to the resumption time specified by the Delay.

To illustrate the use of Delay, evaluate the following code fragment. A message isdisplayed on the Transcript after about 15 seconds.[(Delay forSeconds: 15) wait.

Transcript show: 'Executing delay example'; cr] fork.

Block evaluation methodsAdditional Block methods are supported in CPM that allow a block to beevaluated, with or without arguments, and the result of the last statementanswered. These methods follow in “Block evaluation methods”.

Protocol synopsisThe principle classes and methods in CPM are summarized below.

In “Block evaluation methods”, anObject, anotherObject, and thirdObject refer to thefirst, second, and third parameters of the method.

Block evaluation methods: The following instance methods pertain to blockevaluation:

argumentCountAnswers the number of arguments to the receiver.

value Evaluates the receiver. Answers the result of the last statement to beevaluated.

value: Evaluates the receiver with parameter anObject. Answers the result of thelast statement to be evaluated.

value:value:Evaluates the receiver with parameters anObject and anotherObject. Answersthe result of the last statement to be evaluated.

value:value:value:Evaluates the receiver with parameters anObject, anotherObject, andthirdObject. Answers the result of the last statement to be evaluated.

48 IBM Smalltalk: Programmer’s Reference

Page 63: IBM Smalltalk: Programmer's Reference

valueWithArguments:Evaluates the receiver with the specified array. Answers the result of thelast statement to be evaluated.

valueOnReturnDo:Evaluates the receiver. Answers the result of the last statement to beevaluated. When the receiver returns, evaluate the specified block.

value:onReturnDo:Evaluates the receiver with parameter anObject. Answers the result of thelast statement to be evaluated. When the receiver returns, evaluate thespecified block.

value:value:onReturnDo:Evaluates the receiver with parameters anObject and anotherObject. Answersthe result of the last statement to be evaluated. When the receiver returns,evaluate the specified block.

value:value:value:onReturnDo:Evaluates the receiver with parameters anObject, anotherObject, andthirdObject. Answers the result of the last statement to be evaluated. Whenthe receiver returns, evaluate the specified block.

valueWithArguments:onReturnDo:Evaluates the receiver with the specified array. Answers the result of thelast statement to be evaluated. When the receiver returns, evaluate thespecified block.

Tip: These additional Block methods allow a block to be evaluated, with or withoutarguments, and the result of the last statement answered. anObject,anotherObject, and thirdObject parameters refer to the first, second, and thirdparameters of the method.

Process-related block methodsThe following instance methods pertain to process-related blocks:

fork Creates and schedules a new process to evaluate the receiver block, usingthe priority of the activeProcess (Processor activePriority).

forkAt: Creates and schedules a new process to evaluate the receiver block, at thespecified priority.

newProcessCreates a new process to evaluate the receiver block, using the priority ofthe activeProcess, and places it in suspended state. The new process isscheduled by sending it the resume message.

newProcessWith:Creates a new process to evaluate the receiver block with the specifiedarguments, using the current priority, and places it in suspended state. Thenew process is scheduled by sending it the resume message.

Process methodsThe following instance methods pertain to processes:

priorityAnswers the receiver’s priority.

priority:Sets the receiver’s priority to be the specified value.

Chapter 4. Common Process Model 49

Page 64: IBM Smalltalk: Programmer's Reference

queueInterrupt:Runs the argument block in the receiving process.

resume Resumes the receiver.

suspendPlaces the receiver in suspended state.

terminateTerminates the receiver.

Porting tip: ProcessorScheduler is called ProcessScheduler in Smalltalk/V.

ProcessorScheduler methodsThese messages are sent to the Processor global variable.

The following instance methods pertain to ProcessScheduler:

activePriorityAnswers the priority of the current active process in the system.

activeProcessAnswers the current active process in the system.

highIOPriorityAnswers the priority of the process monitoring the local network devices.

lowIOPriorityAnswers the usual priority for input/output processes.

signal:atTime:Informs the system that it should signal a semaphore at the resumptiontime, specified in milliseconds since midnight.

systemBackgroundPriorityAnswers the priority of a system background process.

timingPriorityAnswers the priority of the process monitoring the real-time clock.

userBackgroundPriorityAnswers the priority of a user background process.

userInterruptPriorityAnswers the priority of any process forked by the user interface thatshould be run immediately.

userSchedulingPriorityAnswers the priority of the user interface process; also the default priorityfor any process forked by the user interface process.

Delay class and instance methodsThe class methods for Delay include the following:

forMilliseconds:Answers a new Delay that, when sent the message wait, suspends theactive process for a specified millisecond count.

forSeconds:Answers a new Delay that, when sent the message wait, suspends theactive process for a specified second count.

50 IBM Smalltalk: Programmer’s Reference

Page 65: IBM Smalltalk: Programmer's Reference

untilMilliseconds:Answers a new Delay that, when sent the message wait, suspends theactive process until the millisecond clock reaches the specified value.

The instance methods include the following:

resumptionTimeAnswers the millisecond clock value at which to resume the waitingprocess.

wait Suspends the active process for the delay period.

Semaphore class and instance methodsThe class methods for Semaphore include the following:

forMutualExclusionAnswers a new semaphore that has one signal.

new Answers a new semaphore that has no signals.

The instance methods include the following:

critical:Evaluates the argument block and guarantees that there will be no contextswitch while the block is being evaluated.

signal Adds a signal to the receiver.

wait Suspends the active process until there is a signal available from thereceiver.

Chapter 4. Common Process Model 51

Page 66: IBM Smalltalk: Programmer's Reference

52 IBM Smalltalk: Programmer’s Reference

Page 67: IBM Smalltalk: Programmer's Reference

Chapter 5. Common File System

The Common File System subsystem (CFS) enables you to access the capabilities ofthe platform file system in a platform-independent manner.

Accessing the capabilities of the Common File SystemCapabilities of the platform file system include basic file protocols, streamprotocols, portability protocols, and error handling protocols. Classes in theCommon File System are prefixed by the letters ‘Cfs,’ for example: CfsFileDescriptor.

Basic file protocolsThe Common File System provides a set of low-level file protocols based on thePOSIX.1 standard. This includes standard protocols for the following:v Unbuffered input and output on file descriptors: open, close, read, write, lseek,

rewind, flush, and size.v Searching directory entries: opendir, closedir, readdir, and rewinddirv Managing files and directories: chdir, getcwd, remove (unlink), rename, mkdir,

and rmdirv Testing existence of files and directories, and obtaining file statistics: statv File locking and sharing

Stream protocolsThe Common File System also extends POSIX.1 to provide file stream protocolsthat conform to and extend those specified by the Blue Book. These protocolsprovide simplified buffered input and output, and are designed to cooperate withand complement the basic file protocols. In fact, the stream protocols themselvesare implemented portably by using the base file protocols.

Portability protocolsThe Common File System also provides protocols to deal with unavoidableplatform-specific attributes, such as line delimiters, path separators, file systemroots, and startup directory, in a portable manner. Extensions to POSIX.1 are alsoprovided for the following:v Copyingv Suppressing platform error dialogsv Obtaining volume information: caseSensitive, preservesCase, maximumFileLength,

volumeName, and volumeType.

Error handling protocolsAll basic Common File System methods and file stream class methods supportintegrated error handling by answering an instance of CfsError if an error occurs.Error constants are the same on all platforms, and are a subset of the POSIX.1 errorconstants. To determine if an error has occurred, send isCfsError to the resultreturned from the operation. Only instances of CfsError answer true to thismessage. All other objects answer false.

© Copyright IBM Corp. 1994, 2000 53

Page 68: IBM Smalltalk: Programmer's Reference

CfsConstants pool dictionaryThe Common File System subsystem provides a pool dictionary called CfsConstantsthat contains constants for specifying values such as file access modes, creationflags, share modes, and error numbers.

Basic classes

CfsVolumeInfoThe CfsVolumeInfo class enables you to obtain information about a volume.

CfsDirectoryDescriptorThe CfsDirectoryDescriptor class provides services for creating, removing, andquerying directories.

CfsDirectoryEntryThe CfsDirectoryEntry class represents the information stored in the directory entryfor a particular file.

CfsFileDescriptorThe CfsFileDescriptor class provides services for creating, removing, querying,reading, and writing files. This includes position control and locking services.

CfsStatThe CfsStat class provides a mechanism for obtaining statistical information (filesize, file type, modification date) about files and directories.

CfsErrorThe CfsError class provides a mechanism for obtaining error information pertainingto file stream creation, file, directory, and file stat operations.

Specifying file names and pathsFile names, directories, and paths are specified using strings. All Common FileSystem methods accept and return file names and paths using the syntax of theplatform file system. You can use both absolute paths and paths relative to thecurrent working directory.

Portable file namesPortable file names should consist of no more than eight characters, plus anoptional extension consisting of a period followed by no more than threecharacters. Valid characters are uppercase and lowercase letters, digits, theunderscore (_), and the hyphen (-). For portability, applications should not assumethat file names are case sensitive or case insensitive.

The CfsVolumeInfo class can be used to portably determine file name length andcase sensitivity for a specific volume. See “Obtaining volume information” onpage 57.

All CFS protocols support the use of DBStrings as file names in locales thatsupport the use of double-byte characters (characters whose values range from 0 to65535). The limitations on file name length imposed by many platforms are oftendetermined by the number of bytes in the file name rather than the number ofcharacters. Because each character in a DBString can require either one or twobytes of storage, a DBStringcontaining eight characters is not necessarily a valid filename in any given operating system. The use of file names containing double-bytecharacters is not portable.

54 IBM Smalltalk: Programmer’s Reference

Page 69: IBM Smalltalk: Programmer's Reference

File system rootsBecause some platforms have multiple file system roots while others do not, it isimportant to be able to obtain the root(s) of the file system. Sending rootDirectoriesto the CfsDirectoryDescriptor class answers an array of one or more fully qualifiedpaths to the root directories of the file system. Examples are shown below:CfsDirectoryDescriptor rootDirectories."For OS/2: #('A:\' 'B:\' 'C:\' 'D:\' 'F:\' 'G:\')""For UNIX: #('/')"

Path separatorsThe path separator used for specifying file names is dependent on the underlyingfile system. Applications can obtain the path separator by sending either thepathSeparator or pathSeparatorString messages to CfsDirectoryDescriptor class, whichanswers the path separator as a character, and as a string, respectively. Both havetheir uses, as demonstrated here:"Check if a path ends with a path separator"|'/usr/local/bin/' last = CfsDirectoryDescriptor pathSeparator.

"Build a path starting with the first root directory"| firstRoot |firstRoot := CfsDirectoryDescriptor rootDirectories first.|firstRoot, 'data', CfsDirectoryDescriptor pathSeparatorString, 'mystuff'.

Managing files and directoriesThe CfsFileDescriptor and CfsDirectoryDescriptor classes provide common protocolfor file and directory management operations. These protocols are Smalltalkequivalents of POSIX.1 functions.

Current working directoryA string specifying the full path for the current working directory can be obtainedby sending getcwd to the CfsDirectoryDescriptor class. To change the currentworking directory, use chdir: as in the following examples:CfsDirectoryDescriptor chdir: 'C:\WINDOWS'.CfsDirectoryDescriptor chdir: 'system'.CfsDirectoryDescriptor chdir: CfsDirectoryDescriptor rootDirectories last.

Creating and removing directoriesA new directory can be created by sending the mkdir: message to theCfsDirectoryDescriptor class. An existing directory can be removed by sending thermdir: message to the CfsDirectoryDescriptor class.CfsDirectoryDescriptor mkdir: 'data'.

CfsDirectoryDescriptor rmdir: 'data'.

Note: Deleting the current working directory can result in unrecoverable errorsdue to platform operating system behavior. Platforms with drives demandspecial caution, because they usually maintain a separate working directoryfor each drive. Changing the current working directory to another drivebefore deleting the old working directory will not necessarily prevent anerror from occurring, because the current working directory associated withthe original drive can remain unchanged. Instead, change the currentworking directory to the root of the drive containing the directory you wantto delete.

Chapter 5. Common File System 55

Page 70: IBM Smalltalk: Programmer's Reference

"The wrong way""Current working directory might be C:\USELESS"CfsDirectoryDescriptor chdir: 'D:\APPLICATION'.CfsDirectoryDescriptor rmdir: 'C:\USELESS'.

"The right way""Current working directory might be C:\USELESS""Prevents working dir for drive C: from being USELESS"CfsDirectoryDescriptor chdir: 'C:\'."If you really want to end up in this dir"CfsDirectoryDescriptor chdir: 'D:\APPLICATION'.CfsDirectoryDescriptor rmdir: 'C:\USELESS'.CfsDirectoryDescriptor chdir: 'C:\'.

Deleting filesDelete unwanted files by sending the remove: message to the CfsFileDescriptor class,as in the following example:CfsFileDescriptor remove: 'unwanted.fil'.

Renaming filesRename a file by sending the rename:new: message to the CfsFileDescriptor class, asin the following example:CfsFileDescriptor rename: 'oldname.txt' new: 'newname.txt'.

Note: If supported by the platform file system, rename:new: can also be used torename directories or move files between directories on the same drive ordevice.

Copying filesA file can be copied by sending the copy:new: message to the CfsFileDescriptor class.An example is shown below.CfsFileDescriptor copy: 'filename.txt' new: 'filename.bak'.

Tip: On platforms which do not provide an OS file copy function, copy:new: isperformed using buffered read/write.

Copy can be performed across devices. An example of an efficient move functionimplemented using rename and copy is shown below. For an explanation of errnocodes, see “Handling errors” on page 71.| result pathA pathB |"Attempt to move the from pathA to pathB using rename.If that fails because it cannot rename across devices,copy it and delete the original."pathA := 'C:\temp\test.txt'.pathB := 'A:\test.new'.result := CfsFileDescriptor rename: pathA new: pathB.(result isCfsError and: [result errno = EXDEV] )

ifTrue: ["Platform cannot rename across devices"result := CfsFileDescriptor copy: pathA new: pathB.result isCfsError

ifFalse: ["Copy successful, delete original"result := CfsFileDescriptor remove: pathA.

].].

|result

56 IBM Smalltalk: Programmer’s Reference

Page 71: IBM Smalltalk: Programmer's Reference

Startup directoryThe path to the directory in which the Smalltalk image was started can be obtainedby sending the startUpDirectory message to the CfsDirectoryDescriptor class. Thispath is in a format acceptable to CfsDirectoryDescriptor class>>#chdir:, and thereforemight or might not end with a path separator. CfsDirectoryDescriptorclass>>#startUpDirectoryPath answers the full path ending with a path separator.This latter format is suitable for concatenation of paths.

Obtaining volume informationA CfsVolumeInfo object can be obtained for any directory, and reports file systemcharacteristics for the volume associated with that directory. Volume informationoperations are extensions of the POSIX.1 standard.

CfsVolumeInfo class>>#volumeInfo: answers a new CfsVolumeInfo instance for thevolume associated with the directory specified by the path argument.CfsVolumeInfo>>#volumeInfo: is functionally identical, however it reuses the receiverCfsVolumeInfo instance.

CfsVolumeInfo instance protocol is described in this section.

Tip: Wherever possible, the operating system is only queried if and when amessage is sent, and the answered value is cached for later queries to thesame instance.

Volume name and typeThe path to the root of a volume can be obtained by sending #volumeName to aninstance of CfsVolumeInfo. The volumeType method answers a string that specifiesthe volume type, for example, ‘FAT,’ ‘HFS,’ ‘HPFS,’ ‘MFS,’ ‘UNIX,’ or ‘VFAT.’ Thefollowing example queries the volume type for the default volume:"Answer the volumeType of the default volume."(CfsVolumeInfo volumeInfo: CfsDirectoryDescriptor getcwd) volumeType.

File names and directory path caseCase sensitivity of file names and paths on a volume can be determined bysending caseSensitive to a CfsVolumeInfo instance. The preservesCase method can beused to determine if the volume preserves the case of file names and paths.

File name lengthThe maximumFilenameLength method answers the maximum length, in bytes, whichthe volume allows for file names and path components. Examples are as follows:"Answer the maximumFilenameLength for the default volume,or a CfsError if it cannot be obtained."| volInfo |volInfo := CfsVolumeInfo volumeInfo: CfsDirectoryDescriptor getcwd.|volInfo isCfsErrorifTrue: [volInfo]ifFalse: [volInfo maximumFilenameLength].

"Answer the maximumFilenameLength, ignoring any error."| volInfo |(volInfo := CfsVolumeInfo new) volumeInfo: CfsDirectoryDescriptor getcwd.|volInfo maximumFilenameLength.

Chapter 5. Common File System 57

Page 72: IBM Smalltalk: Programmer's Reference

Volumes with different file name lengthsThe formatFilename: method can be used to shorten its filename argument to fit thevolumes’ maximumFilenameLength restrictions by dropping vowels and truncating,if necessary. This method assumes that a maximumFilenameLength of 12 indicatesthat file names should consist of eight characters, optionally followed by a periodand a three character extension. The formatFilename: method does not detect orsuppress characters that are not valid.

File names should be composed of the POSIX.1 portable file name characters,which are listed in “Portable file names” on page 54.

Note: If volume information cannot be obtained due to an OS error, caseSensitive,preservesCase and maximumFilenameLength will be set to conservative values(true, false, and 12 respectively) and formatFilename: will operate on thesevalues. This behavior is provided for cases where the volume informationcannot be obtained due to an OS error, such as when no disk is present indrive.

The following example forces a file name to conform to the file name length andcase of the volume specified by path. For further information on thesystemErrorDialog: method, see “Suppressing system error dialogs” on page 73."Modify the file name for the file about to be saved to path,ignoring all errors, including drive not ready."| filename path state volumeInfo newFilename |

filename := 'aVeryLongFilenameWhichWontFitOnSomeSystems.Text'.path := 'a:\workdir'.

"Obtain volume information"(volumeInfo := CfsVolumeInfo new) volumeInfo: path."Force the filename to fit"newFilename := volumeInfo formatFilename: filename."Answer the full path"|path last = CfsDirectoryDescriptor pathSeparator

ifTrue: [ path, newFilename]ifFalse: [ path, CfsDirectoryDescriptor pathSeparatorString, newFilename]

Searching directoriesThe CfsDirectoryDescriptor class provides common protocols for reading thecontents of file system directories. It also supports pattern matching by name andtype.

Opening a directory for searchingOpen a specific directory for searching by sending the opendir:pattern:mode: messageto the CfsDirectoryDescriptor class. This answers a CfsDirectoryDescriptor instancethat is similar to the CfsFileDescriptor instance used to access regular files.

The opendir:pattern:mode: message takes three arguments. The first argument is astring specifying the path of the directory to be searched.

The second argument is a pattern for matching entry names. The $* wildcardcharacter matches 0 or more characters, the $? wildcard character matches anysingle character. A pattern of ‘*’ always matches all files, regardless of platform.

The third argument specifies the type of files to match. It is a logical inclusive-ORof one or more of the following constants, which are defined in the CfsConstants

58 IBM Smalltalk: Programmer’s Reference

Page 73: IBM Smalltalk: Programmer's Reference

pool dictionary:

Table 8. Directory search modes

Pool variable Description

FREG If specified, matches regular files.

FDIR If specified, matches directories.

FSPECIAL If specified, matches files that are neither regular files nor directories.

The following are some examples of opening directory streams:| dd |"Get search handle for files of all types in the current working directory"(dd := CfsDirectoryDescriptor

opendir: '.'pattern: '*'mode: FREG | FDIR | FSPECIAL) isCfsError

ifTrue: [|self error: dd message].dd closedir.

| dd |"Get search handle for all regular files ending in '.bat'"(dd := CfsDirectoryDescriptor

opendir: 'c:\'pattern: '*.bat'mode: FREG) isCfsError

ifTrue: [|self error: dd message].dd closedir.

| dd |"Get search handle for all special files in the root of drive C:"(dd := CfsDirectoryDescriptor

opendir: 'c:\'pattern: '*'mode: FSPECIAL) isCfsError

ifTrue: [|self error: dd message].dd closedir.

Pattern matching uses platform-specific optimizations on platforms with directsupport for pattern-matched searches.

Reading directory entriesThere are three means of reading directory entries, each intended for a particularpurpose.

Using readdirSending the readdir message to a CfsDirectoryDescriptor instance causes the instanceto answer a new CfsDirectoryEntry instance representing the next directory entrymatching the specified pattern and type. A CfsDirectoryEntry instance understandsthe same messages as a CfsStat instance, plus the dName message, which answersthe name of the file represented by the directory entry as a string. See “Testingexistence and obtaining other file properties” on page 74 for a description of themessages understood by a CfsStat instance.

When there are no more directory entries to be read, the readdir message answersnil. An example of the use of readdir follows:"Answer a collection containing directory entries for all regular filesand directories in 'c:\'"| collection dd de |

collection := OrderedCollection new.

Chapter 5. Common File System 59

Page 74: IBM Smalltalk: Programmer's Reference

(dd := CfsDirectoryDescriptoropendir: 'c:\'pattern: '*' mode: FREG | FDIR) isCfsError

ifTrue: [|self error: dd message].

[(de := dd readdir) notNil]whileTrue: [collection add: de].

dd closedir.|collection.

Using readdir:The readdir: message is identical in behavior to readdir, except that instead ofcreating a new CfsDirectoryEntry instance, it stores the directory information in theCfsDirectoryEntry instance supplied as an argument. This technique provides betterperformance than creating and discarding a directory entry for each item in thedirectory. An example follows:"Print all regular files and directories in the current workingdirectory to the transcript"| dd de |

"Because directory entry data can be discarded after being printed,there is no point in creating a separate directory entry for each itemread. Instead reuse the same directory entry instance."de := CfsDirectoryEntry new.

(dd := CfsDirectoryDescriptoropendir: CfsDirectoryDescriptor getcwdpattern: '*'mode: FREG | FDIR) isCfsError

ifTrue: [|self error: dd message].

[(dd readdir: de) notNil]whileTrue: [Transcript cr; show: de printString].

dd closedir.

Using readdirNameSending the readdirName message to a CfsDirectoryDescriptor instance answers astring that is the name of the next directory entry matching the specified patternand type. If there are no more entries, it answers nil.

Tip: Do not use readdirName followed by CfsStat>>stat: to get file information,because this is never faster than using readdir or readdir:, and forces someplatforms to search the directory twice. Using readdir: is the most efficienttechnique if more than the file names are needed.

If only the file names are required, using readdirName is more efficient than othertechniques. Two examples are shown below."Print the names of all files in the current working directory to the

Transcript"| dd name |

(dd := CfsDirectoryDescriptoropendir: '.'pattern: '*'mode: FREG | FDIR | FSPECIAL) isCfsError

ifTrue: [|self error: dd message].

[(name := dd readdirName) isNil]whileFalse: [Transcript cr; show: name].

dd closedir.

"Count the number of files ending in '.new' in the subdirectory called'work' that is located under the current working directory andanswer the result"

| dd count |(dd := CfsDirectoryDescriptor

60 IBM Smalltalk: Programmer’s Reference

Page 75: IBM Smalltalk: Programmer's Reference

opendir: 'work'pattern: '*.new'mode: FREG | FDIR | FSPECIAL) isCfsError

ifTrue: [|self error: dd message].

count := 0.[dd readdirName isNil]

whileFalse: [count := count + 1].dd closedir.|count

Tip: For maximum efficiency when using readdirName, ensure that the modeargument is the inclusive-OR of FREG, FDIR and FSPECIAL. Specifying thatall file types are to be matched eliminates an operating system call todetermine the file type, which would otherwise be needed on some platforms.

Closing the directory descriptorAfter all the desired directory entries have been read, the directory descriptor mustbe closed by sending it the closedir message before it is discarded. This deallocatesany operating system resources associated with the directory descriptor.

Tip: Sending rewinddir to a CfsDirectoryDescriptor instance has the same effect asclosing and reopening the directory descriptor, but is more efficient on someplatforms. The search will resume from the first entry in the directory.

Using file streamsThe Common File System provides buffered I/O services by means of the BlueBook compliant stream protocols. File streams are the preferred method ofperforming file I/O operations within Smalltalk. A complete set of low-level I/Ooperations are also provided; see “Using low-level file operations” on page 64.

File stream classesThe Common File System stream classes consist of three concrete classes thatcorrespond to the three file access modes, and one abstract class.

CfsReadFileStreamThis file stream class provides input services only and corresponds to the POSIX.1ORDONLY access mode.

CfsWriteFileStreamThis file stream class provides output services only and corresponds to the POSIX.1OWRONLY access mode.

CfsReadWriteFileStreamThis file stream class provides both input and output services, and corresponds tothe POSIX.1 ORDWR access mode.

CfsFileStreamThis is an abstract class used to create streams on existing open file descriptors,and to enable you to specify POSIX.1 open modes and flags directly when creatinga new file stream. These operations are descripted in detail in “Mixing streams andfile descriptors” on page 67.

Opening and closing file streamsThe open: and openEmpty: messages are the simplest means of opening a new filestream instance on a particular file. Both messages are sent to the file stream class

Chapter 5. Common File System 61

Page 76: IBM Smalltalk: Programmer's Reference

representing the desired access mode. The open: message opens an existing file,while the openEmpty: message truncates an existing file (to size 0) or creates the fileif it does not exist. Accordingly, the CfsReadFileStream class does not respond to theopenEmpty: message.

Generally, open: is used when reading files and openEmpty: is used when writingnew files or overwriting existing files. Some examples follow.| file |"Opens an existing file for reading and writing, creates the file if it

does not exist."(file := CfsReadWriteFileStream open: 'existing.txt') isCfsError

ifTrue: [|self error: file message]."...Use the file stream for reading and/or writing..."file close.

| file |"Opens an existing file for reading only, fails if it does not exist"(file := CfsReadFileStream open: 'existing.txt') isCfsError

ifTrue: [|self error: file message]."...Use the file stream for reading..."file close. "When done, close the file stream, which closes the file."

| file |"Opens a new file for writing only, truncates it to size 0 if it already exists."(file := CfsWriteFileStream openEmpty: 'new.txt') isCfsError

ifTrue: [|self error: file message]."...Use the file stream for writing..."file close.

Once all desired operations have been performed, the file stream instance must beclosed by sending it the close message before it is discarded. This closes the file, bydeallocating any operating system resources associated with the file stream, andflushing any cached data to disk.

On double-byte platforms, the platform character encoding does not necessarilymatch the character encoding used within Smalltalk. As a result, Smalltalk stringsmust be converted to and from the platform representation as they are written toand read from files. When the Smalltalk and platform encodings differ, the streamanswered by the open: and openEmpty: messages will not be an instance of the classto which the message was sent. In such cases the open: and openEmpty: messagesanswer a specialized stream that conforms to the requested protocols and managesthe conversion of Smalltalk strings to the appropriate platform representation.

In these cases, it is important to use the isCfsError message to test the result of theopen: and openEmpty: operations rather than testing the class of the returned object(for example, returnedObject class == CfsReadFileStream).

Reading and writing file streamsFile streams have the same protocol as CLDT Streams. For the complete set ofmethods supported by the Stream class, see “Stream classes” on page 22. Thefollowing example uses a CfsReadFileStream to read data from an existing file, and aCfsWriteFileStream to write the data to a newly created file.| oldData newData |(oldData := CfsReadFileStream open: 'oldData.txt') isCfsError

ifTrue: [|self error: oldData message].(newData := CfsWriteFileStream openEmpty: 'newData.txt') isCfsError

ifTrue: [|self error: newData message].

newData nextPutAll: oldData contents.oldData close.newData close.

62 IBM Smalltalk: Programmer’s Reference

Page 77: IBM Smalltalk: Programmer's Reference

Note: The indexing methods for file streams answer and accept the byte positionin the file, not the character position. In contrast, the indexing operations ofCLDT Streams answer and accept character positions in the buffer beingstreamed over. When file streams are used with single-byte charactersexclusively, the character position and byte positions are the same. However,this is not the case when a mixture of single and double-byte characters areused.

When used with file streams, the copyFrom:to:, position, position:, size, andskip: messages operate based upon byte indexes and sizes, not character andsizes. The other file stream operations operate in the same manner as theCLDT Stream protocols. For portability, use the next and next: protocols forstream positioning.

Characters versus bytesAll file stream operations accept both character (Character, DBString, String) andbyte (Integer, ByteArray) arguments interchangeably as appropriate for the platform.For example, nextPut: accepts either a character or an integer between 0 and 255 onplatforms that use single-byte characters, and a character or an integer between 0to 65535 on platforms that use double-byte characters. The nextPutAll: messageaccepts an instance of String, DBString, or ByteArray as appropriate for theplatform.

Additionally, you can change the type of objects answered by file streamoperations such as contents, ext, nextLine, upTo:, and upToAll: by using the isBytes:and isCharacters: messages to specify the type of data that is being streamed over,as shown in the following example:"Open a text file for reading"| file contents |file := CfsReadFileStream open: 'readme.txt'.file isCharacters: true."We are streaming over characters, answer file contents as characters"contents := file contents.file close.|contents"Open a bitmap image file for reading"| file contents |file := CfsReadFileStream open: 'looknice.bmp'.file isBytes: true."We are streaming over bytes, answer file contents as bytes"contents := file contents.file close.|contents

The data type being used by a stream can be determined using the Booleanmessages isBytes and isCharacters. These messages are opposites; exactly onereturns true at any given time.

Tip: Care must be taken when using Stream methods position, position:, size, andcopyFrom:to: with CfsFileStreams on a double-byte locale, because these areanswered in bytes and not in characters.

Line delimitersBy default, a stream uses the platform file system’s line delimiter for operationssuch as cr and nextLine. A string representing the current line delimiter can beobtained by sending the lineDelimiter message to a file stream instance, and can bechanged to an arbitrary string by sending the lineDelimiter: message. This makes it

Chapter 5. Common File System 63

Page 78: IBM Smalltalk: Programmer's Reference

possible to adopt a single platform’s file convention as the standard for allplatforms, or to use nextLine to read files written on other platforms. The followingtable lists the line delimiter constants defined in the CldtConstants pool dictionary:

Table 9. Line Delimiter constants in the CldtConstants pool dictionary

Pool variable Description

LineDelimiter The default platform line delimiter

PMLineDelimiter The line delimiter used by OS/2 Presentation Manager

UNIXLineDelimiter The line delimiter used by AIX and OS/390®

WINLineDelimiter The line delimiter used by MS-DOS/Windows

The following example demonstrates the use of the lineDelimiter: message and linedelimiter constants, as well as their effect on the cr message:| file |file := CfsReadWriteFileStream openEmpty: 'testing.txt'.

"Use OS/2 line delimiter"file lineDelimiter: PMLineDelimiter.file cr; nextPutAll: '<-os/2 line delimiter'.

"Set back to default line delimiter"file lineDelimiter: LineDelimiter.file cr; nextPutAll: '<-default line delimiter'.

"Use an arbitrary line delimiter"file lineDelimiter: '[end of line]'.file cr; nextPutAll: '<-arbitrary line delimiter'.file close.

Tip: Use upToAll: and skipToAll: to scan up to various special character sequences.This is better than changing the line delimiter to the special sequence withlineDelimiter: and then using nextLine.

Using low-level file operationsThe CfsFileDescriptor class provides a common protocol for low-level fileoperations. These protocols are Smalltalk equivalents of the POSIX.1 file descriptorfunctions.

Opening filesA file is opened by sending the open:oflag: message to the CfsFileDescriptor class,which answers a new CfsFileDescriptor instance to act as the receiver for I/Ooperations to that file. The first argument is a String or DBString specifying thepath of the file to be opened; the second is an integer specifying the inclusive-ORof exactly one access mode and zero or more open flags. Access modes and flagsare defined in the CfsConstants pool dictionary.

The following table describes open access modes and flags.

Table 10. Open access modes and flags (OR together)

Open access modes (specify only one)

ORDONLY Open for reading only

OWRONLY Open for writing only

ORDWR Open for reading and writing

Open flags (specify zero or more)

64 IBM Smalltalk: Programmer’s Reference

|

Page 79: IBM Smalltalk: Programmer's Reference

Table 10. Open access modes and flags (OR together) (continued)

OAPPEND Causes the file offset to be set to the end of the file prior to EACHwrite

OCREAT Causes the file to be created if it does not exist. Has no effect if the fileexists, except as noted under OEXCL.

OEXCL If OCREAT and OEXCL are both specified, fails if the file exists.

OTRUNC If the file exists and is a regular file, and the file is successfully openedORDWR or OWRONLY, causes the file to be truncated to zero lengthwith other platform attributes unchanged.

Some examples of the use of access modes and open flags follow:| fd |"Opens an existing file for reading, fails if it does not exist"(fd := CfsFileDescriptor

open: 'exists.txt'oflag: ORDONLY) isCfsError

ifTrue: [|self error: fd message].fd close.

| fd |"Opens a new file for writing, fails if it exists"(fd := CfsFileDescriptor

open: 'new.txt'oflag: OWRONLY | OCREAT | OEXCL) isCfsError

ifTrue: [|self error: fd message].fd close.

| fd |"Opens an existing file for reading and writing,

or creates it if it does not exist"(fd := CfsFileDescriptor

open: 'log.txt'oflag: ORDWR | OCREAT) isCfsError

ifTrue: [|self error: fd message].fd close.

| fd |"Ensures that the opened file is empty: creates if it does not exist,

truncate to size 0 if it does."(fd := CfsFileDescriptor

open: 'empty.txt'oflag: ORDWR | OCREAT | OTRUNC) isCfsError

ifTrue: [|self error: fd message].fd close.

Closing file descriptorsOnce all desired operations have been performed on a file descriptor, it must beclosed before being discarded. This is accomplished by sending the file descriptorthe close message, which deallocates all operating system resources associated withit.| fd |(fd := CfsFileDescriptor

open: 'example.txt'oflag: ORDWR | OCREAT | OTRUNC) isCfsError

ifTrue: [|self error: fd message].

"... Put file operations here ..."fd close."Close file when done"

Chapter 5. Common File System 65

Page 80: IBM Smalltalk: Programmer's Reference

Reading and writing dataData can be transferred between a file and a buffer by sending theread:startingAt:nbyte: and write:startingAt:nbyte: messages to the CfsFileDescriptorinstance returned by the open:oflag: message. The first argument specifies the buffer,which can be either a String or ByteArray instance. The second argument specifiesthe position in the buffer to or from which data is to be transferred. The thirdargument specifies the number of bytes to be transferred. The messages answer thenumber of bytes that were successfully read or written.

Note: The startingAt parameter refers to the position in the buffer, not in the file.To change the position in the file (the file offset) use the lseek:whence: message.

"Example of read/write: low level file copy using buffers"| source target buf bytesRead bufSize |

(source := CfsFileDescriptoropen: 'example.txt'oflag: ORDONLY) isCfsError

ifTrue: [|self error: source message].

(target := CfsFileDescriptoropen: 'example.bak'oflag: OWRONLY | OCREAT | OTRUNC) isCfsError

ifTrue: [|self error: target message].

"Choose a reasonable size"bufSize := 4096."Could also use a ByteArray"buf := String new: bufSize.[(bytesRead := source read: buf startingAt: 1 nbyte: bufSize) > 0]

whileTrue: [bytesRead > (target write: buf startingAt: 1 nbyte: bytesRead)

ifTrue: ["Fewer bytes written than requested - might indicate full

file system"source close.target close.

|self error: 'Unable to copy file. File system could be full.']].

source close.target close.

Tip: There is no need to implement a low-level file copy function. CfsFileDescriptorCfsFileDescriptorclass>>#copy:new: portably provides this functionality usingthe most efficient means for each platform.

Changing the file offsetThe lseek:whence: message is used to query and set the file offset. This is theposition in the file used by read:startingAt:nbyte: and write:startingAt:nbyte: whentransferring data. A successful read or write operation automatically sets the fileoffset to point after the last byte read or written.

The lseek:whence: message is sent to an open CfsFileDescriptor instance. The firstargument, offset, is an integer offset into the file. The second argument, whence, isone of the constants shown in the following table, which are defined in theCfsConstants pool dictionary. The lseek:whence: message answers an integerrepresenting the new file offset.

66 IBM Smalltalk: Programmer’s Reference

Page 81: IBM Smalltalk: Programmer's Reference

Table 11. Whence constants for the lseek:whence: message

Pool variable Description

SEEKSET The file offset is set to the position specified by the first argument. Anoffset of 0 sets the file offset to the beginning of the file.

SEEKCUR The file offset is set to its current position plus the number of bytesspecified by the first argument.

SEEKEND The file offset is set to the file size plus the number of bytes specifiedby the first argument.

Some examples of the use of lseek:whence: follow:| fd current |

"Open an existing file for reading, fail if it does not exist"(fd := CfsFileDescriptor

open: 'exists.txt'oflag: ORDONLY) isCfsError

ifTrue: [|self error: fd message].

"Get the current file pointer position"current := fd lseek: 0 whence: SEEKCUR.Transcript cr; show: 'Current position: ', current printString.

"Seek to 5 bytes before the end of the file"fd lseek: -5 whence: SEEKEND.

"Seek to the beginning of the file"fd lseek: 0 whence: SEEKSET.

"Seek after 10th byte of file, next read or writewill start with 11th byte"

fd lseek: 10 whence: SEEKSET.

"Rewind file pointer by 20 bytes"fd lseek: -20 whence: SEEKCUR.fd close.

Other low-level operationsThe following list describes what happens when the specified method’s message issent to an open CfsFileDescriptor instance:

rewind Rewinds the file pointer to the beginning of the file.

size Answers the size of the file in bytes without affecting the position of thefile pointer.

flush Forces all changes to the file to be written to disk.

Mixing streams and file descriptorsIn some applications, it might be necessary to mix the convenience of streams withthe low-level capabilities of file descriptors.

Using access modes and flags with file streamsIt is possible to open a file stream on an existing file descriptor by sending the on:message to the CfsFileStream class. The on: message answers an instance of theconcrete stream class corresponding to the access mode of the file descriptor. Anexample of converting a file descriptor into a file stream is shown below:

Chapter 5. Common File System 67

Page 82: IBM Smalltalk: Programmer's Reference

| fd file |fd := CfsFileDescriptor

open: 'new.fil'oflag: ORDWR | OCREAT | OEXCL.

fd isCfsErrorifTrue: [|self error: fd printString].

file := CfsFileStream on: fd."Close the file stream - this will automatically close the file

descriptor as well"file close.

The on: message is also useful if the file is to be opened with a special share mode,using the open:oflag:share: message, which was discussed in “File locking” on page68. An example follows:| file fd |(fd := CfsFileDescriptor

open: 'a.fil'oflag: ORDWRshare: ODENYRDWR) isCfsError

ifTrue: [|self error: fd message].file := CfsFileStream on: fd.file close.

Performing low-level file operations on streamsBecause the file streams in IBM Smalltalk are implemented using theCfsFileDescriptor class, it is possible to obtain the CfsFileDescriptor instance that afile stream is streaming over. To do this, send the fileDescriptor message to the filestream instance. The CfsFileDescriptor instance that is answered can then be usedfor low-level file descriptor operations. An example of cooperation betweenstreams and file descriptors is shown below:"An example of combining file descriptor locking with file streams"| fileStream |

(fileStream := CfsReadWriteFileStream openEmpty: 'lockable.fil') isCfsErrorifTrue: [|self error: fileStream message].

fileStream nextPutAll: 'This is a LOCKED area'.

"Lock the word LOCKED"fileStream fileDescriptor lock: FMDLOCK start: 10 len: 6.

"Unlock it"fileStream fileDescriptor unlock: FMDLOCK start: 10 len: 6.

"Close the file stream"fileStream close.

File locking and share modesThe Common File System provides common protocols for file locking and sharemodes. However, file locking and share modes are not uniformly supported by allplatform file systems.

File lockingThere are two general locking schemes, advisory locking and mandatory locking.Advisory locks have no effect on clients that do not explicitly check for a lock.Mandatory locks do not require clients to explicitly check for locks, but represent asecurity risk because it is possible to interfere with the normal operation of asystem by placing mandatory locks on essential files. For this reason mandatory

68 IBM Smalltalk: Programmer’s Reference

Page 83: IBM Smalltalk: Programmer's Reference

locks are excluded from the POSIX.1 standard. A platform file system usuallysupports either advisory or mandatory locking but not both.

The locking constants in the CfsConstants pool dictionary appear in the followingtable:

Table 12. File locking constants

Pool variable Description

FRDLOCK Specifies a shared (read) advisory lock. A shared advisory lock preventsany other client from setting an exclusive advisory lock on any portionof the protected area. Noncooperating clients can read or write inprotected areas.

FWRLOCK Specifies an exclusive (write) advisory lock. An exclusive advisory lockprevents any other client from setting a shared or exclusive advisorylock on any portion of the protected area. Noncooperating clients canread or write in protected areas.

FMDLOCK Specifies an exclusive mandatory lock. An exclusive mandatory lockprevents any other client from reading, writing, or locking any portionof the protected area.

Determining supported lock typesIn general, a platform operating system supports either advisory locking ormandatory locking, but not both. To determine whether a lock type is supported,send the supportsLockType: message to the CfsFileDescriptor class, with the desiredlocking constant as an argument. If the specified type of lock is supported, true isanswered. Otherwise, false is answered. An example follows:"Need exclusive lock, preferably mandatory. Answer what is available"(CfsFileDescriptor supportsLockType: FMDLOCK)

ifTrue: [|FMDLOCK]ifFalse: [

(CfsFileDescriptor supportsLockType: FWRLOCK)ifTrue: [|FWRLOCK]ifFalse: [|self error: 'No exclusive lock types are supported']].

Tip: Locking might have no effect unless the file is being accessed by what theoperating system considers to be distinct processes. With some networksoftware, locking can only be effective if the file is being accessed fromdifferent machines. These are limitations in the services provided by theoperating system or network.

Locking and unlocking regionsSending the lock:start:len: message to a CfsFileDescriptor instance sets a segment lockon the file associated with the CfsFileDescriptor instance. The first argument is oneof the file locking constants described in the table in the preceding section. Thesecond argument is an integer specifying the zero-based offset of the first byte tobe locked. The third argument is an integer specifying the number of bytes to belocked. If the specified locking constant is not supported, a CfsError instance isanswered. To release a lock, use the unlock:start:len: message. The arguments areidentical. Examples are as follows:| fd theSize |(fd := CfsFileDescriptor

open: 'lockable.fil'oflag: ORDWR | OCREAT | OTRUNC) isCfsError

ifTrue: [|self error: fd message].fd write: 'This is a TEST LOCK area' startingAt: 1 nbyte: 24.

Chapter 5. Common File System 69

Page 84: IBM Smalltalk: Programmer's Reference

"Lock the word test with a mandatory lock - should really determine appropriatelock type first as shown in previous section on determining lock type"fd lock: FMDLOCK start: 10 len: 4.

"Release the lock, must use same lock constant"fd unlock: FMDLOCK start: 10 len: 4

"Lock the entire file and then unlock it""The size is saved so that the region is locked as was unlocked, evenif the file size increased between the operations."fd lock: FMDLOCK start: 0 len: (theSize :=fd size).fd unlock: FMDLOCK start: 0 len: theSize.fd close.

When releasing a lock, the value of the lock type, start, and length arguments mustbe exactly the same as those used to set the lock. Otherwise the unlock operationcan fail or have unpredictable behavior. Using the size message when releasing alock as shown in the previous example is dangerous, because the size might havechanged since the lock was set. Instead, save the parameters used when lockingand reuse these values when releasing the lock. An example follows:| fd len |(fd := CfsFileDescriptor

open: 'lockable.fil'oflag: ORDWR | OCREAT | OTRUNC) isCfsError

ifTrue: [|self error: fd message].fd write: 'This is a TEST LOCK area' startingAt: 1 nbyte: 24.

fd lock: FMDLOCK start: 0 len: (len := fd size).fd unlock: FMDLOCK start: 0 len: len.fd close.

The effect of locking overlapping regions or releasing locks that have not been setis platform-specific. It is recommended that all locks be explicitly released beforeclosing the file.

Share modesThe Common File System supports four share modes for opening files. Theconstants used to specify these modes appear in the following table. Theseconstants are defined in the CfsConstants pool dictionary.

Table 13. Share mode constants

Pool variable Description

ODENYNONE Other processes can open the file for any access: read-only, write-only,or read-write.

ODENYRD Other processes can open the file for write-only access, but they cannotopen it for read-only or read-write access.

ODENYWR Other processes can open the file for read-only access, but they cannotopen it for write-only or read-write access.

ODENYRDWR The current process has exclusive access to the file. Other processescannot open the file. It is unspecified whether the file can be opened bythe current process.

Selecting valid share modesLike file locking types, share modes are not uniformly supported by all platforms.Some platforms can have default share modes that are associated with accessmodes, and cannot be changed. For example, opening a file with ORDONLY accessmight have the same effect as specifying the ODENYWR share mode, and opening

70 IBM Smalltalk: Programmer’s Reference

Page 85: IBM Smalltalk: Programmer's Reference

a file with OWRONLY access might have the same effect as specifyingODENYRDWR. On platforms that do not support specifiable share modes, sharemodes are ignored.

To determine whether a particular share mode is supported, send thesupportsShareMode: message to the CfsFileDescriptor class, with the desired sharemode constant as an argument. If the specified share mode is supported, true isanswered. Otherwise, false is answered. The following code fragment determines ifthe ODENYRDWR share mode is supported:"Is ODENYRDWR supported?"|CfsFileDescriptor supportsShareMode: ODENYRDWR.

Tip: Like locking, share modes might have no effect unless the file is beingaccessed by what the operating system considers to be a distinct process. Withsome network software, it can only be effective if the file is being accessedfrom a different machine.

Opening files using share modesTo open a file descriptor with a specific share mode, send the open:oflag:share:message to the CfsFileDescriptor class instead of sending open:oflag:. The thirdargument specifies the share mode to use. If share modes are not supported, it hasno effect. Here are some examples:"Open a file read/write with exclusive access"| fd |fd := CfsFileDescriptor

open: 'exclusiv.fil'oflag: ORDWR | OCREATshare: ODENYRDWR.

fd isCfsErrorifTrue: [|self error: fd printString].

fd close.

"Open a file denying write access to others"| fd |fd := CfsFileDescriptor

open: 'readonly.str'oflag: ORDONLYshare: ODENYWR.

fd isCfsErrorifTrue: [|self error: fd printString].

fd close.

Handling errorsThe CfsError class provides a common mechanism for obtaining error informationpertaining to file system operations. If an error prevents the successful completionof a Common File System operation, the affected method will answer an instanceof CfsError, rather than its normal return value. The CfsError instance containsinformation pertaining to the cause of the error.

Errors are detected by sending the isCfsError message to the result returned by anylow-level file system operation, CfsStat operation, or file stream class method suchas open: or openEmpty:. Instances of CfsError are the only objects that answer true tothis message, all other objects answer false.

File stream instance methods in Common File System handle errors in the samemanner as the Stream class in CLDT. If errors are expected when streaming over afile, set up an exception handler as described in the section on “Handling ofexceptions” on page 26.

Chapter 5. Common File System 71

Page 86: IBM Smalltalk: Programmer's Reference

Two examples of handling errors follow. The CwMessagePrompter class is describedin “Message prompter” on page 198."Attempt to open a file stream on a file, fail if the file does not exist"| fileName file text |file := CfsReadFileStream open: (fileName := 'notthere.txt').file isCfsError"Test the file descriptor 'open' result for a CfsError"

ifTrue: ["Open a dialog displaying the open error"|CwMessagePrompter new

buttonType: XmOK;iconType: XmICONERROR;messageString: ('Unable to open file: %1.%2 Error: %3'

bindWith: fileNamewith: LineDelimiterwith: file printString);

prompt].

"If the file does exist, answer the file's contents. Instances ofCfsError are not answered by the file stream instance methodscontents or close"text := file contents.file close.|text"Attempt to open a file descriptor for a file, fail if the file does not exist"| fd fileName strings stringBuf result |fd := CfsFileDescriptor

open: (fileName := 'strings.dat')oflag: ORDONLY.

fd isCfsError

"Test the file descriptor 'open' result for a CfsError"ifTrue: [

"Open a dialog displaying the error"|CwMessagePrompter new

buttonType: XmOK;iconType: XmICONERROR;messageString: ('Unable to open file: %1.%2 Error: %3'

bindWith: fileNamewith: LineDelimiterwith: fd printString);

prompt].

"If the file exists, read 1000 24-byte strings into an array of strings,and answer the array. If a file error occurs at any time while reading,answer the CfsError."strings := Array new: 1000.1 to: strings size do: [:i |

stringBuf := String new: 24.result := fd

read: stringBufstartingAt: 1nbyte: stringBuf size.

result isCfsError

"Test the file descriptor 'read' result for a CfsError"ifTrue: [

fd close.|result].

strings at: i put: stringBuf.].fd close.|strings

The information contained in a CfsError instance is accessed by way of thefollowing methods:

errno Answers the integer error number for comparison against the errorconstants in the CfsConstants pool dictionary.

72 IBM Smalltalk: Programmer’s Reference

Page 87: IBM Smalltalk: Programmer's Reference

identifierAnswers a string that is the abbreviated error name. This is the same asthe string representing the key in the CfsConstants pool dictionaryassociated with the receiver’s errno value.

messageAnswers a short text description of the error.

Printing a CfsError instance using the printString or printOn: message will displayall of the information described above.

The specific errors that can be returned by a method are listed in the methodcomment. No other errors are returned. Following is an example of testing for aspecific error that prompts to overwrite existing file:"Open a new file, prompt for overwrite if it exists"| fd |

"Open the file, OEXCL causes failure if it exists"fd := CfsFileDescriptor

open: 'new.fil'oflag: ORDWR | OCREAT | OEXCL.

fd isCfsErrorifTrue: ["NOTE: Because an error occurred, fd is not a file descriptor,

it is a CfsError instance."fd errno = EEXIST

ifTrue: ["The file already exists"(CwMessagePrompter new

buttonType: XmYESNO;iconType: XmICONWARNING;messageString: 'File exists. Overwrite?';prompt)

ifTrue: ["Overwrite the file obtaining a file descriptor"fd := CfsFileDescriptor

open: 'new.fil'oflag: ORDWR | OTRUNC.

fd isCfsErrorifTrue: [|self error: fd printString]]

ifFalse: [|self]]ifFalse: [

"It's some other error - walkback"|self error: fd printString]].

"Here, fd is guaranteed to be a file descriptor,do something with the fd, and then close it"fd close.

When testing for a specific error, compare the CfsError instance’s errno against theerror constants in the CfsConstants pool dictionary. All application code anddocumentation should refer to errors by identifier, for example, ENOENT, ratherthan by number, because error constant values can vary from platform to platform.

Suppressing system error dialogsOn some platforms, certain file system errors, such as “drive not ready” and “diskchange required,” causes a system error dialog to appear. You can suppress thisdialog by sending systemErrorDialog: to CfsError class. An example is as follows:"Get volume info for drive A, ignoring drive not ready."| state volumeInfo |

Chapter 5. Common File System 73

Page 88: IBM Smalltalk: Programmer's Reference

"Turn off system error dialog."state := CfsError systemErrorDialog: false.

"Get volume info for drive A:"volumeInfo := CfsVolumeInfo volumeInfo: 'A:\'."Reset system error dialog to original state"CfsError systemErrorDialog: state.|volumeInfo

Tip: On platforms that do not support dialog suppression, systemErrorDialog: hasno effect.

Testing existence and obtaining other file propertiesThe CfsStat class provides common protocols for obtaining information about aparticular file from its directory entry. This includes size, type, and modificationdate and time.

Obtaining a CfsStat instanceSending the stat: message to the CfsStat class returns a CfsStat instance containingthe statistics for the file specified as its argument. These statistics can be accessedby sending messages, that match POSIX.1 stat structure names, to the instance. Anexample follows:"Answer the file size"|(CfsStat stat: 'bigfile.txt') stSize

Tip: To obtain the exact size of a file, send size to an open file descriptor ratherthan using stat:, because CfsFileDescriptor>>#size reflects the true size of thefile based on the end-of-file position as of last write, while CfsStat>>#sizeobtains the amount of storage space allocated to the file by reading the file’sdirectory entry. For this reason, the size obtained by sending size to a CfsStateor CfsDirectoryEntry might not match the logical size of the file, and might notbe up-to-date if the file is currently open, even if a flush was just performedon the file descriptor.

The following messages can be sent to a CfsStat instance. The messages alwaysanswer a meaningful value, because all platforms support the informationassociated with them.

isBlk Answers true if the receiver is reporting statistics for a block special file.Otherwise answers false.

isChr Answers true if the receiver is reporting statistics for a character specialfile. Otherwise answers false.

isDir Answers true if the receiver is reporting statistics for a directory. Otherwiseanswers false.

isFifo Answers true if the receiver is reporting statistics for a pipe or for a FIFOspecial file. Otherwise answers false.

isReg Answers true if the receiver is reporting statistics for a regular file.Otherwise answers false.

isSpecialAnswers true if the receiver is reporting statistics for a special file.Otherwise answers false. A special file is any file that is neither a regularfile nor a directory.

stat: Obtains statistics for the specified file and stores them in the receiver.

74 IBM Smalltalk: Programmer’s Reference

Page 89: IBM Smalltalk: Programmer's Reference

stMode Answers the platform-specific file mode, which indicates the type of fileand other attributes.

stMtimeAnswers an array containing the date and time that the file was lastmodified.

stSize Answers an integer that is the size in bytes of the regular file. If thereceiver is not reporting statistics for a regular file, the value is unspecified.

The following messages in provide access to additional information that is notsupported uniformly by all platforms. These messages can answer nil if aparticular platform does not support the associated type of information.

stAtimeAnswers an array containing the date and time that the file was lastaccessed.

stCTimeAnswers an array containing the date and time that the file’s status waslast changed.

stDev Answers the device ID of the device containing the file.

stFtimeAnswers an array containing the creation date and time.

stGid Answers the group ID for the file.

stIno Answers the serial number of the file.

stNlinkAnswers the number of links for the file.

stUid Answers the user ID for the file.

If repeated stat operations are to be performed, garbage creation can be minimizedby creating an empty CfsStat instance and then reusing it by sending the stat:message to the instance. An example follows:| statBuf |"Create CfsStat instance for buffer"statBuf := CfsStat new."Answer the sum of the sizes of three files"|(statBuf stat: 'one.fil') stSize + (statBuf stat: 'two.fil')

stSize + (statBuf stat: 'three.fil') stSize

By combining the stat: message with error checking, it is possible to test for fileexistence and other special properties. Some examples follow."Check file existence: Answer true if path specifies an existing file of any type"|(CfsStat stat: path) isCfsError not

"Check if a path name is already being used""Answer true if path specifies an existing file of any type""Customized to consider inaccessible entries to be existing files"| result |result := CfsStat stat: path.result isCfsError

ifTrue: [result errno = EACCES ifTrue: [|true].|false]

ifFalse: [|true].

Chapter 5. Common File System 75

Page 90: IBM Smalltalk: Programmer's Reference

"Answer true if path specifies an existing directory"| result |result := CfsStat stat: 'aDir'.result isCfsError

ifTrue: [|false]ifFalse: [|result isDir].

Tip: Do not use stat: to try to prevent errors by testing whether a file exists beforeopening it. It is better to catch the fail case from the open operation, becausethe file can be deleted in the time between the existence test and opening thefile.

Mixing platform-specific and Common File System operationsIt can sometimes be necessary or desirable to use platform-specific calls for somefile system operations, despite the fact that this will result in nonportable code.Services are provided to permit cooperation between Common File System andplatform-specific calls, thereby minimizing the portability costs associated withplatform-specific calls.

Tip: Mixing Common File System and platform-specific operations should only bedone as a last resort when no satisfactory solution exists using portableCommon File System operations. Use these facilities with extreme caution.

These operations should only be used by experts, because there are hidden pitfalls.Some platforms can have multiple valid file descriptor representations, thus somecalls might not be compatible with the particular representation chosen by theCfsFileDescriptor. Furthermore, on such platforms, the possibility exists that theunderlying representation might change.

Performing a platform-specific call with a CfsFileDescriptorTo perform a platform-specific call with an existing open CfsFileDescriptor instance,send the message fileDescriptor to the instance. This will answer theplatform-specific file descriptor used as the underlying representation of theCfsFileDescriptor, which can then be passed as an argument to the platform-specificcall.

Converting a platform file descriptor into a CfsFileDescriptorTo convert a platform-specific file descriptor into a CfsFileDescriptor instance, usethe on: message as follows:CfsFileDescriptor on: aPlatformFileDescriptor

This answers an initialized CfsFileDescriptor instance whose platform-specific filedescriptor is aPlatformFileDescriptor.

Some platforms can have more than one type of file handle. Ensure that theplatform-specific file descriptor specified as the argument to on: is of the same typeas that used by the Common File System itself.

Obtaining platform-specific error informationPlatform-specific error information can be obtained from a CfsError instance bymeans of the following messages. These messages return nil if not supported by aparticular platform or in the case of a synthetic error that is simulated forcompatibility rather than being generated by the platform operating system itself.

platformErrnoAn integer representing the native platform error code, if any

76 IBM Smalltalk: Programmer’s Reference

Page 91: IBM Smalltalk: Programmer's Reference

platformErrorCategoryAn integer representing the native platform error category, if any

platformErrorLocationAn integer representing the native platform error location, if any

platformRecommendedActionAn integer representing the recommended action, if any, suggested by theplatform operating system

Platform-specific error information is useful for debugging, and appears as fourintegers, separated by commas, between square brackets when a CfsError printsitself. If necessary, these methods can be used to trigger special platform-specificactions. However, this will of course result in nonportable code.

Chapter 5. Common File System 77

Page 92: IBM Smalltalk: Programmer's Reference

78 IBM Smalltalk: Programmer’s Reference

Page 93: IBM Smalltalk: Programmer's Reference

Chapter 6. Common Graphics

The Common Graphics (CG) subsystem can be divided into two sets of classes:v The core Common Graphics classesv Classes comprising Common Graphics Image Support

This document first describes the core Common Graphics classes and laterdescribes the Image Support classes.

The core Common Graphics classes and methods enable programmers to do thefollowing:v Define drawing attributes, such as line widths or styles, through the use of

graphics contextsv Perform drawing operations, such as drawing lines, arcs, text strings, and

polygonsv Manipulate fontsv Manipulate two-color bitmaps and multicolor pixmaps

Common Graphics Image Support also enables programmers to do the following:v Specify a palette of colors to use in drawing operationsv Create, manipulate, and draw bitmap images in a platform-independent and

device-independent formatv Create and draw iconsv Load and unload images and icons using standard file formats

This chapter describes how the core system is based on the X Window System’sgraphics library, shows the class hierarchy, and explains the basic process forbuilding an application. It summarizes resource management, describing when andhow to free graphics resources that have been allocated.

Classes in the Common Graphics hierarchy are prefixed by the letters ‘Cg;’ forexample, CgRGBColor or CgFont.

X Window system graphics library compatibilityThe core Common Graphics subsystem is based on the X Window system’s libraryof graphics operations (Xlib) and provides the same functions as the Xlib C calls.The Common Graphics Image Support classes are not based on Xlib.

This section will be of interest to developers familiar with Xlib graphic operations,as it describes the two main strategies that were used to convert the standard XlibC calls to Smalltalk classes and methods. By understanding these two principles,experienced Xlib software engineers should be able to use the Common Graphicssubsystem relatively quickly.

First, objects have been created for all C data types. These data types include itemssuch as Display, Drawable, GC, and Font. These objects were named by prefixingthe Xlib data type name with Cg and removing any leading X. For example, theXlib type Display becomes the Smalltalk class CgDisplay.

© Copyright IBM Corp. 1994, 2000 79

Page 94: IBM Smalltalk: Programmer's Reference

Second, each Xlib C function has been converted to a corresponding Smalltalkmethod. To understand this conversion, consider the following standard Xlibfunction XDrawRectangle:XDrawRectangle(display, drawable, gc, x, y, width, height);

In the Common Graphics subsystem, this function has been converted to thefollowing method:CgDrawable>>#drawRectangle: gc x: x y: y width: width height: height.

In translating C Xlib functions to Smalltalk, two rules have been applied:v If the first parameter of the C function is a display and the second parameter is

a graphics resource, such as a drawable or a graphics context, the secondparameter indicates the receiver of the equivalent Smalltalk message. Graphicsresources such as a CgDrawable know the display on which they are located, soit is not necessary to specify the display in the Smalltalk equivalent. If thesecond parameter is not a graphics resource, the first parameter is used toindicate the receiver.

v The Smalltalk message selector is formed using the C function name, with thepreceding ‘X’ removed, and the remaining parameter names.

Core Common Graphics class hierarchyThe core Common Graphics subsystem contains several classes. The mostfrequently used classes are presented first. Frequently used classes are covered indifferent subsections of this chapter, and are listed in Table 14.

Table 14. Frequently used classes

Class Represents Default object, if it exists See subsection

CgCursor* A cursor Varies by platform “Using cursors” on page 103

CgDisplay A connection to thegraphics server

CgDisplay default “Core Common Graphics classhierarchy” on page 80

CgDrawable* A place to draw(either a window or apixmap)

CgScreen default rootWindow orCgWindow default

“Core Common Graphics classhierarchy” on page 80

CgFont* A font resource CgDisplay default defaultFont orCgFont default

“Using fonts” on page 93

CgFontStruct A font structure CgDisplay defaultdefaultFontStruct orCgFontStruct default

“Using fonts” on page 93

CgGC (graphicscontext)

A table of graphicdisplay attributessuch as line width,line style

CgScreen default defaultGC orCgGC default

“Using graphics contexts” onpage 84

CgGCValues A data structure usedfor configuring aCgGC

Table 16 on page 86 “Using graphics contexts” onpage 84

CgPixmap* An off-screenrectangular array ofpixels (monochromeor color)

None “Using pixmaps” on page 106

CgWindow* A window CgScreen default rootWindow orCgWindow default

“Core Common Graphics classhierarchy” on page 80

80 IBM Smalltalk: Programmer’s Reference

Page 95: IBM Smalltalk: Programmer's Reference

Table 14. Frequently used classes (continued)

Class Represents Default object, if it exists See subsection

CgScreen A physical screendevice

CgScreen default “Core Common Graphics classhierarchy” on page 80

CgTextItem A text data structure None “Using fonts” on page 93

Note: *Denotes a class that is a subclass of the abstract class CgId.

The following figure illustrates the most frequently used core Common Graphicsclasses.

CgScreen represents the physical display device.

CgDisplay represents the link between your applicationand the graphics server.

CgWindow represents an individual window. CgWindowis the link to Common Widgets (see Tip below).

the graphics server, which can be drawn on and copiedCgPixmap represents off-screen memory, located at

to and from other windows or pixmaps.

CgGC represents the drawing attributes used indrawing operations, including line width, line style,fill pattern, and clipping region.

A CgDisplay object represents a connection to a graphics server: the link betweenyour application and the server. Your application can control several displayobjects, each one representing a link between your application and a differentgraphics server. You can obtain the default instance using CgDisplay default.

A CgScreen object represents a single hardware output device. It containsinformation about the device including its dimensions, its color capabilities and itsdefault graphics context. You can obtain the default screen of the default displayusing CgDisplay default defaultScreen or CgScreen default.

A CgDrawable object represents an area that can be drawn upon—either an instanceof CgWindow or CgPixmap. All drawing operations are performed on a drawable.Conceptually, drawables are located in the graphics server. Drawing commands aresent from the application to the graphics server, which then performs the requiredoperations on the drawable. Drawing operations are performed with respect to theorigin (the point defined by 0@0), which is in the upper left corner of thedrawable.

A CgWindow object represents an area of the screen, usually the visible area of auser interface widget. Widgets are created by the application using the CommonWidgets subsystem (see the “Common Widgets” chapter). Each widget has acorresponding window, which is obtained by sending the window message to thewidget. In addition to the windows of widgets, each screen has a root windowcovering the entire area of the screen. All other windows are layered on top of the

Chapter 6. Common Graphics 81

Page 96: IBM Smalltalk: Programmer's Reference

root window. You can obtain the root window of the default screen usingCgWindow default. In general, IBM Smalltalk applications use windows provided bythe Common Widgets subsystem. The root window is useful for testing purposesand is used throughout this chapter to show examples.

Note: It is important to note that CgWindow forms a link between the CommonGraphics and Common Widgets subsystems of IBM Smalltalk. A CwWidgetcannot be drawn on directly. However, every CwWidget has a correspondingCgWindow that can be used for drawing. That is, CgWindows are alsoCgDrawables. This is obtained by sending the window message to theCwWidget. For further information, see “Drawing area widgets” on page 164in the Common Widgets chapter.

A CgPixmap object represents an off-screen monochrome or color bitmapped imagecreated by your application. The format of pixmap memory is device dependentand is not directly accessible to the application. Pixmaps are used to specify stippleand tile pattern drawing attributes. They are also often used to cache the results ofdrawing for high speed display. A pixmap is displayed by copying a rectangulararea of its contents to a window. Your application is responsible for creating,manipulating, and freeing pixmap objects. These operations are described in“Using pixmaps” on page 106.

A CgGC object (also called a GC or Graphics Context) is a data type that containsdrawing attribute information. The GC manages attributes such as the currentforeground color, line width, and line style. Requests to change the value of anattribute are made to the GC. Your application is responsible for creating,manipulating, and freeing GC objects. In general, applications will create their ownGCs. However, each screen has a default GC that is useful for testing purposes.You can obtain the default GC of the default screen using CgGC default.

Each of these objects plays an important role in the Common Graphics subsystem.

Seldom-used and abstract classesOnce you are familiar with the frequently used classes and the classes that performspecific operations, you might want to learn more about the seldom-used classeslisted in the following table. These classes are beyond the scope of thisintroduction, but are referenced in later sections of this chapter.

Table 15. Seldom-used or abstract classes

Class Description

CgArc Specifies the integer coordinates and angles of an arc.

CgCharStruct Specifies properties of individual characters, includingheight, width, and offset.

CgFontProp Specifies an extra property of a font such as its name orits spacing.

CgID Abstract class of server resources, includingCgDrawable, CgCursor, CgFont.

CgLogicalFontDescription Specifies a data structure used to assist in parsing fontnames.

CgRegion Specifies a geometric region consisting of a set ofrectangles.

CgSegment Specifies the integer coordinates of a line segment.

CgVisual Specifies visual properties of a screen.

82 IBM Smalltalk: Programmer’s Reference

Page 97: IBM Smalltalk: Programmer's Reference

A simplified drawing process overviewMost drawing operations use the following procedure:

Before drawingv Load any required fonts.v Create one or more graphics contexts.v Create any required pixmaps.

Note: These steps cause operating system resources to be allocated.

During drawingv Set attributes in the graphics context; for example, line width, font.v Issue the drawing operation request; for example, drawString, fillRectangle.

After drawingv Unload any fonts that were loaded.v Free any graphics contexts that were created.v Free any pixmaps that were created.

Note: These steps release the operating system resources.

The above process does not address the use of color. The sections on the ImageSupport classes discuss the use of color. The remaining sections and examples forthe core classes assume drawing is done using black and white.

A simple example of the drawing processIn the following example, the default window is assigned to the temporaryvariable drawable. A graphics context called gc is created for this drawable with noinitial values. Notice that the CgConstants pool dictionary constant None is used toindicate that no values are being set. In the next line, the foreground color is set toblack. (The blackPixel message, used to get the pixel value for black, is discussed in“Drawing in black and white” on page 119.) The drawable is then sent a messageto draw a filled rectangle at the appropriate coordinates using the displayattributes from the graphics context called gc. At the end of this routine, the GC isfreed, and its resources are returned to the operating system.| gc drawable |drawable := CgWindow default.gc := CqGCdefault

"Set a graphics context attribute."gc setForeground: drawable blackPixel.drawable"Issue a drawing operation."

fillRectangle: gcx: 100y: 100width: 50height: 50.

CgConstants pool dictionaryThe Common Graphics subsystem uses a pool dictionary called CgConstants. Thisdictionary provides pool variables for constant values that are used by thesubsystem. For example, pool variables such as GCForeground and GCLineWidth areused to indicate which graphics context attributes to change in the createGC:values:and changeGC:values: methods. Other pool variables, such as FillStippled and

Chapter 6. Common Graphics 83

Page 98: IBM Smalltalk: Programmer's Reference

LineSolid, are used to represent various GC attribute values. Pool variable namesshould be used rather than directly using their constant values.

Using graphics contextsA Graphics Context or GC is an object that contains drawing attributeinformation, such as foreground color, background color, line width, and line style.When an object is drawn on a drawable, the drawable references the graphicscontext to determine how the object should appear.

Normally, an application creates and uses at least one GC. Your application cancreate and use many graphics contexts, however. You should use multiple graphicscontexts carefully as they are relatively expensive to build and maintain.

For optimum performance, you should draw as much as possible with the sameGC, minimizing the number of times you change its components. The cost ofchanging GC components relative to using different GCs depends on the specificplatform because some servers cache a limited number of GCs in the displayhardware.

For interactive experimentation and testing, there is a default GC that can beaccessed using CgScreen default defaultGC or CgGC default.

Note: The default GC is intended only for experimentation and testing.Applications should create their own GCs.

In the following figure, a drawable (the root window of the default screen) receivesa message to draw a 100x100 filled rectangle at 20@20. The programmer provides agraphics context called aGC. The drawable references aGC to find out how todisplay the rectangle.

The root window (CgWindow default)

Smalltalk message sent by your applicationThe graphics context called ‘aGC’

2 pixels

LineSolid

black

white

FillSolid

.

.

.

lineWidth

lineStyle

foregroundcolor

backgroundcolor

fillStyle

.

.

.

Draws rectangle

Basic graphics context methodsA brief summary of the main methods that apply to graphics contexts follows.There are convenience methods for setting individual attributes of a graphicscontext. These methods are described later in this section.

84 IBM Smalltalk: Programmer’s Reference

Page 99: IBM Smalltalk: Programmer's Reference

createGC:values:Create and initialize a graphics context.

changeGC:values:Change a group of graphics context attributes.

copyGC:dest:Copy a group of graphics context attributes to another graphics context.

getGCValues:valuesReturn:Retrieve a group of graphics context attributes from a graphics context.

freeGC Free the resources allocated to the graphics context.

Creating graphics contextsGraphics contexts are created by sending the createGC:values: message to aCgDrawable. The GC attributes are initialized to preset values, listed in Table 16 onpage 86. The two arguments of the message specify modifications to the presetvalues. The first argument, valuemask, specifies which components of the secondargument, values, should override the preset values.

Creating a graphics context with default valuesIn the following example, the temporary variable gc is assigned a graphics context.By passing the CgConstants constant None as the valuemask and nil as the values,the graphics context is initialized using default values.| gc |gc := CgWindow default

createGC: Nonevalues: nil.

Creating a graphics context using the CgGCValues objectGraphics contexts can be configured using a CgGCValues object. The CgGCValuesobject is a convenient way of storing graphics attributes without having to storethe graphics context and its associated overhead. The CgGCValues object is used toconfigure a GC or to query its attributes.

In the following example, a CgGCValues object is created, the function: message setsthe desired raster operation (GXhighlight), and the lineWidth: message sets a linewidth value (2 pixels) in the CgGCValues object. The CgGCValues object is thenpassed to the drawable using the createGC:values: message. The valuemasksGCFunction and GCLineWidth are ORed together to create a mask that identifieswhich attributes are being modified. The gcValues variable contains the new valuesfor the attributes.| gc gcValues |gcValues := CgGCValues new

function: GXhighlight;lineWidth: 2.

gc := CgWindow defaultcreateGC: GCFunction | GCLineWidthvalues: gcValues.

Retrieving several values from a graphics context using theCgGCValues objectYou can also use a CgGCValues object to retrieve attribute values from a graphicscontext. In the following example, the GCLineWidth valuemask is used to retrievethe current line width. The information is returned in a new CgGCValues object.

Chapter 6. Common Graphics 85

Page 100: IBM Smalltalk: Programmer's Reference

| gcValues lineWidth |CgGC default

getGCValues: GCLineWidthvaluesReturn: (gcValues := CgGCValues new).

lineWidth := gcValues lineWidth.

Note: The GCClipMask and GCDashList components of a GC cannot be retrieved.Table 16 contains the complete list of attributes that can be initialized or modified.In most cases, the attribute is either an integer value or a constant from theCgConstants pool dictionary. For a detailed explanation, consult the methodcomment for the createGC:values: method of CgDrawable.

Table 16. Graphics context attributes

Value mask Value expected Default value

GCForeground specifies theforeground drawing color

Integer pixel value (index of color in colormap) 0

GCBackground specifies thebackground drawing color

Integer pixel value (index of color in colormap) 1

GCLineWidth specifies thethickness of the drawing line

Integer value of line width in pixels 1 pixel

GCLineStyle specifies how aline should be drawn. Dashpattern is specified using adash list (see “dashes” below)

LineSolid (foregroundcolor)

LineOnOffDash(foreground color)

LineDoubleDash (fore-and background color)

LineSolid

GCCapStyle specifies how aline should be ended

CapNotLastCapButtCapRoundCapProjecting

CapButt

CGJoinStyle specifies how twolines should be joined

JoinMiter

JoinRound

JoinBevel

JoinMiter

GCFillStyle specifies how to fillan object such as an arc,rectangle, or polygon

FillSolid(foreground color)FillStippled(foreground color)FillOpaqueStippled(fore- and background

colors)FillTiled(a multicolored pixmap)

Pixmap

FillSolid

GCFillRule specifies how apolygon should be drawnwhen it intersects itself

EvenOddRule (hollowwhere areas intersect)

WindingRule (solid whereareas intersect)

EvenOddRule

86 IBM Smalltalk: Programmer’s Reference

Page 101: IBM Smalltalk: Programmer's Reference

Table 16. Graphics context attributes (continued)

Value mask Value expected Default value

GCArcMode specifies how anarc should be drawn. To fill anarc, the GCFillStyle would alsohave to be set correctly.

ArcChord (connects startand end points directly)

ArcPieslice (connects startand end points throughthe arc center point)

ArcChord

GCFunction specifies the rasteroperation to be used

GXcopy(draws shape directly from source)GXhighlight(draws shape, replacing foreground with

background and vice-versa. Drawingthe same shape again will restoredrawable to previous state)

GXcopy

GCFont specifies the font to beused in text drawingoperations

A CgFont Standard system font

GCSubwindowMode specifieswhether drawing in a parentwindow is clipped by or drawsover child windows

ClipByChildren(allows drawing only in the parent window; child

windows are not affected)IncludeInferiors(child boundaries are ignored; drawing in the

parent window will draw over child windows)

ClipByChildren

GCTileStripXOrigin specifiesthe x offset of the tile orstipple pattern allowing you toposition the pattern evenly

Integer value Checker stipple patternis 10 pixels square

Area to be filled is also10 pixels square

If GCTileStipXOriginequals -1, the pattern isoffset as shown.

0

GCTileStipYOrigin specifiesthe y offset of the stipple ortile pattern allowing you toposition the pattern evenly

Integer value Checker stipple pattern is10 pixels square

Area to be filled is also 10pixels square

If GCTileStipYOrigin equals-1, the pattern is offset asshown.

0

GCClipXOrigin x integer coordinate for clipping 0

GCClipYOrigin y integer coordinate for clipping 0

GCClipMask specifies theCgPixmap used as a clippingmask

A CgPixmap of depth 1, or nil nil

GCDashOffset specifies inpixels where to begin within adash pattern

Integer value 0

tile specifies a CgPixmap to beused as a multiplane,multicolor fill pattern

A CgPixmap of the same depth as the drawable A tile CgPixmapcontaining all zeros

stipple specifies a CgPixmap tobe used as a 1-plane, 2-colorfill pattern

A CgPixmap of depth 1 A stipple CgPixmapcontaining all ones

dashes specifies the lengths ofsegments in the dash list

Array of integersspecifying the length ofeach dash in number ofpixels

#(4 4)

Chapter 6. Common Graphics 87

Page 102: IBM Smalltalk: Programmer's Reference

Tip: Some platforms impose constraints on the implementation of the graphicscontext attributes. These limitations are described in “Appendix D. Commongraphics platform differences” on page 515.

Configuring a graphics context using convenience methodsConvenience (set) methods have been provided for setting graphics contextattributes. These methods are sent directly to the graphics context and are simplerto use than specifying CgGCValues and valuemasks.

In the following example, a GC is created using default values, then immediatelymodified using two convenience methods.| gc |gc := CgWindow default

createGC: Nonevalues: nil.

gc setFunction: GXcopy.

gcsetLineAttributes: 2lineStyle: LineSolidcapStyle: CapButtjoinStyle: JoinMiter.

The following table lists frequently used convenience methods that can be sent to agraphics context.

Table 17. Graphics context convenience (set) methods

Method Values modified Example

setBackground: Background color gc setBackground:CgWindow default whitePixel

setDashes:dashList:

Dash offset and pattern gc setDashes: 0 dashList: #(100 20)

setForeground: Foreground color gc setForeground:CgWindow default blackPixel

setFunction: Raster operation gc setFunction: GXhighlight

setLineAttributes:lineStyle:capStyle:joinStyle:

Width, style, endcap style, andjoin style of a line, all at once

gcsetLineAttributes: 2

lineStyle: LineOnOffDashcapStyle: CapButtjoinStyle: JoinMiter

setState:background:function:planeMask:

Foreground and backgroundcolors, the raster operationfunction, and the planeMask allat once

gcsetState: CgWindow default blackPixelbackground: CgWindow default whitePixelfunction: GXcopyplaneMask: nil

Copying graphics contextsCopy graphics context attributes to another GC using copyGC:dest:. The followingexample creates a GC, sets its foreground and background attributes, and thencopies these attributes to a new GC.| oldGC newGC |oldGC := CgWindow default

createGC: Nonevalues: nil.

88 IBM Smalltalk: Programmer’s Reference

Page 103: IBM Smalltalk: Programmer's Reference

oldGCsetForeground: CgWindow default blackPixel;setBackground: CgWindow default whitePixel.

newGC := CgWindow defaultcreateGC: Nonevalues: nil.

oldGCcopyGC: GCForeground | GCBackgrounddest: newGC

Changing graphics contextsSeveral graphics context attributes can be modified at once using thechangeGC:values: message. The following example creates a GC with defaultattributes, then changes the foreground and background colors.| gc |gc := CgWindow default

createGC: Nonevalues: nil.

gcchangeGC: GCForeground | GCBackgroundvalues:

(CgGCValues newforeground: CgWindow default blackPixel;background: CgWindow default whitePixel).

Freeing graphics contextsGraphics contexts are released using freeGC. Your application is responsible forfreeing the graphics contexts it creates. Graphics contexts can be freed at any time,but cannot be used for drawing after being freed.| gc |gc := CgWindow default

createGC: Nonevalues: nil.

"Perform some drawing operations using the gc..."

gc freeGC.

Tip: Do not attempt to free the default GC. This can cause unpredictable behavior.

Using graphics contexts with other drawablesA graphics context can be used for drawing on any drawable that is on the samescreen and that has the same depth as the drawable for which it was created. Thismeans that a GC created for a window on a 256-color screen can be used for anywindow or 256-color pixmap on the same screen, but it cannot be used fordrawing on a pixmap of depth 1. In this case, a separate GC must be created forthe 1-bit pixmap.

Drawing operationsCommon Graphics includes methods for drawing points, lines, rectangles,polygons, arcs, and strings. All drawing methods are sent to a CgDrawable—eithera window or a pixmap. The first keyword in the method describes the function ofthe method. The first argument passed to the method is always a graphics context.The first keywords of the CG drawing methods follow:

drawArc:drawArcs:

Chapter 6. Common Graphics 89

Page 104: IBM Smalltalk: Programmer's Reference

drawImageString:drawLine:drawLines:drawPoint:drawPoints:drawRectangle:drawRectangles:drawSegments:drawString:drawText:fillArc:fillArcs:fillPolygon:fillRectangle:fillRectangles:

Because the drawString:, drawImageString:, and drawText: methods require the use offonts, they are described in the subsection “Using fonts” on page 93. The otherdrawing methods are covered in the following subsections:

Drawing pointsTwo methods are used to draw points. A point is a single pixel in a drawable.drawPoint:x:y:

Draws a single pointdrawPoints:points:mode:

Draws multiple points

Note: The point “0@0” is in the upper left corner.

The following example draws a point at 20@20 on the default root window usingthe default GC.CgWindow default

drawPoint: CgGC defaultx: 20y: 20.

The following example draws a series of points, specified as an Array of Points.The constant CoordModeOrigin is used to indicate that each point should be drawnrelative to the origin. Passing CoordModePrevious as the mode specifies that thecoordinates of each point (except the first) are relative to the previous point.| points |points := Array new: 10.1 to: 10 do: [:i |

points at: i put: (i*3)@(i*6)].

CgWindow defaultdrawPoints: CgGC defaultpoints: pointsmode: CoordModeOrigin.

Drawing linesThree methods are used to draw lines. Lines provided in the argument list aredrawn using the attributes (such as color, line style, line width) contained in theGC provided in the argument list.

drawLine:x1:y1:x2:y2:Draws a single line.

90 IBM Smalltalk: Programmer’s Reference

Page 105: IBM Smalltalk: Programmer's Reference

drawLines:points:mode:Draws a polyline, consisting of multiple connected lines specified as anArray of Points.

drawSegments:segments:Draws multiple, unconnected lines.

The following example draws a single line from 20@20 to 50@50 on the defaultroot window using the default GC.

CgWindow defaultdrawLine: CgGC defaultx1: 20y1: 20x2: 50y2: 50.

+

+

The following example draws a series of lines on the root window beginning withthe first point and ending at the last point in the array.

| points |(points := Array new: 6)

at: 1 put: 89 @ 100;at: 2 put: 12 @ 45;at: 3 put: 108 @ 45;at: 4 put: 31 @ 100;at: 5 put: 60 @ 10;at: 6 put: 89 @ 100.

CgWindow defaultdrawLines: CgGC defaultpoints: pointsmode: CoordModeOrigin

+++

+ +

Drawing rectanglesThe drawRectangle:x:y:width:height:, fillRectangle:x:y:width:height:,drawRectangles:rectangles: and fillRectangles:rectangles: messages are used to drawoutlined and filled rectangles. The fillRectangle: and fillRectangles: messages areshown in the following example:

CgWindow defaultfillRectangle: CgGC defaultx: 10y: 10width: 50height: 50.

+

+

| rects rect1 rect2 |rect1 := 10@10 extent: [email protected] := 70@10 extent: [email protected] := Array with: rect1 with: rect2.

CgWindow defaultfillRectangles: CgGC defaultrectangles: rects.

+ +

+

Chapter 6. Common Graphics 91

Page 106: IBM Smalltalk: Programmer's Reference

Drawing polygonsPolygons are drawn using the fillPolygon:points:shape:mode: method. The polygon isautomatically closed whether or not the first and last points match. For instance, inthe following example, Array with: 10@10 with: 10@60 with: 60@35 with: 10@10would have provided the same result. The shape argument describes the shape ofthe polygon and can be set to Complex, Convex, or Nonconvex. Complex specifies thatthe polygon can be either convex or self-overlapping. Convex specifies that thepolygon is one where a straight line connecting any two points of the polygondoes not cross any edge. Nonconvex specifies that the polygon is not convex, butthat it does not overlap itself. Specifying Complex will draw correctly in all cases.Specifying Convex or Nonconvex can improve drawing performance on someplatforms, but the polygon’s shape must be known in advance. The followingexample draws a triangle based on the collection of points provided.

| points |points := Array with: 10@10 with: 10@60

with: [email protected] default

fillPolygon: CgGC defaultpoints: pointsshape: Convexmode: CoordModeOrigin.

+

+

+

The mode argument can be set to CoordModeOrigin, so that all points are drawnrelative to the origin, as in the previous example, or CoordModePrevious, so that allpoints are drawn relative to the previous point in the collection, as in the followingexample:

| points |points := Array with: 10@10

with: 10@60 with: [email protected] default

fillPolygon: CgGC defaultpoints: pointsshape: Convexmode: CoordModePrevious

+

+

+

Drawing arcs and circlesThere are several methods for drawing arcs: fillArcs:arcs:,drawArc:x:y:width:height:angle1:angle2:, fillArc:x:y:width:height:angle1:angle2:, anddrawArcs:arcs:. Angles are specified in 1/64 of a degree. Zero degrees is positionedat three o’clock with positive angles measuring in a counterclockwise direction. Todraw an arc, you specify a bounding rectangle, a start angle (in 64ths of a degree)and an extent angle (in 64ths of a degree). The extent angle is relative to the startangle. For example, to draw a semicircle from 90 degrees to 270 degrees, the startangle would be 90 * 64 degrees and the extent angle would be 180 * 64 degrees.You can draw multiple arcs using the drawArcs:arcs: methods.

The following example draws an arc bounded by the rectangle (20@20 corner:60@60). The arc starts at an angle of 45 degrees and extends for another 270degrees, ending at 315 degrees.

92 IBM Smalltalk: Programmer’s Reference

Page 107: IBM Smalltalk: Programmer's Reference

CgWindow defaultdrawArc: CgGC defaultx: 20y: 20width: 40height: 40angle1: 64 * 45angle2: 64 * 270

+

+

Drawing pie slices and chords using filled arcsFilled arcs draw either as a pie slice or as a chord, depending on the setting of theGCArcMode GC attribute. When the GCArcMode is set to ArcPieSlice, a pie slice isdrawn.

| gc |gc := CgGC default.gc setArcMode: ArcPieSlice.CgWindow default

fillArc: gcx: 20y: 20width: 40height: 40angle1: 64 * 45angle2: 64 * 270.

+

+

When the GCArcMode is set to ArcChord, a chord is drawn.

| gc |gc := CgGC default.gc setArcMode: ArcChord.CgWindow default

fillArc: gcx: 20y: 20width: 40height: 40angle1: 64 * 45angle2: 64 * 270.

+

+

Using fontsThis section gives an overview of the Common Graphics font system. For moredetails, refer to the X11R4 reference manual. For further information on scalablefonts, refer to the X11R5 reference manual. The following classes comprise the fontsystem:

CgFontRepresents a loaded font with a given size and style

CgFontStructDescribes a CgFont. Contains information such as the number of charactersin the font, font height, average character width, ascender height,descender height, whether the font is monospaced or proportional, and thedimensions of each character in the font

Chapter 6. Common Graphics 93

Page 108: IBM Smalltalk: Programmer's Reference

CgFontPropContains additional font properties, such as the font’s name

CgCharStructDescribes the dimensions of each character in the font

CgGC Specifies the font to use in string drawing operations

CgDisplayLoads and lists available fonts

CgTextItemIs a data structure used by the drawText: method, which draws multipletext strings, each with different attributes, in a single drawing operation

CgLogicalFontDescriptionIs a data structure used to assist in specifying and parsing font names

A simplified view of the font processEach platform has a list of fonts that are available for use. An application queriesthe platform to find out which fonts are available using a pattern-matching searchmechanism. The platform returns all matching font names. The application thenloads the appropriate font into memory, assigns the font to a graphics context andissues string drawing operations. After the application is finished with the font, itunloads it from memory.

Times

aCgWindow

Handle tothe fontstructure

CgFont

aCgWindowdrawString: aCgGCx: 20y: 100string: ‘Times’

Your Application

Font: aCgFont

aCgGC

Fontattributes:height,width, #chrs,and so on

CgFontStruct

Individual character definition

CgCharStruct

XLFD standardfont name

CgFontProp

Using fonts1. Query the system for available fonts (CgDisplay).2. Load the requested font(s) into memory (CgDisplay).3. Assign the font for use in drawing operations (CgGC).4. Perform the drawing operations (CgDrawable).5. Free the font(s) from memory (CgFont).

The following example illustrates the complete font process described in the stepsabove. Each step is described in detail in the subsections following the example.| fontNames font gc |"Query the system for the string names of two available fonts"fontNames := CgDisplay default

listFonts: '*'maxnames: 2.

"Use the font string name to load a font"font := CgDisplay default loadFont: (fontNames at: 2).gc := CgCGdefault

94 IBM Smalltalk: Programmer’s Reference

Page 109: IBM Smalltalk: Programmer's Reference

"Assign the font for use in drawing operations"gc setFont: font.

CgWindow default"Perform a string drawing operation"

drawString: gcx: 10y: 100string: 'hello world'.

"Free the font"font unloadFont.

Querying the system for fontsThe system is queried for available fonts by sending the listFonts:maxnames:message to a CgDisplay. The message includes two arguments: a pattern-matchingstring and the maximum number of font string names to be returned.

Pattern matchingThe Common Graphics subsystem defines font names using the X Logical FontDescription (XLFD) convention. This convention is described in detail in the X11R4and R5 reference manuals. Valid search patterns can be created using anycombination of wildcard (* or ?) or literal values. The “*” represents a string ofzero or more arbitrary characters. The “?” represents a single arbitrary character.The “-” is used as a separator between fields in the XLFD name. The followingexample shows the meaning of each field in the XLFD name:

’-adobe-helvetica-bold-i-normal-sans serif-12-120-75-75-p-70-iso8859-1’

weight

slant spacingfamilyname

additionalinformation(often blank)

pointsize

character setregistry

fontfoundry

set_widthname pixel size x and y

resolutionaveragewidth

The following table describes the fields of an XLFD name.

Table 18. X logical font description fields

Field name Valid field values Examples

Font foundry X-registered manufacturer name adobe, bitstream,microsoft

Family name Font family name helvetica, times, courier

Weight Blackness or density medium, bold

Slant Vertical posture of font characters r (roman), i (italic), o(oblique), ri (reverseitalic), ro (reverseoblique), ot (other)

Set_width_name Width of font characters (usuallynormal)

normal, condensed,narrow, double wide

Add_style_name Additional information (often blank) serif, sans serif, informal,decorated, iso9241

Pixel_size Font vertical height measurement inpixels

8, 10, 12, 14, and so on(zero indicates a scalablefont)

Chapter 6. Common Graphics 95

Page 110: IBM Smalltalk: Programmer's Reference

Table 18. X logical font description fields (continued)

Field name Valid field values Examples

Point_size Font vertical height measurement in1/10ths of 1/72 of an inch (24 point =240)

120, 140, 180, 240, 360(zero indicates a scalablefont)

Resolution_x Horizontal resolution of display in dotsper inch

75, 100

Resolution_y Vertical resolution of display in dotsper inch

75, 100

Spacing Font spacing p (proportional), m(monospaced), c(character cell)

Average_width Average width of all the glyphs in 1/10of pixel increments. Used formonospaced fonts and character cellfonts to calculate characters per line

50, 60, 70, and so on(zero indicates a scalablefont)

Charset_registry/encoding

X registered name that identifies thecoding authority for the character set

iso8859-1

The following table shows the sample values for the character set andregistry/encoding fields.

Table 19. Example platform charset_registry/encoding names

Family Name Charset Registry/Encoding Description

courier iso8859 1 courier matches iso8859specification

symbol microsoft fontspecific microsoft symbol font

@system microsoft @shiftjis microsoft system double-bytefont, double-byte charactersrotated 90° counter-clockwise

terminal microsoft shiftjis microsoft terminal double-bytefont double-byte characters notrotated

courier ibm 437 ibm courier for code page 437

courier ibm 932.sbcs ibm courier single-byte font forcode page 932

mincho ibm 932 ibm mincho double-byte fontfor code page 932 (zeroindicates a scalable font)

Note: The CdLogicalFontDescription class can be used to assist in creating XLFDfont names and in parsing the fields out of font names. Its use is illustratedin “Determining whether a font is scalable” on page 97 and “Parsing ascalable font name” on page 98.

The following example finds a maximum of two font strings of any description (*):| fontNames |fontNames := CgDisplay default

listFonts: '*'maxnames: 2.

96 IBM Smalltalk: Programmer’s Reference

Page 111: IBM Smalltalk: Programmer's Reference

The following example finds a maximum of 20 helvetica fonts. Note that allfourteen fields are specified, either as wildcards or not. It is not necessary tospecify all fourteen fields. However, if all fourteen fields are specified and eitherthe pixel size or point size fields are not wildcards (that is, a specific size isdesired), then scalable fonts will match the pattern, filling in the pixel size andpoint size fields appropriately. Scalable fonts are described in detail in the nextsection.| fontNames |fontNames := CgDisplay default

listFonts: '-*-helvetica-*-*-*-*-*-*-*-*-*-*-*-*'maxnames: 20

Tip: The listFonts: method is not required to include scalable fonts in the returnedlist unless all XLFD fields are specified in the pattern. To ensure that scalablefonts are included in the list, specify all 14 XLFD fields as in the previousexample rather than using a single wildcard to match across several fields.

As a general rule, it is best to specify the font’s family name, weight, slant,and point size fields explicitly.

It is better to match the point size field and leave the pixel field as a wildcardbecause this allows the most appropriate match for the resolution of thedisplay.

Loading fontsCommon Graphics supports both scalable and nonscalable fonts. Scalable fonts area variable font definition that can be scaled to different sized fonts. Nonscalablefonts cannot be scaled and, when loaded, are always the same size. Scalable fontsare indicated by zeros in the pixel size, point size, and average width fields of thefont name.

To load a scalable font successfully, you must specify the size of the font bychanging the pixel size or the point size field in the font name prior to issuing oneof the font loading methods. Because a nonscalable font has a predetermined size,its font name is passed directly to the font loading methods without anypreprocessing.

Determining whether a font is scalableConsider the two font names that follow. In the first font name, the pixel size, pointsize and average width fields contain zeros (-0-0-...-0-) indicating that it is a scalablefont. In the second font name, all three fields have actual values (-33-240-...-180-)indicating that it is a nonscalable, or fixed size, font.-adobe-helvetica-bold-i-normal-sans serif-0-0-100-100-p-0-iso8859-1-adobe-helvetica-bold-i-normal-sans serif-33-240-100-100-p-180-iso8859-1

CgLogicalFontDescription class can be used to parse and modify an XLFD name. Thefollowing example determines whether or not a font is scalable by first creating aCgLogicalFontDescription object for the font.| fontName description |"Ask the system for any font name."fontName := (CgDisplay default

listFonts: '-*-*-*-*-*-*-*-*-*-*-*-*-*-*'maxnames: 1) first.

"Create a font description object for the font name."

Chapter 6. Common Graphics 97

Page 112: IBM Smalltalk: Programmer's Reference

description := CgLogicalFontDescription name: fontName.

"Answer true if the font is scalable, false otherwise."|description isScalable.

Parsing a scalable font nameTo load a scalable font, the zeros in the size fields of the font name must bereplaced by actual values and passed to one of the font loading methods. Thefollowing example illustrates the use of a CgLogicalFontDescription object to specifythe point size in a scalable font name. Point size is specified in 1/10ths of 1/72 ofan inch (tenths of a point), so a 24-point font is represented as 240. Also note thatthe pixel size and average width fields are changed to wildcards, indicating thatthey will be computed based on the point size.| fontName description |fontName := '-adobe-helvetica-bold-i-normal-sans serif-0-0-100-100-p-0-iso8859-1'.

"Create a font description object for the name."description := CgLogicalFontDescription name: fontName.

"Replace point size, pixel size, and average character width fields."description

points: '240';pixels: '*';averageWidth: '*'.

"Get the modified name back as a string."description name

The preceding code returns this:'-adobe-helvetica-bold-i-normal-sans serif-*-240-100-100-p-*-iso8859-1'

Once the scalable font name has been modified to specify a fixed size, it is thenreferred to as a scaled font name. It can then be passed to one of the font loadingmethods that follow. Fonts are loaded into memory by sending the loadFont: orloadQueryFont: messages to a CgDisplay object. The loadFont: method takes a fontname and returns a CgFont object. The loadQueryFont: method takes a font nameand returns a CgFontStruct object.

Loading a CgFont| fontName font |fontName := '8x13'.font := CgDisplay default

loadFont: fontName.

Loading a CgFontStruct| fontName fontStruct |fontName := '8x13'.fontStruct := CgDisplay default

loadQueryFont: fontName.

More about CgFont and CgFontStructIn the last example, two different operations were used to load a CgFontStruct anda CgFont object. These two objects, while both representing a font, provide differentkinds of information to the application.

CgFont is a handle to the font in the operating system. It is useful in applicationswhere you simply wish to draw text and do not require a measure of thedimensions of the text.

98 IBM Smalltalk: Programmer’s Reference

Page 113: IBM Smalltalk: Programmer's Reference

CgFontStruct is a more detailed description of the font. It provides information thatis useful when you need to perform calculations based on text width or textheight, for example, centering a label in a window.

Here are some of the more useful CgFontStruct access methods:

font Returns the CgFont.

name Returns the name of the font.

ascent Returns the integer height in pixels of the font ascender.

descent Returns the integer height in pixels of the font descender.

height Returns the integer height in pixels of the font (ascent plus descent).

defaultCharReturns the character index to use for undefined characters.

numCharsReturns the number of characters in the font.

perCharReturns the first row of an array of CgCharStructs describing thedimensions of each character in the font.

perCharAtRow:Returns the specified row of an array of CgCharStructs describing thedimensions of each character in the font. Use for double-byte fonts.

perCharNumRowsReturns the number of rows in the font’s per-char information.

perCharNumColumnsReturns the number of columns in the font’s per-char information.

maxBoundsReturns a CgCharStruct describing the maximum bounds over all charactersin the font.

minBoundsReturns a CgCharStruct describing the minimum bounds over all charactersin the font.

textWidth:Returns the width in pixels of the text string provided.

textExtents:directionReturn:fontAscentReturn:fontDescentReturn:overallReturn:Returns the direction in which text is drawn, the font ascender, the fontdescender, and a CgCharStruct describing the overall size of the text.

More about CgCharStructWhile a CgFontStruct holds information about the entire font, a CgCharStruct holdsinformation about each individual character in the font. The following diagramshows some of the commonly used metrics of both CgFontStruct and CgCharStruct

Chapter 6. Common Graphics 99

Page 114: IBM Smalltalk: Programmer's Reference

as they pertain to two characters ‘A’ and ‘j’ in a typical font.

baseline

asce

nt

asce

ntde

scen

t

CgC

harS

tru c

t fo r

’j’

lbearing

CgF

ontS

truc

tas

cent

desc

ent

CgF

ontS

truc

t

CgC

harS

tru c

t fo r

’A’

desc

ent =

0

rbearing

bearing

characterorigins

width widthCgCharStruct for ’A’ CgCharStruct for ’j’

Note that the origin of each character is on the baseline, and not in the upper left.A CgCharStruct’s origin is the leftmost pixel along its baseline; therefore, it isactually at a point that is 0 @ ascent with respect to the upper left corner of theCgCharStruct. This is useful to know when drawing a string inside of a rectangledrawn at x @ y. The string must be drawn at x @ (y + ascent). This is in keepingwith typographic convention. The ascent, descent, and width of a CgFontStruct areequal to the largest CgCharStruct ascent, descent, and width in the font. Thelbearing, rbearing, and bearing metrics are only shown for ‘A.’ AdditionalCgCharStruct instance methods follow:

ascent Returns the number of pixels between the baseline and the top edge of theraster.

descent Returns the number of pixels between the baseline and the bottom edge ofthe raster.

height Returns the number of pixels between the top edge of the raster and thebottom edge of the raster.

extent Returns a point in which the x-coordinate is the character’s height, and they-coordinate is the character’s width.

bearing Returns the number of pixels between the left edge of the raster and theright edge of the raster.

lbearingReturns the number of pixels between the origin and the left edge of theraster.

rbearingReturns the number of pixels between the origin and the right edge of theraster.

width Returns the number of pixels to advance to the next character’s origin.

Assigning fonts for use in drawing operationsBefore a font can be used in a drawing operation, it must be assigned to a graphicscontext. All text drawing operations use the font in the graphics context. A CgFontis assigned to the graphics context using the setFont: method.

100 IBM Smalltalk: Programmer’s Reference

Page 115: IBM Smalltalk: Programmer's Reference

| font |font := CgDisplay default

loadFont: '-*-helvetica-bold-r-normal-*-*-240-*-*-*-*-*-*'.CgGC default

setFont: font.

The following example shows assigning a CgFontStruct for use in a graphicscontext:| fontStruct |fontStruct := CgDisplay default

loadQueryFont: '-*-helvetica-bold-r-normal-*-*-240-*-*-*-*-*-*'.CgGC default"The setFont: method expects to be passed a CgFont"setFont: fontStruct font.

String drawing operations with fontsYou can draw text by sending the drawString:, drawImageString:, or drawText:messages to a CgDrawable object. As in all drawing operations, the first parameterpassed to the method must be a valid graphics context. This graphics context willcontain either a default font or the font you have loaded and set in the graphicscontext.

In all string and text drawing methods the y-coordinate specifies the coordinatewhere the baseline of the string will be drawn, not the top of the string’s boundingbox.

Drawing a stringThe drawString:x:y:string: method draws a string at a given point in the foregroundcolor. Only the pixels for the characters are modified. Pixels between characters areleft unchanged.

CgWindow defaultdrawString: CgGC defaultx: 10y: 100string: 'Going global'.

+

Drawing an image stringThe drawImageString:x:y:string: method draws a string at a given point. The text isdrawn in the foreground color and the pixels in the remainder of the rectanglecontaining the string are set to the background color.

CgWindow defaultdrawImageString: CgGC defaultx: 10y: 100string: 'Hello world'.

+

Drawing multifont strings using CgTextItem objectsThe drawText:x:y:items: allows multiple strings to be drawn at once. Strings aredrawn in the same manner as drawString:. The background is left unmodified. Eachstring is specified by a CgTextItem object.

Chapter 6. Common Graphics 101

Page 116: IBM Smalltalk: Programmer's Reference

A CgTextItem object contains character, delta and font components. The charcomponent specifies the string value, delta represents the horizontal offset from theprevious item and font represents the font to be used in the drawing operation. Thefont component is optional. If it is specified, the font in the graphics context ischanged and the string is drawn in the new font. Otherwise, the string is drawn inthe current font. The CgTextItem must be provided with at least the char and deltainformation. These values can be set individually, with chars:, delta:, or font:, orsimultaneously, with chars:delta:font:.

| fontName1 font1 fontName2 font2 item1 item2 item3 |fontName1 := (CgDisplay default

listFonts: '-*-helvetica-bold-r-normal-*-*-240-*-*-*-*-*-*'maxnames: 1) at: 1.

font1 := CgDisplay default loadFont: fontName1.

fontName2 := (CgDisplay defaultlistFonts: '-*-helvetica-bold-i-normal-*-*-240-*-*-*-*-*-*'maxnames: 1) at: 1.

font2 := CgDisplay default loadFont: fontName2.

item1 := CgTextItem chars: 'The ' delta: 0 font: font1.item2 := CgTextItem chars: 'quick ' delta: 0 font: font2.item3 := CgTextItem chars: 'brown fox' delta: 0 font: font1.

CgWindow defaultdrawText: CgGC defaultx: 10y: 100items: (Array with: item1 with: item2 with: item3).

The quick brown fox+

Releasing CgFonts and CgFontStructs from memoryYou can release fonts or fontStructs from memory either by sending the unloadFontmessage to a CgFont object or by sending the freeFont message to a CgFontStructobject. This should be done when the font is no longer required for drawing.

Tip: Every font loaded with loadFont: must be unloaded using unloadFont. EveryfontStruct loaded with queryFont: or loadQueryFont: must be freed usingfreeFont. The freeFont method also unloads the CgFont object associated withthe CgFontStruct.

Obtaining the current font from a graphics contextYou can determine the font currently set in a graphics context using thegetGCValues: method. In the following example, the GCFont valuemask is used toretrieve the current font. The information is returned in a new CgGCValues object.You can retrieve the CgFontStruct information by sending a queryFont message tothe CgFont. You then obtain the actual string name of the font from theCgFontStruct.| values font fontStruct fontName |CgGC default

getGCValues: GCFontvaluesReturn: (values := CgGCValues new).

font := values font.fontStruct := font queryFont.fontName := fontStruct name.

102 IBM Smalltalk: Programmer’s Reference

Page 117: IBM Smalltalk: Programmer's Reference

Using cursorsThe Common Graphics subsystem provides three types of cursors. Font cursors arecreated from a predefined, built-in cursor font. Glyph cursors are created fromcharacters in a specified font. Pixmap cursors are created from two pixmaps.

The process for using cursorsTo use cursors, do the following.1. Create the cursor.2. Define the cursor in a window.3. Perform some work, during which the cursor is shown. Whenever the mouse

pointer is over a window, the defined cursor for the window is shown.4. Undefine the cursor from the window.5. Free the cursor.

Before using a cursor, you must create it by sending a cursor creation message toeither a CgDisplay, CgFont, or CgPixmap object, depending on what type of cursor(font, glyph, or pixmap) is being created. The method allocates the cursor andreturns a CgCursor object. Although there are different ways of creating cursors,once created all cursors have the same behavior. See the subsections that follow formore on creating cursors.

A cursor can be shown in a window by sending defineCursor: to the window,specifying the cursor to use.

Tip: Cursors can only be defined in the window of a widget, not the root windowof the screen. The widget can be any widget and is not restricted to the shellwidget of the application.

The cursor is reset to the default cursor by sending undefineCursor to the window.When the application is finished using the cursor, it should be released frommemory by sending freeCursor to the cursor. This process is illustrated by thefollowing code. (This example and the following cursor examples assume that theshell method answers a CwTopLevelShell widget.)

| window watch |window := self shell window.

"Create the cursor."watch := window display

createFontCursor: XCWatch.

"Display the cursor."window defineCursor: watch.(Delay forSeconds: 5) wait.window undefineCursor.watch freeCursor

Font cursorsFont cursors are easy to use. They are specified by a constant from the CgConstantspool dictionary. The previous example used a font cursor called watch:. In thefollowing example, a coffee mug cursor appears on the screen for 5 seconds:| window mug |window := self shell window.mug := window display createFontCursor: XCCoffeeMug.

Chapter 6. Common Graphics 103

Page 118: IBM Smalltalk: Programmer's Reference

window defineCursor: mug.(Delay forSeconds: 5) wait.window undefineCursor.mug freeCursor

The following table lists the available font cursors specified in the CgConstants pooldictionary:

Table 20. Font cursorsXCArrow XCBasedArrowDown XCBasedArrowUp XCBoatXCBogosity XCBottomLeftCorner XCBottomRightCorner XCBottomSideXCBottomTee XCBoxSpiral XCCenterPtr XCCircleXCClock XCCoffeeMug XCCross XCCrosshairXCCrossReverse XCDiamondCross XCDot XCDotboxXCDoubleArrow XCDraftLarge XCDraftSmall XCDrapedBoxXCExchange XCFleur XCGobbler XCGumbyXCHand1 XCHand2 XCHeart XCIconXCIronCross XCLeftbutton XCLeftPtr XCLeftSideXCLeftTee XCLlAngle XCLrAngle XCManXCMiddlebutton XCMouse XCNumGlyphs XCPencilXCPirate XCPlus XCQuestionArrow XCRightbuttonXCRightPtr XCRightSide XCRightTee XCRtlLogoXCSailboat XCSbDownArrow XCSbHDoubleArrow XCSbLeftArrowXCSbRightArrow XCSbUpArrow XCSbVDoubleArrow XCShuttleXCSizing XCSpider XCSpraycan XCStarXCTarget XCTcross XCTopLeftArrow XCTopLeftCornerXCTopRightCorner XCTopSide XCTopTee XCTrekXCUlAngle XCUmbrella XCUrAngle XCWatchXCXCursor XCXterm

Glyph cursorsGlyph cursors are created by using a character from an application-specified fontas a cursor. To create a glyph cursor, the application must have loaded a CgFont.Then a cursor object is created by sending thecreateGlyphCursor:sourceChar:maskChar: orcreateGlyphCursor:sourceChar:maskChar:foregroundColor:backgroundColor: message tothe CgFont object (the “source font”). In the following example, the same font andcharacter are used for the mask font and the mask character. The following codecreates and displays the @ sign as a cursor.

| window font cursor |window := self shell window.

"Create the cursor."font := window display loadFont: '8x13'.cursor := font

createGlyphCursor: fontsourceChar: $@ asIntegermaskChar: $@ asInteger.

font unloadFont.

"Display the cursor."window defineCursor: cursor.(Delay forSeconds: 5) wait.window undefineCursor.cursor freeCursor

@

104 IBM Smalltalk: Programmer’s Reference

Page 119: IBM Smalltalk: Programmer's Reference

Pixmap cursorsPixmap cursors are created by specifying two pixmaps: a shape pixmap and amask pixmap. The pixmaps must both have a depth of 1 (that is, 1 bit per pixel).The mask pixmap specifies at which pixels the cursor is opaque. Where the maskpixmap is 0, the background shows through. Where it is 1, the shape pixmapspecifies the color of the pixel. Where the shape pixmap is 1, the foreground color(black) is used. Where it is 0, the background color (white) is used. A mask pixmapof nil specifies that the cursor is opaque at all pixels. For more information oncreating and using pixmaps, see “Using pixmaps” on page 106.

In the following example, a CgPixmap is created by sending thecreateBitmapFromData:width:height: message to the drawable. Then this CgPixmapobject is sent the createPixmapCursor:x:y: orcreatePixmapCursor:foregroundColor:backgroundColor:x:y: message. Parameters passedto this method include an optional mask pixmap, and the x- and y-coordinates ofthe cursor’s hot spot. The hot spot is the point at which the cursor is centered overthe current pointer coordinates.

The following code creates and displays a pixmap cursor with the shape of a smallblack rectangle with a transparent interior. The cursor’s hot spot is in the center ofthe rectangle. Note that, in this case, the same pixmap is used both for the maskand to define the shape.

| window data pixmap cursor |window := self shell window.

"Create the cursor."data := #[

2r111111112r100000012r100000012r100000012r100000012r100000012r100000012r11111111].

pixmap := windowcreateBitmapFromData: datawidth: 8height: 8.

cursor := pixmapcreatePixmapCursor: pixmapx: 4y: 4.

pixmap freePixmap.

"Display the cursor."window defineCursor: cursor.(Delay forSeconds: 5) wait.window undefineCursor.cursor freeCursor

Changing the color of a cursorThe color of a cursor can be changed by sending the recolorCursor:backgroundColor:message to a CgCursor object. The color arguments are specified using CgRGBColorobjects. Class CgRGBColor is described in more detail in “Specifying colors” onpage 113. The following example illustrates how to recolor a font cursor so that theforeground is red and the background is blue.

Chapter 6. Common Graphics 105

Page 120: IBM Smalltalk: Programmer's Reference

| window cursor red blue |window := self shell window.

"Create and recolor the cursor."cursor := CgDisplay default createFontCursor: XCWatch.red := CgRGBColor red: 65535 green: 0 blue: 0.blue := CgRGBColor red: 0 green: 0 blue: 65535.cursor recolorCursor: red backgroundColor: blue.

"Display the cursor."window defineCursor: cursor.(Delay forSeconds: 5) wait.window undefineCursor.cursor freeCursor

Note: Some platforms, such as OS/2 PM and Windows, do not support colorcursors.

Platform cursorsYou can map font cursors to correspond to a platform’s built-in cursors by sendingmapFontCursor:platformCursor: to a CgDisplay object. In the following example, thesymbol #wait is defined as a key that maps to the current platform’s wait cursor.You can use any object as a key. The cursor is created using createFontCursor: anddisplayed in a window. Note that constants from the PlatformConstants pooldictionary are used.| window platform key cursor |window := self shell window.

"Determine what the current platform is and set the constant namespecifying the platform's wait cursor."platform := System subsystemType: 'CG'.(#('WIN' 'WIN32s' 'WIN-NT') includes: platform)

ifTrue: [key := 'IdcWait'].platform = 'PM' ifTrue: [key := 'SptrWait'].platform = 'X' ifTrue: [key := 'XCWatch'].

"Look up the constant and define a font cursor that maps to theplatform's wait cursor."window display

mapFontCursor: #waitplatformCursor: (PlatformConstants at: key asPoolKey).

"Create a font cursor which maps to the platform's wait cursor."cursor := window display

createFontCursor: #wait.

"Display the cursor."window defineCursor: cursor.(Delay forSeconds: 5) wait.window undefineCursor.

"Free the cursor."cursor freeCursor.

Using pixmapsA pixmap, represented by class CgPixmap, is an off-screen rectangular area ofpixels, located in graphics server memory. The depth, or number of bits per pixel,of a pixmap is specified when it is created. The depth is usually either 1 bit or thedepth of the window on which it will be displayed. Pixmaps with a depth of 1,representing monochrome graphics, are called bitmaps, but are also represented byclass CgPixmap. The memory representation of pixmaps is device dependent and ishidden from the application programmer. A pixmap is a kind of drawable,

106 IBM Smalltalk: Programmer’s Reference

Page 121: IBM Smalltalk: Programmer's Reference

meaning that it can be the destination of drawing operations. The followingmethods are used to create, free, and manipulate pixmaps, excluding drawingoperations.

createPixmapCreates a pixmap.

createPixmapFromBitmapDataCreates a pixmap and initialize it using the bitmap data provided.

freePixmapReleases a pixmap from memory.

getGeometryGets the dimensions of the pixmap.

createBitmapFromDataCreates a bitmap from the data provided.

readBitmapFileReads a bitmap file from disk in text format.

writeBitmapFileWrites a bitmap file to disk in text format.

Pixmaps are created by sending the createPixmap:height:depth: orcreatePixmapFromBitmapData:width:height:fg:bg:depth: message to a CgDrawable. ThecreatePixmap: message specifies the width, height, and depth of the pixmap. Adepth of 1 specifies a monochrome pixmap (a bitmap); a depth of 8 specifies a256-color pixmap. In most cases, the depth is set to either 1 or the depth of thewindow the pixmap will be displayed on.

Creating a pixmap using createPixmap:In this example, a pixmap is created with a width of 500, a height of 50, and adepth equal to that of the root window. depth is a CgWindow accessor method thatreturns the depth of the window.| window pixmap |window := CgWindow default.pixmap := window

createPixmap: 500height: 50depth: window depth

The contents of a newly created pixmap are undefined.

Freeing pixmapsThe application is responsible for releasing pixmaps (including bitmaps) frommemory when they are no longer required. Depending on their dimensions, theseobjects can take up large amounts of memory. Pixmaps are freed by sending thefreePixmap message to a CgPixmap object.pixmap freePixmap

Creating a pixmap using createPixmapFromBitmapData:In this example, a series of bits are passed to the pixmap creation routine alongwith width, height, foreground pixel, background pixel, and depth information.Wherever a 1 appears in the bitmap data, the foreground pixel is set in thepixmap. Wherever a 0 appears, the background pixel is set. After creating thepixmap, the example copies it onto the screen.

Chapter 6. Common Graphics 107

Page 122: IBM Smalltalk: Programmer's Reference

| gc window bits pixmap |gc := CgGC default.window := CgWindow default.

bits := #[2r11111111 2r111111112r00000110 2r011000002r00011000 2r000110002r01100000 2r000001102r10000000 2r00000001].

pixmap := windowcreatePixmapFromBitmapData: bitswidth: 16height: 5fg: window blackPixelbg: window whitePixeldepth: window depth.

pixmapcopyArea: windowgc: gcsrcX: 0srcY: 0width: 16height: 5destX: 10destY: 10.

pixmap freePixmap

Copying pixmaps to and from windowsThe copyArea:gc:srcX:srcY:width:height:destX:destY: method enables the contents ofany CgDrawable object (window or pixmap) to be copied to another CgDrawableobject. The receiver is the source drawable. The first argument is the destinationdrawable. The source and destination can be the same drawable. Additionalarguments include the graphics context, the source rectangle to be copied (srcX:,srcY:, width:, and height:), and the location in the destination (destX: and destY:) tobegin the copying operation.

How the bits are displayed is dependent on the raster operation function, eitherGXcopy or GXhighlight, that has been set in the graphics context. The rasteroperation specifies a binary function that is applied at each pixel, using the currentpixel values of the source and the destination to determine the new pixel value ofthe destination.

GXcopy sets the destination pixel value to the source pixel value; the currentdestination pixel value is ignored.

GXhighlight functions differently when copying areas than when drawing using theforeground or background CgGC components. In the latter case the foreground andbackground colors are exchanged in the destination. When copying areas,GXhighlight performs a binary exclusive-OR on the current source and destinationpixel values and sets the destination pixel value to the result. The example in thefollowing subsection illustrates copying a pixmap.

Getting pixmap geometryInformation about a CgDrawable (window or pixmap) can be obtained by sendingthe getGeometry: message to the drawable. In the following example a pixmap iscreated and its geometry is requested. Return parameters are provided for the root

108 IBM Smalltalk: Programmer’s Reference

Page 123: IBM Smalltalk: Programmer's Reference

window of the drawable, x, y, width, height, border width and depth information.The root window of a pixmap is the same as that for the window that was used tocreate the pixmap.| window pixmap rootReturn xReturn yReturn wReturn hReturn bwReturn dReturn |window := CgWindow default.pixmap := window

createPixmap: 500height: 50depth: window depth.

pixmapgetGeometry: (rootReturn := ReturnParameter new)xReturn: (xReturn := ReturnParameter new)yReturn: (yReturn := ReturnParameter new)widthReturn: (wReturn := ReturnParameter new)heightReturn: (hReturn := ReturnParameter new)borderWidthReturn: (bwReturn := ReturnParameter new)depthReturn: (dReturn := ReturnParameter new).

Transcript cr;show: 'Pixmap root: ', rootReturn value printString; cr;show: ' x: ', xReturn value printString;show: ' y: ', yReturn value printString;show: ' width: ', wReturn value printString;show: ' height: ', hReturn value printString; cr;show: ' borderWidth: ', bwReturn value printString;show: ' depth: ', dReturn value printString.

pixmap freePixmap

There are also convenience methods, width, height, and depth, for querying thegeometry of drawables.

Creating a bitmap from bitmap dataA CgPixmap of depth 1, called a bitmap, can be created and initialized from bitmapdata by sending the createBitmapFromData:with:height: message to a CgDrawable(window or pixmap). The message arguments are the bitmap data, its width, andits height. In the following example, an 8x8 bitmap is created using the data in bits.The bitmap forms a brick pattern when several copies are drawn side by side.| bits bitmap |bits := #[

2r111111112r000000012r000000012r000000012r111111112r000100002r000100002r00010000].

bitmap := CgWindow defaultcreateBitmapFromData: bitswidth: 8height: 8.

Creating stipples using bitmapsTo carry the example further, the bitmap in the previous example could be used tocreate a stipple drawing pattern. The pattern (a brick pattern) is created as abitmap. This bitmap is set as the stipple pattern in a graphics context using thesetStipple: method. The fill style, FillOpaqueStippled, and the stipple origin offsets (x:1 y: 2) are also set by sending the appropriate messages to the graphics context.The graphics context is then used to draw a filled rectangle.

Chapter 6. Common Graphics 109

Page 124: IBM Smalltalk: Programmer's Reference

| bits bitmap |bits := #[

2r11111111 2r00000001 2r00000001 2r000000012r11111111 2r00010000 2r00010000 2r00010000].

bitmap := CgWindow defaultcreateBitmapFromData: bitswidth: 8height: 8.

CgGC defaultsetFillStyle: FillOpaqueStippled;setTSOrigin: 1 tsYOrigin: 2;setStipple: bitmap;setForeground: CgWindow default blackPixel;setBackground: CgWindow default whitePixel.

CgWindow defaultfillRectangle: CgGC defaultx: 50y: 50width: 100height: 100.

CgGC default setFillStyle: FillSolid.bitmap freePixmap.

Writing bitmaps to filesBitmaps can be written to files by sending thewriteBitmapFile:width:height:xHot:yHot: message to the bitmap.

Tip: The bitmap file format only supports any CgPixmap of depth one. It is anerror to try to write a CgPixmap with a different depth.

The bitmap is written in X11 bitmap file format, which looks like C source code fora structure initialization. Parameters passed to the method include the file name,the width, the height, and the hot spot coordinates within the bitmap. A hot spot isuseful for cursor specifications. The write operation returns zero if successful, or anerror value if unsuccessful.| bits bitmap error |bits := #[

2r11111111 2r00000001 2r00000001 2r000000012r11111111 2r00010000 2r00010000 2r00010000].

bitmap := CgWindow defaultcreateBitmapFromData: bitswidth: 8height: 8.

error := bitmapwriteBitmapFile: 'brick'width: 8height: 8xHot: 0yHot: 0.

error = 0ifTrue: [Transcript cr; show: 'File write successful.']ifFalse: [Transcript cr; show: 'File write error: ',

error printString].bitmap freePixmap.

The file created by this example follows:#define brick_width 8#define brick_height 8#define brick_x_hot 0#define brick_y_hot 0static char brick_bits[] = {

0xff, 0x01, 0x01, 0x01, 0xff, 0x10, 0x10, 0x10};

110 IBM Smalltalk: Programmer’s Reference

Page 125: IBM Smalltalk: Programmer's Reference

Reading bitmaps from filesBitmaps can be read from files by sending thereadBitmapFile:widthReturn:heightReturn:bitmapReturn:xHotReturn:yHotReturn:message to any CgDrawable. Parameters passed to the method include the filename and ReturnParameter objects for the width, height, the actual bitmap, andthe x and y hot spot location. The value of any ReturnParameter object can beaccessed by sending it the value message.| error wReturn hReturn bReturn xReturn yReturn bitmap |error := CgWindow default

readBitmapFile: 'brick'widthReturn: (wReturn := ReturnParameter new)heightReturn: (hReturn := ReturnParameter new)bitmapReturn: (bReturn := ReturnParameter new)xHotReturn: (xReturn := ReturnParameter new)yHotReturn: (yReturn := ReturnParameter new).

error = 0ifTrue: [

Transcript cr; show: 'File read successful. ','Bitmap width: ', wReturn value printString,', height: ', hReturn value printString,', hotspot: ', (xReturn value @ yReturn value) printString.

bitmap := bReturn value.bitmap freePixmap]

ifFalse: [Transcript nextPutAll: 'File read error: ',error printString; cr].

Displaying bitmapsTo display a bitmap, the copyPlane:gc:srcX:srcY:width:height:destX:destY:plane: methodis used instead of copyArea:, which is used to copy between drawables having thesame depth. Like copyArea:, copyPlane: specifies the destination drawable, thesource rectangle, and the destination point. It has an extra argument that specifieswhich plane of the source drawable to use. When displaying bitmaps, thisargument should have a value of 1.

Unlike copyArea: which copies pixel values directly between the source anddestination drawables, copyPlane: expands the monochrome source bitmap to colorbefore performing the copy. Each pixel is copied as follows: If the source pixelvalue is 1, the foreground pixel value in the GC is combined with the destinationpixel value using the GC function, and the resulting pixel value is set in thedestination. If the source pixel value is 0, the background pixel value in the GC iscombined with the destination pixel value using the GC function, and the resultingpixel value is set in the destination.

The following example creates a brick pattern bitmap and copies it to the rootwindow using black as the foreground color and white as the background color:| gc window bits bitmap |gc := CgGC default.window := CgWindow default.

bits := #[2r111111112r000000012r000000012r000000012r111111112r000100002r000100002r00010000].

Chapter 6. Common Graphics 111

Page 126: IBM Smalltalk: Programmer's Reference

bitmap := windowcreateBitmapFromData: bitswidth: 8height: 8.

gcsetForeground: CgWindow default blackPixel;setBackground: CgWindow default whitePixel.

10 to: 50 by: 8 do: [:y |10 to: 50 by: 8 do: [:x |

bitmapcopyPlane: windowgc: gcsrcX: 0srcY: 0width: 8height: 8destX: xdestY: yplane: 1]].

bitmap freePixmap

Two additional methods, copyAreaMasked: and copyPlaneMasked:, use a mask tospecify transparency.

Tip: Note that Common Widgets provides a platform-independent way ofrequesting and releasing handles to shared system pixmaps in a pixmap cacheusing the getPixmap:foreground:background:,getPixmap:foreground:background:background:pallette:, and destroyPixmap: methodsof CgScreen. The pixmaps are created from images in an image cache.

Common Graphics image supportAn image is a two-dimensional array of pixels, with an associated palette definingthe pixel values to color mapping. An icon is a small image augmented withtranparency information. Modern graphical user interfaces require not only theability to draw lines, rectangles, arcs, and text, but also to display images andicons. The support for this in Xlib, on which the core Common Graphics classes arebased, is minimal, providing only a low-level mechanism (XImage) for transferringimage data between the application and drawables. Xlib’s color mechanism(Colormap) is also very low level. The XImage and Colormap mechanisms place aheavy burden on the application, leaving it responsible for parsing image fileformats, allocating the image’s palette of colors one color at a time, remapping theimage data to use the allocated pixel values for the colors, transferring theremapped data to a window or a pixmap whenever the image needs to beredrawn, and freeing color resources when the image is no longer required.

Common Graphics Image Support provides higher level abstractions for handlingimages, icons, colors, and palettes of colors. In keeping with the design philosophyof IBM Smalltalk, these abstractions are implemented using the highest levelcapabilities applicable on each platform. Image Support provides the followingadditional capabilities:v A color class, which allows the application to describe a colorv Palette classes, which allow the application to describe the set of colors it

requires or the set of colors associated with an imagev A device-independent representation of images, which allows the application to

create, modify, or display an image

112 IBM Smalltalk: Programmer’s Reference

Page 127: IBM Smalltalk: Programmer's Reference

v An icon class, which allows the application to describe an icon as a single objectcontaining both its image and its mask, simplifying the use of icons in labels,buttons, and other widgets, and in operations such as drag-and-drop

v Classes for reading and writing image and icon file formats, with severalstandard file formats supported

Specifying colorsTo specify colors, Common Graphics defines the following class:

CgRGBColorSpecifies a color using integer values in the range 0–65535 giving theintensities of the color primaries red, green, and blue.

There are three ways to create a CgRGBColor in Common Graphics as follows:v Specify the red, green, and blue intensities of the color with integers between 0

(full off) to 65535 (full on).v Specify a color name to look up in a database of colors.v Specify the RGB intensities in string form.

Specifying colors as RGB intensitiesTo specify a color by its red, green, and blue (RGB) intensities, send thered:green:blue: message to CgRGBColor with integer arguments specifying theintensities of the red, green, and blue components of the color. The values rangebetween 0 and 65535. Higher values add more of the color to the color mix. Lowervalues specify less color in the color mix. In the following example, color1 specifies50% gray and color2 specifies bright magenta.| color1 color2 |color1 := CgRGBColor red: 32767 green: 32767 blue: 32767.color2 := CgRGBColor red: 65535 green: 0 blue: 65535

The intensity: class method of CgRGBColor creates a gray-scale color, where the red,green, and blue intensities have the same value. In the following example, color1and color2 are equivalent:| color1 color2 |color1 := CgRGBColor intensity: 40000.color2 := CgRGBColor red: 40000 green: 40000 blue: 40000.

The red, green, and blue components of a CgRGBColor can be retrieved using thered, green, and blue methods.

Tip: The black and white class methods of CgRGBColor answer preexisting instancesof CgRGBColor representing black (all intensities = 0) and white (all intensities= 65535), respectively.

Specifying colors by nameCommon Graphics provides a selection of predefined named colors. The RGBvalues of these colors are stored in an internal database and can be referenced byname at any time by an application. A subset of these named colors is listed in thefollowing table:

Table 21. A subset of the predefined named colorsaquamarine black blueblue violet brown cadet bluecoral cornflower blue cyan

Chapter 6. Common Graphics 113

Page 128: IBM Smalltalk: Programmer's Reference

Table 21. A subset of the predefined named colors (continued)dark green dark olive green dark orchiddark slate blue dark slate gray dark turquoisedim gray firebrick forest greengold gray0 gray10gray100 gray20 gray30gray40 gray50 gray60gray70 gray80 gray90green green yellow indian redkhaki light blue light steel bluelime green magenta maroonmedium aquamarine medium blue medium forest greenmedium goldenrod medium orchid medium sea greenmedium slate blue medium spring green medium turquoisemedium violet red navy blue orangeorange red orchid pale greenpink plum redsalmon sandy brown sea greensienna sky blue slate bluespring green steel blue tanthistle turquoise violetviolet red wheat whiteyellow

The RGB values of a named color can be looked up in the color database bysending the lookupColor: message to a CgScreen. The method is passed the colorname to look up. The result is the corresponding CgRGBColor, if the color namewas found in the database, or nil if the name was not found.| color |color := CgScreen default lookupColor: 'orange'.Transcript cr; show: color printString.

This code prints a string such as aCgRGBColor(16rFFFF, 16rA5A5, 16r0000) on theTranscript Window. The actual values can differ, depending on the platform.

Parsing a color-specification stringA color-specification string consists either of a color name or a pound character (#)followed by a 3-, 6-, or 12-hex digit specification of the color’s red, green, and blueintensities. The following examples specify various approximations of the colormagenta: ‘magenta’, ‘#F0F’, ‘#FF00FF’, ‘#FFFF0000FFFF’. A color-specification stringcan be parsed for the RGB values it specifies by sending the parseColor: message toa CgScreen with the color-specification string as the argument. The result is thecorresponding CgRGBColor, if the string was successfully parsed, or nil if the stringcould not be parsed. If the specification string is a color name, the result is thesame as using lookupColor:.| color |color := CgScreen default parseColor: '#300050008000'.Transcript cr; show: color printString.

The preceding code prints the string:aCgRGBColor(16r3000, 16r5000, 16r8000).

Using palettesA palette defines a mapping from pixel values to colors. Palettes have twocommon uses:

114 IBM Smalltalk: Programmer’s Reference

Page 129: IBM Smalltalk: Programmer's Reference

v Specifying a set of colors that an application requires. The palette is selected intoa shell window before any drawing occurs, to ensure that its colors are availablefor later drawing requests. A shell window has exactly one palette associatedwith it. This palette is called the selected palette. When drawing is done in awindow, the foreground and background values in the CgGC are used as indicesinto the selected palette.

v Specifying the mapping from pixel values to colors in an image. Images areoften represented using 8 or fewer bits per pixel. In these cases, a palette definesthe colors corresponding to each pixel value in the image. Images using 16, 24,or more bits per pixel typically encode colors directly in the pixel values. In a24-bit-per-pixel image, one byte is used to encode each of the primary (red,green, or blue) intensities. In these cases the palette defines which bits in a pixelvalue map to each color primary.

Common Graphics defines the following palette classes:

CgPaletteAbstract superclass of CgIndexedPalette and CgDirectPalette.

CgIndexedPaletteDefines a pixel-value-to-color mapping as an array of colors, indexed by0-based pixel values. There is no restriction on the size of the palette (sizesof 2, 16, and 256 are often encountered in standard image formats). Colorsare undefined for pixel values not in the palette. A drawable can select aCgIndexedPalette but not a CgDirectPalette.

CgDirectPaletteDefines a pixel-value-to-color mapping that encodes colors directly in pixelvalues. The palette specifies which bits in a pixel value correspond to eachof the RGB primaries. Only the specified bits are used when doingconversions; other bits in a pixel value are ignored. A CgDirectPalettecannot be selected in a drawable. It is used only to specify thepixel-value-to-color mapping of images using direct pixel values. Thefollowing sections describe ways of selecting a CgDirectPalette, in order todisplay images using direct pixel values.

The default paletteFor applications with minimal color requirements, a default palette is providedthat contains 16 colors. The following table gives the pixel-value-to-color mappingof the default palette.

Table 22. Pixel-value-to-color mapping for the default palette

Pixel value Color Pixel value Color

0 black 1 dark red

2 dark green 3 dark yellow

4 dark blue 5 dark magenta

6 dark cyan 7 light gray

8 gray 9 red

10 green 11 yellow

12 blue 13 magenta

14 cyan 15 white

Chapter 6. Common Graphics 115

Page 130: IBM Smalltalk: Programmer's Reference

All windows have the default palette selected unless the application has selected adifferent palette. Use of the default palette has some key advantages:v It minimizes color resource allocation, leaving more colors available to other

applications that require them.v It minimizes the amount of redrawing that needs to be done when windows

change ordering and when color resource allocations are made by otherapplications.

Some platforms, such as OS/2 and Windows, provide an operating system defaultpalette containing some or all of these colors. On these platforms, the colors in theCommon Graphics default palette use the same color intensities as thecorresponding colors in the operating system default palette in order to minimizecolor resource allocation.

Tip: The default palette is retrieved by evaluating CgIndexedPalette default.

Creating indexed palettesIf the default palette does not satisfy the application’s color requirements, theapplication can create its own indexed palette by using the colors: class method. Inthe following example, a palette with 5 different levels of gray, from black to whiteis created:| colors palette |(colors := Array new: 5)

at: 1 put: (CgRGBColor intensity: 16r0000);at: 2 put: (CgRGBColor intensity: 16r1FFF);at: 3 put: (CgRGBColor intensity: 16r7FFF);at: 4 put: (CgRGBColor intensity: 16rBFFF);at: 5 put: (CgRGBColor intensity: 16rFFFF).

palette := CgIndexedPalette colors: colors

The following example creates a palette using named colors:| names colors palette |names := #('black' 'white' 'red' 'green' 'blue' 'brown' 'aquamarine' 'pink').colors := names collect: [:name |

CgScreen default lookupColor: name].palette := CgIndexedPalette colors: colors

From pixel values to colors and backAs described earlier, a palette defines a mapping from pixel values to colors. Pixelvalues are integers between 0 and n-1, where n is the number of colors defined bythe palette.

To find the color corresponding to a given pixel value, the at: message is sent tothe palette with the pixel value as the argument. In the following example, thepalette has three colors and so defines colors for pixel values between 0 and 2inclusive:| colors palette |colors := Array

with: (CgRGBColor red: 0 green: 0 blue: 0)with: (CgRGBColor red: 16rFFFF green: 0 blue: 0)with: (CgRGBColor red: 16rFFFF green: 16rFFFF blue: 16rFFFF).

palette := CgIndexedPalette colors: colors.

palette at: 0==> aCgRGBColor(16r0000, 16r0000, 16r0000)

116 IBM Smalltalk: Programmer’s Reference

Page 131: IBM Smalltalk: Programmer's Reference

palette at: 1==> aCgRGBColor(16rFFFF, 16r0000 16r0000)

palette at: 2==> aCgRGBColor(16rFFFF, 16rFFFF, 16rFFFF)

palette at: 3==> aCgRGBColor(16r0000, 16r0000, 16r0000)

The last expression illustrates that if the palette does not define a color for a givenpixel value, the at: method answers black, that is, a CgRGBColor with intensities of0.

It is also possible to find the pixel value corresponding to a given color in a paletteby using the nearestPixelValue: message. This message answers the pixel value forthe color in the palette that most closely matches the given color, as the followingexample illustrates. The exact algorithm used for matching colors is described inthe specification for CgPalette>>nearestPixelValue:.| colors palette |colors := Array

with: (CgRGBColor red: 0 green: 0 blue: 0)with: (CgRGBColor red: 16rFFFF green: 0 blue: 0)with: (CgRGBColor red: 16rFFFF green: 16rFFFF blue: 16rFFFF).

palette := CgIndexedPalette colors: colors.

palette nearestPixelValue: (CgRGBColor red: 0 green: 0 blue: 0)==> 0

palette nearestPixelValue: (CgRGBColor red: FFFF green: 0 blue: 0)==> 1palette nearestPixelValue: (CgRGBColor red: FFFF green: FFFF

blue: FFFF)==> 2

palette nearestPixelValue: (CgRGBColor red: BFFF green: 0 blue: 0)==> 1

The nearestColor: message answers the color in the palette that most closelymatches the given color. It is equivalent to looking up the color in the palette usingat: after getting the nearest pixel value using nearestPixelValue:.| colors palette |colors := Array

with: (CgRGBColor red: 0 green: 0 blue: 0)with: (CgRGBColor red: 16rFFFF green: 0 blue: 0)with: (CgRGBColor red: 16rFFFF green: 16rFFFF blue: 16rFFFF).

palette := CgIndexedPalette colors: colors.

palette nearestColor: (CgRGBColor red: 0 green: 0 blue: 0)==> (CgRGBColor red: 0 green: 0 blue: 0)

palette nearestColor: (CgRGBColor red: FFFF green: 0 blue: 0)==> (CgRGBColor red: FFFF green: 0 blue: 0)

palette nearestColor: (CgRGBColor red: FFFF green: FFFFblue: FFFF)

==> (CgRGBColor red: FFFF green: FFFF blue: FFFF)

palette nearestColor: (CgRGBColor red: BFFF green: 0 blue: 0)==> (CgRGBColor red: FFFF green: 0 blue: 0)

Selecting and drawing with palettesThis section describes how to select palettes and how to draw using palettes.

Chapter 6. Common Graphics 117

Page 132: IBM Smalltalk: Programmer's Reference

Selecting a paletteBefore you can draw using the colors of a given palette, the palette must first beselected in the window of the application’s shell widget. This ensures that thepalette’s colors are available in the video hardware when the window is active.This is done using the setPalette: message.

If the default palette is to be used, the setPalette: message is not required, because itis selected by default when windows are created. Remember that CgIndexedPalettescan be selected in windows, not CgDirectPalettes.

The setPalette: message can be sent only to the window of a shell widget or to apixmap. It is an error to send setPalette: to other windows. The shell window’spalette is inherited by all child windows of the shell window.

Tip: The size of selected palettes should be kept as small as possible, to minimizecolor resource allocation. This gives other applications a better chance ofdrawing with their preferred colors.

The following example illustrates how to select a palette. This assumes that theshell message answers the CwTopLevelShell widget of the application (see “Shellwidgets” on page 158 for more information on shell widgets).| names colors color palette |names := #('black' 'white' 'red' 'green' 'blue' 'brown' 'aquamarine' 'pink').colors := Array new: names size.1 to: names size do: [:i |

color := self shell screen lookupColor: (names at: i).color isNil ifTrue: [self error: 'Color not found.'].colors at: i put: color].

palette := CgIndexedPalette colors: colors.self shell window setPalette: palette

Retrieving the selected paletteThe selected palette can be retrieved using the getPalette message.

The getPalette message can be sent to any drawable. If getPalette is sent to awindow that is not a shell window, the palette of the shell window is answered.

Drawing with palettesTo use a color specified by the selected palette, the corresponding pixel value is setin the graphics context foreground or background component. For example, thefollowing code draws a blue-filled rectangle, assuming the palette in the previousexample is selected. This code assumes that the drawable message answers thewindow of a CwDrawingArea widget (which is a child of the shell widget used inthe previous example).| gc |gc := self drawable

createGC: Nonevalues: CgGCValues new.

"Blue has a pixel value of 4 in the palette."gc setForeground: 4.self drawable

fillRectangle: gc x: 0 y: 0 width: 100 height: 50.gc freeGC

Alternatively, the getPalette and nearestPixelValue: methods can be used to find theappropriate pixel value.

118 IBM Smalltalk: Programmer’s Reference

Page 133: IBM Smalltalk: Programmer's Reference

| gc palette pixelValue |gc := self drawable

createGC: Nonevalues: CgGCValues new.

palette := self drawable getPalette.

pixelValue := palettenearestPixelValue: (self shell screen lookupColor: 'blue').

gc setForeground: pixelValue.self drawable

fillRectangle: gc x: 0 y: 0 width: 100 height: 50.gc freeGC

Drawing in black and whiteIf drawing is done in black or white, the blackPixel and whitePixel methods ofCgDrawable can be used to determine the pixel value to use for the selected palette.

The blackPixel and whitePixel methods of CgDrawable answer the pixel value of thecolor closest to black and white, respectively, in the drawable’s selected palette.

Drawing in pixmaps using palettesDrawing in pixmaps requires special consideration when using palettes other thanthe default palette.

When a CgPixmap is first created using createPixmap:, the default palette is selectedin the pixmap, not the palette of receiver of the createPixmap: message. The receiveris only used to specify the screen and compatible depths of the pixmap. Becausethe receiver might not be the intended destination of a copy operation using thepixmap, the receiver’s palette is not selected in the pixmap.

The palette of the window in which the pixmap is to be displayed must be selectedin the pixmap before drawing is done. This is required so that thepixel-value-to-color mapping of the pixmap is the same as that of the destinationwindow. If this is not done, the pixel-value-to-color mappings for the pixmap andthe destination window will be different, and the results will not be what isexpected when the pixmap is copied to the window.

The following code shows the correct way to draw in a pixmap using a paletteother than the default palette. The code assumes that the shell method answers theCwTopLevelShell widget and that the drawingArea method answers theCwDrawingArea widget in which the pixmap will be displayed.| shellWindow destWindow colors color palette pixmap gc |shellWindow := self shell window.destWindow := self drawingArea window.

"Create the palette."colors := Array new: 16.0 to: 15 do: [:i |

color := CgRGBColor red: 65535 * i // 15 green: 0 blue: 0.colors at: i + 1 put: color].

palette := CgIndexedPalette colors: colors.

"Select the palette in the shell window."shellWindow setPalette: palette.

"Create the pixmap and select the palette in it."pixmap := destWindow

createPixmap: 320 height: 50 depth: destWindow depth.pixmap setPalette: palette.

"Draw vertical bars in increasing intensities of red in the pixmap."gc := pixmap

createGC: Nonevalues: nil.

Chapter 6. Common Graphics 119

Page 134: IBM Smalltalk: Programmer's Reference

0 to: 15 do: [:i |gc setForeground: i.pixmap

fillRectangle: gc x: i * 20 y: 0 width: 20 height: 50].

"Copy the pixmap to the destination window."pixmap

copyArea: destWindow gc: gc srcX: 0 srcY: 0 width: 320 height: 50destX: 0 destY: 0.

"Free the gc and pixmap."gc freeGC.pixmap freePixmap

Direct palettesDirect palettes, represented by the class CgDirectPalette, specify apixel-value-to-color mapping for pixel values that directly encode colors. They areused primarily in bitmapped images with 16 or more bits per pixel. A direct palettespecifies which bits of a pixel value correspond to each of the color primaries. Thiscorrespondence is defined by three nonoverlapping bit masks.

For example, an image with 24 bits per pixel directly encodes each pixel’s color inthe corresponding pixel value with 8 bits for each of the primary color (red, green,and blue). The following code creates a CgDirectPalette where the low-order byte ofa 24-bit pixel value gives the intensity of red, the next highest byte gives theintensity of green, and the high byte gives the intensity of blue.| palette |palette := CgDirectPalette

redMask: 16rFFgreenMask: 16rFF00blueMask: 16rFF0000

The at:, nearestPixelValue:, and nearestColor: methods described for indexed palettesare also applicable to CgDirectPalettes. The following example illustrates the use ofat: on the palette created above:palette at: 16r000000==> aCgRGBColor(16r0000, 16r0000, 16r0000)

palette at: 16rFFFFFF==> aCgRGBColor(16rFFFF, 16rFFFF, 16rFFFF)

palette at: 16r1F3F7F==> aCgRGBColor(16r7F7F, 16r3F3F, 16r1F1F)

Note: The pixel values in this case use 8 bits (0–255) each for red, green, and blue,whereas CgRGBColors use 16 bits (0–65535). The red component of the pixelvalue in the last example is 16r7F. To convert this to 16 bits it is multipliedby 65535 and divided by 255 giving 16r7F7F.

Device-independent imagesConceptually, an image is a two-dimensional array of colors. For storage efficiency,colors in an image are usually encoded as discrete pixel values with a fixednumber of bits for each pixel value. There are two common ways in which colorsare encoded as pixel values. In the first kind of encoding, the image is restricted toa small set of colors (256 or less). This set is ordered and the pixel values aretreated as indices into the list of colors. This encoding requires 8 bits or fewer perpixel. In the second kind of encoding, colors are encoded directly in the pixelvalues. For example, the red, green, and blue intensities of a color can be encodedas values in the range 0 to 255, requiring 8 bits for each primary and therefore 24bits for the whole pixel value. For both encodings a palette is required to definethe pixel-value-to-color mapping.

120 IBM Smalltalk: Programmer’s Reference

Page 135: IBM Smalltalk: Programmer's Reference

Common Graphics provides a class, CgDeviceIndependentImage, that defines adevice-independent representation of uncompressed bitmap images with 1, 4, 8, or24 bits per pixel. The image data format is made public, allowing it to beefficiently manipulated by applications. The same data format is used on allplatforms. The data format is as follows:v Scanlines are ordered from top (scanline 0) to bottom (scanline height-1).v The number of bytes representing a scanline is rounded up to an integral

multiple specified on image creation (usually 1, 2, or 4 bytes).v In images of depth 1 or 4, the pixels are ordered in each byte from left to right

starting at the most significant bit of the byte.v In images of depth greater than 8, the bytes comprising the pixel value are

ordered with the most significant byte first.

Device-independent images are created in one of two ways:v Created by the application using application-defined datav Loaded from a file

The following section describes how to create an image using application-defineddata. Image file formats are described in a later section.

Creating and manipulating imagesTo create a blank image, use the width:height:depth:palette: class method ofCgDeviceIndependentImage. The image data is initialized to all zeros. The followingexample shows how to create a 100-by-50 pixel gray-scale image with 8 bits perpixel. Because the palette specifies black for pixel value 0, the image is initially allblack.| colors color palette image line gc |colors := Array new: 256.0 to: 255 do: [:i |

color := CgRGBColor intensity: i * 65535 // 255.colors at: i + 1 put: color].

palette := CgIndexedPalette colors: colors.image := CgDeviceIndependentImage

width: 100height: 50depth: 8palette: palette.

The image attributes can be retrieved using the width, height, depth, palette, and datamethods of CgDeviceIndependentImage. The extent method answers the width andheight as a point.

To modify a single pixel value, use the putPixel:y:pixelValue: method. This methodtakes the x- and y- coordinates of the pixel and stores the new pixel value at thatlocation in the image.

Tip: As with the drawing methods described in previous sections, the x-andy-coordinates within images start at 0. The point 0@0 is at the top left cornerof the image, with the x-coordinate increasing from left to right, and they-coordinate increasing from top to bottom.

Continuing the previous example, the following code modifies the image data onepixel at a time. The resulting image has adjacent vertical stripes increasing inintensity from black at the left to white at the right.

Chapter 6. Common Graphics 121

Page 136: IBM Smalltalk: Programmer's Reference

0 to: 99 do: [:x |intensity := x * 255 // 99.0 to: 49 do: [:y |

image putPixel: x y: y pixelValue: intensity]].

A more efficient way of modifying image data is to use theputPixels:y:width:pixels:startIndex: method, which modifies a horizontal line of pixelsin a given scanline. The following code modifies the image data with the sameresult as the previous code, but is more efficient.line := ByteArray new: 100.0 to: 99 do: [:x |

line at: x + 1 put: x * 255 // 99].0 to: 49 do: [:y |

image putPixels: 0 y: y width: 100 pixels: line startIndex: 1].

Image data can be retrieved one pixel at a time using the getPixel:y: method. Ahorizontal line of pixels can be retrieved using getPixels:y:width:pixels:startIndex:. Anew image can be copied from an area of an existing image using the getSubImage:method and passing it a rectangle. The getPixel:... and putPixel: methods havegetColor: and putColor: equivalents that answer and accept CgRGBColor objectsrather than pixel values and use the image’s palette to convert between colors andpixel values.

Displaying imagesThe putDeviceIndependentImage:image:srcRect:destRect: method of CgDrawable is usedto display images. As with all drawing operations, the first argument is a CgGCspecifying the drawing attributes. The next argument is the image to display. Thelast two arguments are a source rectangle, specifying the area of the image todisplay, and a destination rectangle, specifying the area of the drawable in whichto display the source area. If the source and destination rectangles do not have thesame extent, the source area of the image is stretched or shrunk to fit in thedestination area. The image can be flipped by specifying a negative width orheight in the destination or source rectangles.

The following code displays the image created in the previous example, stretchedby a factor of two. To ensure that the required colors are available in the videohardware, the image’s palette is first selected in the window of the shell widget.This code assumes that the shell method answers the shell widget and that thedrawable method answers the window of the drawing area.

self shell window setPalette: image palette.gc := self drawable

createGC: Nonevalues: CgGCValues new.

self drawableputDeviceIndependentImage: gcimage: imagesrcRect: (0@0 extent: image extent)destRect: (20@20 extent: image extent * 2).

gc freeGC

+

+

Direct color imagesA direct-color image is an image in which the pixel values directly encode thecolors. Typically these images have 16 or more bits per pixel, with 24 bits per pixelbeing the most common. A CgDirectPalette is used to define the pixel-value-to-colormapping for direct-color images. Although CgDirectPalettes cannot be selected intoa CgDrawable, a CgIndexedPalette creation convenience method, colorCube:, can be

122 IBM Smalltalk: Programmer’s Reference

Page 137: IBM Smalltalk: Programmer's Reference

used to create an approximation of all possible colors. The colorCube: method takesan array of three integers specifying the number of levels of red (R), green (G), andblue (B) to include in the palette. The resulting palette has R*G*B entries. Thefollowing example creates and displays a 256-by-256 direct-color image with aconstant amount of red, with green increasing from top to bottom, and with blueincreasing from left to right. The resulting image has red at the top left corner,magenta at the top right, yellow at the bottom left, and white at the bottom right.The image is not shown here because it cannot be adequately reproduced in blackand white.| directPalette image pixel gc r g b |directPalette := CgDirectPalette

redMask: 16rFFgreenMask: 16rFF00blueMask: 16rFF0000.

image := CgDeviceIndependentImagewidth: 64height: 64depth: 24palette: directPalette.

r := 255.0 to: 63 do: [:y |

g := y * 255 // 63.0 to: 63 do: [:x |

b := x * 255 // 63.pixel := (b bitShift: 16) + (g bitShift: 8) + r.image putPixel: x y: y pixelValue: pixel]].

self shell window setPalette:(CgIndexedPalette colorCube: #(6 6 6)).

gc := self drawablecreateGC: Nonevalues: CgGCValues new.

self drawableputDeviceIndependentImage: gcimage: imagesrcRect: (0@0 extent: image extent)destRect: (20@20 extent: image extent).

gc freeGC

Tip: The putDeviceIndependentImage: method supports 1-, 4-, and 8-bit per pixelimages on all platforms. Twenty-four-bit images are supported on Windowsand OS/2 PM only. 16- and 32-bit images are not supported. In the 24-bitcase, the image’s palette must be a CgDirectPalette with the same masks asused in the example above. Note also that the display of 24-bit images onWindows is very slow unless it is directly supported by the video driver.

Copying images from a drawableA rectangular area of a drawable can be retrieved as an image using thegetDeviceIndependentImage: method of CgDrawable. This is primarily useful fortaking snapshots of the screen or specific windows. It can also be used, withputDeviceIndependentImage:, to stretch an area of a drawable.

The following example gets the contents of the entire default screen as an image:| screen rect image |screen := CgScreen default.rect := 0 @ 0 extent: screen width @ screen height.image := screen rootWindow getDeviceIndependentImage: rect

Chapter 6. Common Graphics 123

Page 138: IBM Smalltalk: Programmer's Reference

IconsIcons are small (typically not more than 32-by-32 pixels) images augmented with atransparency mask. They are often used in user interface (UI) components such asbuttons and labels, as well as in UI operations such as drag-and-drop. The classCgIcon represents an icon in Common Graphics. CgIcon objects can be createdusing application-defined data, by loading from a dynamic link library (DLL), byspecifying a system icon constant, or by specifying an operating system (OS) iconrepresentation.

Creating iconsThe fromImage:maskImage: class method creates a CgIcon given a shape image and amask image. Wherever there is a 1 in the mask image, the icon is opaque and thecorresponding pixel in the shape image is displayed. Wherever there is a 0 in themask image, the icon is transparent and the corresponding pixel in the shapeimage is ignored. Specifying nil as the mask image is equivalent to specifying amask image of all 1s (entirely opaque).

Tip: The palette of the mask image arugment of fromImage:maskImage: is ignoredwhen creating an icon. Transparency information is specified directly by themask data, with 1 indicating opaque and 0 indicating transparent.

An icon must be freed using the freeIcon method when it is no longer required, inother words, when it will no longer be drawn and it is not set as the value of anicon resource of any widget.

The following example creates an 8-by-8 monochrome icon of a white cross with ablack border. The icon is transparent outside of the white border. The icon is notfreed because it will be used in the next example.| palette shapeImage maskImage icon |palette := CgIndexedPalette colors:

(Arraywith: CgRGBColor black "0s are black"with: CgRGBColor white). "1s are white"

shapeImage := CgDeviceIndependentImagewidth: 8height: 8depth: 1palette: palettescanlinePad: 1data: #[

2r001111002r001001002r111001112r100000012r100000012r111001112r001001002r00111100].

maskImage := CgDeviceIndependentImagewidth: 8height: 8depth: 1palette: palette "The mask image palette is not used."scanlinePad: 1

data: #[2r001111002r001111002r111111112r11111111

124 IBM Smalltalk: Programmer’s Reference

Page 139: IBM Smalltalk: Programmer's Reference

2r111111112r111111112r001111002r00111100].

icon := CgIconfromImage: shapeImagemaskImage: maskImage

Drawing iconsThe drawIcon:x:y:icon: method of CgDrawable is used to draw CgIcon objects. Thefollowing code draws the icon, created in the previous example, at the top leftcorner of the screen. The icon is freed because it is no longer required.

CgWindow defaultdrawIcon: CgGC defaultx: 0y: 0icon: icon.

icon freeIcon

As with images, CgIcons have a platform- and device-independent datarepresentation. However, for speed, CgIcons are displayed using the operatingsystem’s representation of icons. On OS/2 PM the limit is 32x32 or 40x40,depending on the video driver. On Windows, the size of operating-system icons islimited to 32x32. If an icon is created larger than the maximum size on theseplatforms, it is clipped to the maximum size and only its top left corner is drawn.

The best icon size to use can be obtained by sending queryBestIconSize to theCgScreen. On Window and OS/2 PM this size is the maximum displayable iconsize. On X this size is only a suggestion, not a hard limit.

CgIcons are displayed using only the default palette colors. It is not necessary toselect a palette in the destination drawable. The drawIcon: method ignores theselected palette.

Loading icons from DLLsOn Windows and OS/2 platforms, CgIcons can be loaded from an icon resourcelinked into the virtual machine (VM) executable or another file. A platform-specificresource specifier object is used to identify the icon resource.

On OS/2, only integers are used as resource specifiers. On Windows, resourcespecifiers can be either strings (as in the previous example) or integers.

The following code illustrates how to load an icon resource from the VMexecutable on the Windows platform. Do this using the fromResource: class method:| icon |icon := CgIcon fromResource: 'APP_ICON'.CgWindow default

drawIcon: CgGC default x: 0 y: 0 icon: icon.icon freeIcon

The equivalent code for OS/2 is as follows:

Chapter 6. Common Graphics 125

Page 140: IBM Smalltalk: Programmer's Reference

| icon |icon := CgIcon fromResource: 1.CgWindow default

drawIcon: CgGC default x: 0 y: 0 icon: icon.icon freeIcon

To load an icon resource from a file other than the VM executable, use thefromResource:fileName: class method of CgIcon. The following examples load an iconfrom the VM executable, as above, but the file name is explicitly specified:"Windows"| icon |icon := CgIcon

fromResource: 'APP_ICON' fileName: 'abt.exe'.CgWindow default

drawIcon: CgGC default x: 0 y: 0 icon: icon.icon freeIcon

"OS/2"| icon |icon := CgIcon

fromResource: 1 fileName: 'abt.exe'.CgWindow default

drawIcon: CgGC default x: 0 y: 0 icon: icon.icon freeIcon

Using operating system iconsCommon Graphics provides two methods for creating a CgIcon given an operatingsystem icon representation. The fromOSIcon: class method creates a CgIcon given anoperating system icon. The fromSystem: class method is similar, but the operatingsystem icon is specified as a platform-specific system icon constant.

On OS/2 PM, operating system icons are represented by class OSHpointer. OnWindows, operating system icons are represented by class OSHicon.

Common Widgets provides a platform-independent way of requesting andreleasing handles to share system icons in an icon cache using thegetIcon:foregroundColor: and destroyIcon: methods of CgScreen.

Image and icon file formatsThere are many file formats used for storing images and icons. Common Graphicsprovides several classes for reading and writing standard file formats. Thefollowing image file formats are supported:

Table 23. Supported image file formats

Format Description

Windows BMP Native format for the Windows platform

PM BMP Native format for the PM platform

TIFF Portable format, supported by many tools on different platforms

PCX Common file format on PC platforms

The following icon file formats are supported:

Table 24. Supported icon file formats

Format Description

Windows ICO Native format for the Windows platform

126 IBM Smalltalk: Programmer’s Reference

Page 141: IBM Smalltalk: Programmer's Reference

Table 24. Supported icon file formats (continued)

Format Description

PM ICO Native format for the PM platform

The following table shows the class hierarchy that implements the file formatframework of Common Graphics. This framework provides methods to load andunload images and icons in these formats, to test whether a file has a given format,and to detect what the format of a given file is.

Table 25. File format class hierarchyClass Description.CgFileFormat Abstract file format class

CgIconFileFormat Abstract icon file format classCgPMICOFileFormat PM ICO file formatCgWinICOFileFormat Windows ICO file format

CgImageFileFormat Abstract image file format classCgPCXFileFormat PCX file formatCgPMBMPFileFormat PM BMP file formatCgTIFFFileFormat TIFF file formatCgWinBMPFileFormat Windows BMP file format

In addition to loading from files and unloading into files, Common Graphicsprovides methods to load from ByteArrays and unload into ByteArrays. Errorhandling methods are also provided. These methods are described in the followingsections.

Loading images from filesTo load an image from a file, the loadFromFileHandle:atOffset: message is sent to aninstance of the appropriate subclass of CgImageFileFormat. The first argument is aCfsFileDescriptor, opened for reading on the input file. The atOffset: argument is thenumber of bytes from the start of the file at which to start reading. The result is aCgDeviceIndependentImage if the file was successfully loaded, or nil if an erroroccurred.

The following example illustrates how to load a PCX image from a file namedmy-image.pcx:| format file image |format := CgPCXFileFormat new.file := CfsFileDescriptor open: 'my-image.pcx' oflag: ORDONLY.image := format loadFromFileHandle: file atOffset: 0.file close.|image

The loadFromFile: method takes a file name directly, saving the application fromhaving to explicitly open and close the file. The following code has the same resultas the previous example:| format image |format := CgPCXFileFormat new.image := format loadFromFile: 'my-image.pcx'.|image

Handling errorsIf an error occurs during a load, the loadFromFileHandle:atOffset: method answersnil. Another way to detect an error is to send the hasErrorOccurred message to the

Chapter 6. Common Graphics 127

Page 142: IBM Smalltalk: Programmer's Reference

format object (the instance of the CgFileFormat subclass). This method answers trueif an error occurred in the last operation, or false if no error occurred. To determinewhat the error was, the currentError and currentErrorString messages can be sent tothe format object. The currentError method answers an integer error code. ThecurrentErrorString method answers a String describing the error. The following tablelists the error codes and corresponding error strings.

Table 26. CgFileFormat error codes and error strings

Error code Error string

1 No errors

2 Error opening file

3 Invalid file handle

4 Invalid offset

5 Invalid array of ByteArrays

6 Invalid array of integer offsets into ByteArrays

7 Seek error

8 Write error

9 Read error

10 Read-only object encountered (attempt to unload into ByteArraymarked as read-only)

11 Memory allocation error

12 File format not supported

13 File is not of specified format

14 Compression type not supported

15 Unsupported aspect of the specified format encountered

16 Invalid extra info

The following example adds error handling to the previous example of loading aPCX file:| format image |format := CgPCXFileFormat new.image := format

loadFromFile: 'my-image.pcx'.format hasErrorOccurred

ifTrue: [self error: format currentErrorString]ifFalse: [|image]

Loading icons from filesTo load icons from a file, send loadFromFileHandle:atOffset: or loadFromFile: to aninstance of the appropriate subclass of CgIconFileFormat. Because the icon fileformats allow more than one icon to be stored in a file, these methods answer anarray of CgIcon objects if the file was successfully loaded, rather than a singleCgIcon object. As with the image file formats, nil is answered if an error occurred.The following example illustrates how to load the icons from a Windows ICO filenamed my-icons.ico. Only the first icon is answered.| format icons |format := CgWinICOFileFormat new.icons := format

128 IBM Smalltalk: Programmer’s Reference

Page 143: IBM Smalltalk: Programmer's Reference

loadFromFile: 'my-icons.ico'.format hasErrorOccurred

ifTrue: [self error: format currentErrorString].|icons first

Unloading images into filesTo unload an image into a file, the unload:intoFileHandle:atOffset: message is sent tothe appropriate CgImageFileFormat object. The method answers true if the imagewas successfully unloaded, or false if an error occurred. As with the load methods,the hasErrorOccurred, currentError, and currentErrorString methods can be used tohandle errors.

Note: Unloading does not modify the original object.

The following code unloads an image captured from the screen into a file namedimg-out.pcx using the PCX format:| screen rect image file format success |screen := CgScreen default.rect := 0 @ 0 extent: screen width @ screen height.image := screen rootWindow

getDeviceIndependentImage: rect.format := CgPCXFileFormat new.

file := CfsFileDescriptoropen: 'img-out.pcx'oflag: OCREAT | OTRUNC | OWRONLY.

success := formatunload: imageintoFileHandle: file atOffset: 0.

file close.success

ifFalse: [self error: 'Error unloading image']

The unload:intoFile: method takes a file name as an argument. It creates the file if itdoes not exist, or overwrites the file if it does exist. The following code has thesame effect as the previous example.| screen rect image format |screen := CgScreen default.rect := 0 @ 0 extent: screen width @ screen height.image := screen rootWindow

getDeviceIndependentImage: rect.format := CgPCXFileFormat new.(format unload: image intoFile: 'img-out.pcx')

ifFalse: [self error: 'Error unloading image']

Unloading icons into filesCgIcon objects are unloaded into files using the same methods as for images.However, as with the icon load methods, an array of CgIcons is given, rather than asingle CgIcon.

The following code unloads a single icon into a file in the Windows ICO format. Itassumes that the iconToUnload method answers the CgIcon to unload.| icons format |icons := Array with: self iconToUnload.format := CgWinICOFileFormat new.(format unload: icons intoFile: 'icon-out.ico')

ifFalse: [self error: 'Error unloading icon']

Chapter 6. Common Graphics 129

Page 144: IBM Smalltalk: Programmer's Reference

Unloading images and icons into ByteArraysIn addition to using files, Common Graphics allows images and icons to be loadedand unloaded using ByteArrays. The totalSizeBeforeUnload: method determines thenumber of bytes required to unload the image. Theunload:intoByteObjects:offsetsIntoByteObjects: method, which does the actualunloading, takes an array of ByteArrays and an array of Integer offsets. The offsetsspecify how many bytes to skip at the beginning of each ByteArray. The offsets canbe used, for example, to leave room for database record headers. As withunload:intoFile:, true is answered if the unload was successful, false if an erroroccurred.

The following code illustrates how to unload an image into an array of ByteArraysusing the PCX format. Each ByteArray is limited to a maximum size of 64K. Toillustrate how space is reserved for a database record header, 32 bytes are skippedat the beginning of each ByteArray.| image format headerSize maxSize imageSize numByteArrays byteArrays offsets |image := self imageToUnload.format := CgPCXFileFormat new.headerSize := 32.maxSize := 65536. "64K"imageSize := format totalSizeBeforeUnload: image.

"Determine total size."numByteArrays := imageSize // (maxSize - headerSize) + 1.byteArrays := OrderedCollection new.1 to: numByteArrays do: [:i|

byteArrays add: (ByteArray new: maxSize)].byteArrays := byteArrays asArray.

offsets := Array new: byteArrays size.offsets atAllPut: headerSize.(format

unload: imageintoByteObjects: byteArraysoffsetsIntoByteObjects: offsets)ifFalse: [self error: format currentErrorString]

Icons are unloaded into ByteArrays in a similar fashion. The only difference is thatthe totalSizeBeforeUnload: and unload:intoByteObjects:offsetsIntoByteObjects: methodsfor the icon file formats take an array of CgIcons rather than an image.

Loading images and icons from ByteArraysTo load images or icons from ByteArrays, use the loadFromByteObjects:-offsetsIntoByteObjects: method.

The following code illustrates how to load a PCX format image from an array ofByteArrays. It assumes that the imageStorage method answers the array ofByteArrays created in the previous example.| format headerSize byteArrays offsets image |format := CgPCXFileFormat new.headerSize := 32.byteArrays := self imageStorage.offsets := Array new: byteArrays size.offsets atAllPut: headerSize.

image := formatloadFromByteObjects: byteArraysoffsetsIntoByteObjects: offsets.

image isNilifTrue: [self error: format currentErrorString]

130 IBM Smalltalk: Programmer’s Reference

Page 145: IBM Smalltalk: Programmer's Reference

Icons are loaded from ByteArrays in a similar fashion. As with loadFromFile:, theloadFromByteObjects:offsetsIntoByteObjects: method for icon file formats answers anarray of CgIcons.

Determining the format of a fileCommon Graphics provides methods to do the following:v Determine whether a file has a given file formatv Determine which format a given file has

The formatMatchesFileHandle:atOffset: class method answers true if the given filematches the receiver’s format, false if it does not. For example, the following codetests whether the file named my-image.pcx is actually a PCX image file:| file |file := CfsFileDescriptor open: 'my-image.pcx' oflag: ORDONLY.(CgPCXFileFormat formatMatchesFileHandle: file atOffset: 0)

ifTrue: [Transcript cr; show: 'Format matches.']ifFalse: [Transcript cr; show: 'Format does not match.'].

file close

The formatMatchingFileHandle:atOffset:ifNone: class method determines which formatmatches the given file. It answers the appropriate file format class if a matchingformat was found. If one was not found, the block passed as the last argument isevaluated and its result is answered. The following code determines the format ofthe file named my-image.pcx:| file formatClass |file := CfsFileDescriptor open: 'my-image.pcx' oflag: ORDONLY.formatClass := CgImageFileFormat

formatMatchingFileHandle: fileatOffset: 0ifNone: [file close. |self error: 'No matching format found'].

file close.Transcript cr; show: 'Matching format: ', formatClass printString

When the input is an array of ByteArrays, use the formatMatchesByteObjects:-offsetsIntoByteObjects: and formatMatchingByteObjects:offsetsIntoByteObjects:- ifNone:class methods.

Extra file format informationImage file formats often specify more information than is represented byCgDeviceIndependentImage. For example, image data in BMP format can either beuncompressed or compressed using run-length encoding. The application mightneed to know the data compression technique used by a loaded image’s file so thatthe image can later be unloaded in the same way. The image file format objectspreserve this extra information as part of their state when an image is loaded, anduse this information when an image is unloaded.

Each of the CgFileFormat classes provides format-specific methods to access andchange the extra information. These methods are outlined in the following sections.

Following these sections, an example illustrates how to manipulate extrainformation.

PCXThe following methods provide extra information preserved and used by theCgPCXFileFormat class:hRes Horizontal resolution of device

Chapter 6. Common Graphics 131

Page 146: IBM Smalltalk: Programmer's Reference

paletteInfoHow to interpret palette (color or gray scale)

version Format version numbervRes Vertical resolution of device

PM BMPThe following methods provide extra information preserved and used by theCgPMBMPFileFormat class:colorEncode

Color encoding schemecolorsUsed

Number of colors used by the imagecompression

Data compression algorithm usedident Application specific identifierimportantColors

Number of colors important for displaying imagerecording

Recording algorithm usedrendering

Halftoning algorithm usedresUnits

Units of measure for xRes and yRessize1 Halftoning correction factorsize2 Halftoning correction factorxRes Horizontal resolution of deviceyRes Vertical resolution of device

TIFFThe following methods provide extra information preserved and used by theCgTIFFFileFormat class:colorScheme

Color scheme (gray scale, palette, RGB)compression

Data compression algorithm usedpredictor

Prediction method, used with some types of compression

Windows BMPThe following methods provide extra information preserved and used by theCgWinBMPFileFormat class:compression

Data compression algorithm usedimportantColors

Number of colors important for displaying imagepelsPerMeter

Horizontal and vertical resolution of device

ExampleThe following code illustrates how to unload an image in Windows BMP format,using run-length encoding of the data if the image has a depth of 4 or 8. Thedevice resolution and number of important colors are also specified.| image format |image := self imageToUnload.format := CgWinBMPFileFormat new.format compression: 0. "No compression by default."image depth = 8

ifTrue: [format compression: 1]. "RLE8 compression."

132 IBM Smalltalk: Programmer’s Reference

Page 147: IBM Smalltalk: Programmer's Reference

image depth = 4ifTrue: [format compression: 2]. "RLE4 compression."

format importantColors: (1 bitShift: image depth) - 3."All but 3 colors are important. Approx. 75 dots per inch."format pelsPerMeter: 3000 @ 3000.format unload: image intoFile: 'img-out.bmp'

Resource management summaryMost Common Graphics resources need to be explicitly deallocated when nolonger required, otherwise operating system resources are lost and will eventuallyrun out. This includes fonts, pixmaps, color cells, graphics contexts, cursors, andicons.

Often the best place to deallocate graphics resources is in a destroy callbackhandler for the drawing area widget in which graphics are being drawn. See“Drawing area widgets” on page 164 for more information.

The following table summarizes when and how to free graphics objects allocatedby the application:

Table 27. Graphics object freeing reference

Graphics object Summary

CgCursor Obtained using: CgDisplay>>createFontCursorCgPixmap>>createPixmapCursorCgFont>>createGlyphCursor

Freed using: CgCursor>>freeCursor

When to free: When it will no longer be set as the cursor forany window (usingCgWindow>>setWindowCursor:). Cursors arenormally allocated when an application isopened and freed when it is closed.

CgDeviceIndepen-dentImage

Obtained using: CgDeviceIndependentImage class>>width:height:depth:palette:width:height:depth:palette:scanlinePad:data:

Freed using: <None>

When to free: Images do not need to be explicitly freed.

CgDirectPalette Obtained using: CgDirectPalette class>>redMask:greenMask:blueMask:

Freed using: <None>

When to free: Direct palettes do not need to be explicitlyfreed.

CgGC Obtained using: CgWindow>>createGC:

Freed using: CgGC>>freeGC

When to free: When it is no longer required for graphicsoperations on the drawable for which it wascreated. It is typically freed when a window isclosed by hooking the destroy callback.

Chapter 6. Common Graphics 133

Page 148: IBM Smalltalk: Programmer's Reference

Table 27. Graphics object freeing reference (continued)

Graphics object Summary

CgFont Obtained using: CgDisplay>>loadFont:

Freed using: CgFont>>unloadFont

When to free: When it is no longer required for graphicsoperations on any drawable. It is typically freedwhen no more text will be drawn with that font.The font can remain selected in a CgGC but if arequest using the font is made, such as drawinga string, the results are undefined.

CgFontStruct Obtained using: CgDisplay>>loadQueryFont:CgFont>>queryFont

Freed using: CgFontStruct>>freeFont

When to free: When it is no longer required for informationabout its font and when no more text will bedrawn with that font. The same conditions asfor freeing CgFont apply.

CgIndexedPalette Obtained using: CgIndexedPalette class>>entries:colors:

Freed using: <None>

When to free: Indexed palettes do not need to be explicitlyfreed.

CgIcon Obtained using: CgIcon class>>fromImage:maskImage:fromOSIcon:fromResource:fromResource:fileName:fromResources:fromResources:fileName:fromSystem:width:height:depth:palette:shapePad:-

shapeData:maskPad:maskData:

Freed using: CgIcon>>freeIcon

When to free: When it will no longer be drawn and it is nolonger set as an icon resource of a widget.

CgPixmap Obtained using: CgDrawable>>createPixmap:createBitmapFromData:createPixmapFromBitmapData:readBitmapFile:

Freed using: CgPixmap>>freePixmap

When to free: When it will no longer be used for drawing on,it will no longer be used as the source for acopy operation, and it will no longer be used asa tile or stipple pattern in a GC.

CgArc, CgCharStruct,CgFontProp,CgGCValues,CgRGBColor,CgSegment,CgTextItem

Obtained using: <Misc>

Freed using: <None>

When to free: These objects are informational data structuresonly, and need not be explicitly freed.

134 IBM Smalltalk: Programmer’s Reference

Page 149: IBM Smalltalk: Programmer's Reference

Chapter 7. Common Widgets

The Common Widgets (CW) classes and methods subsystem enables developers todesign and build graphical user interfaces using an application programminginterface (API) based on OSF/Motif. Using the Common Widgets subsystem,developers can do the following:v Create individual widgets, including buttons, lists, text, menus, and dialog boxesv Create compound widget structures by combining individual widgetsv Specify the positioning of widgets relative to each otherv Program operations to occur in response to user actions

These capabilities are described later in this chapter. In addition, this chapterexplains how the system is based on OSF/Motif, gives an overview of theCommon Widgets class hierarchy, and describes the basic approach for building anapplication.

OSF/Motif compatibilityThe Common Widgets subsystem is based on the OSF/Motif C programminginterface standard. This section is of interest to developers familiar with Motif. Itdescribes the strategy used to translate Motif C types and functions to Smalltalkclasses and methods. Experienced Motif developers will be able to apply theirknowledge of the C programming interface directly when programming CommonWidgets.

Smalltalk classes have been created for most C data types. These classes are namedby prefixing the Motif data structure name with ‘Cw’ (after first removing any X,Xt, or Xm prefix). For example, the Motif data structure Widget is represented bythe Smalltalk class CwWidget.

Motif functions have corresponding Smalltalk methods. To understand thismapping, consider the following function XmListSelectItem:void XmListSelectItem (widget, item, notify)Widget widget;XmString item;Boolean notify;

In the Common Widgets subsystem, the XmListSelectItem call has been mapped toan instance method of the class CwList:selectItem: item notify: notify

The C type Widget, in this case, is mapped to the Smalltalk class CwList becausethe XmListSelectItem function applies only to list widgets. The XmList prefix hasbeen stripped off, because such C-specific prefixing is unnecessary in Smalltalk.

Where C types have appropriate corresponding Smalltalk base classes, C types aremapped to these. For example, the C type XmString is mapped to the Smalltalkclass String, and the C type Boolean is mapped to the Smalltalk class Boolean.

Common Widgets class hierarchyThis section describes the Common Widgets class hierarchy and provides anoverview of the functionality provided by each class.

© Copyright IBM Corp. 1994, 2000 135

Page 150: IBM Smalltalk: Programmer's Reference

A is a user interface component, such as a top-level window (shell), button or list.A graphical user interface is built by creating a tree of widgets. Every widgetexcept the topmost widget in a tree has a parent widget. In the user interface achild widget appears on top of the parent and is normally prevented fromdrawing outside the bounds of its parent. Each parent widget is responsible forsizing and positioning its children. The parent-child relationship defines the widgettree. The topmost widget in the tree is called a shell widget. Shell widgets areresponsible for negotiating with the window manager for their position on thescreen, and for the various window decorations that they display, such as a title,border, or close box.

All Common Widgets are subclasses of one of the following classes:

CwPrimitiveA primitive widget has no children.

CwCompositeA composite widget can have zero or more children.

CwShellA shell widget has exactly one child.

Primitive widgets are the simplest building blocks in Common Widgets. Aprimitive widget is always the child of another widget. The following tableprovides brief descriptions of the CwPrimitive class and its subclasses. Classes initalics are abstract classes (they are never instantiated).

Note: The parent-child relationship is not the same as the class-subclassrelationship.

Table 28. Primitive hierarchyClass hierarchy ResponsibilityCwWidget Defines common behavior for all widgets

CwBasicWidget Defines common behavior for widgets implementeddirectly by the platform

CwPrimitive Defines common behavior for widgets that do not havechildren

CwArrowButton Displays an arrow buttonCwComboBox Combines a list and text area to provide a prompted entry

fieldCwLabel Displays a static label that can be a string, pixmap, or

iconCwCascadeButton Used as part of a menu system to trigger submenusCwDrawnButton Displays a button drawn by the applicationCwPushButton Displays a push button containing a string, pixmap, or

iconCwToggleButton Displays a button that has on and off state such as a radio

or check buttonCwList Displays a list of strings from which one or more can be

selectedCwScrollBar Displays a vertical or horizontal scroll barCwSeparator Displays a separator line, normally between menu itemsCwText Displays and provides editing capability for text

Composite widgets can have zero or more child widgets. A composite widget’schildren can include other composite widgets, primitive widgets, or both. Differentcomposite widgets provide various kinds of layout capabilities for arrangingchildren. The following table briefly explains the CwComposite class and itssubclasses. Classes in italics are abstract classes.

136 IBM Smalltalk: Programmer’s Reference

Page 151: IBM Smalltalk: Programmer's Reference

Table 29. Composite hierarchyClass hierarchy ResponsibilityCwWidget Defines common behavior for all widgets

CwBasicWidget Defines common behavior for widgets implementeddirectly by the platform

CwComposite Defines common behavior for widgets that contain childwidgets

CwBulletinBoard Allows application-defined child widget positioningCwCompositeBox Defines common behavior for CwMessageBox and

CwSelectionBoxCwMessageBox Provides a notification message, icon, and OK, Cancel,

and Help buttonsCwSelectionBox Provides a list of items to select, a text box showing the

selection, and OK, Cancel, Apply, and Help buttonsCwForm Provides a constraint-based mechanism for laying out

child widgetsCwDrawingArea Performs no child layout and provides an area for

performing graphic operationsCwFrame Provides an optionally labeled frame around its single

child widgetCwRowColumn Provides a mechanism for laying out child widgets in

rows or columnsCwScale Displays a numeric scale with a position indicatorCwScrolledWindow Allows a child widget to be scrolled using scrollbars

CwMainWindow Provides layout management for a menu bar andoptionally scrollable work area

Shell widgets provide the protocol between the application interface and thewindow manager. The following table provides brief descriptions of the CwShellclass and its subclasses. Classes in italics are abstract classes.

Table 30. Shell hierarchyClass hierarchy ResponsibilityCwWidget Defines common behavior for all widgets

CwBasicWidget Defines common behavior for widgets implementeddirectly by the platform

CwShell Defines common behavior for the top-level widgets ofwindows and dialogs

CwOverrideShell A pop-up window that bypasses window management,and normally appears on top of all other widgets

CwWMShell Defines common behavior for shell widgets that do notbypass window management

CwTopLevelShell Provides a normal window with standard appearance anddecorations

CwTransientShell A pop-up dialog window that does not bypass windowmanagement

CwDialogShell A pop-up window used to implement modal andmodeless dialog windows

Overview of Common Widgets user interface conceptsAll user interfaces have two directions of communication: from the application tothe user, and from the user back to the application. Using Common Widgets, thesetwo directions of communication work as follows:v The application creates and configures user interface components (widgets)

through the use of resources and functions, and expresses interest in receivingnotification of user actions by registering callbacks and event handlers.

Chapter 7. Common Widgets 137

Page 152: IBM Smalltalk: Programmer's Reference

v The user interface notifies the application of user actions by calling callbacks andevent handlers.

The next sections explain how widgets are created and configured, and howcallbacks and event handlers allow the application to react to user actions.

The parent-child widget treeA widget tree is created in a top-down manner. First a shell widget is created.Next, a single child widget, usually a subclass of CwComposite, is created as thechild of the shell. This process continues until the application has created all thewidgets in the tree.

In the following example, the widget tree for a graphics application window isshown. A CwTopLevelShell is created to interact with the window manager. ACwMainWindow is created as the single child of the shell. A CwForm is created asthe child of the main window. The CwForm is required to position aCwDrawingArea and a CwRowColumn, which are created as children of the form.Three CwPushButtons are created as children of the row-column widget.

CwDrawingArea

CwTopLevelShell

Appearance on screen

Widget tree

menu bar and work area

decorations and title bar

positions side by side

positions in column

a button

a button

a button

for drawing

CwMainWindow

CwForm

CwPushButton

CwPushButton

CwPushButton

CwRowColumn

The widget lifecycleFor a widget to appear on the user’s display, it must be created, managed,mapped, and realized. When a widget is no longer required, it is destroyed. Thesesteps are described in the following section.

1. Creating a widgetThe first step is to create the widget. When a widget is created, it is given a name,and its parent-child relationship is established. A new widget adopts defaultsettings for any of its resources that are not explicitly set when the widget iscreated. Widget resources are data that define how a widget appears and behaves.Resources are described in “Widget resources and functions” on page 141.

Widget names serve several purposes:v Some widgets use their name to establish a default resource value. For example,

shells that have titles use their name as the default title. Push button and labelwidgets use their name as the default labelString. Using the name in this wayresults in more efficient code.

138 IBM Smalltalk: Programmer’s Reference

Page 153: IBM Smalltalk: Programmer's Reference

v Widget names are used as part of a widget’s printable representation (usingprintOn:). They are also useful for identifying widgets during debugging.

v On platforms supporting OSF/Motif as the native widget system, widget namesare used in conjunction with X resource files to set initial resource values forwidgets.

Tip: If you plan to use widget names to set initial resource values through Xresource files, such as .Xdefaults, then you must take care to use names whichfollow the X resource file naming conventions.

When a widget is created, it does not immediately appear on the screen. In thefollowing illustration, a label widget named CwLabel 3 has been created, along withtwo others, in a widget tree. Its parent is a row-column widget namedCwRowColumn. A row-column widget lays out its children horizontally, vertically,or both. The row-column’s parent is a shell widget named CwTopLevelShell.

CwLabel 2

Widget tree is created in memory only;no windows are associated with it

Nothing is visible on thescreen at this point

CwLabel 3CwLabel 1

CwTopLevelShell

CwRowColumn

2. Managing a widgetTo manage a widget, you specify that its size and position will be managed by itsparent widget. This process is called geometry management. Any changes in thesize or position of the parent widget will be recursively propagated to managedchild widgets. The application must specify that a widget is to be managed bysending the manageChild message to the widget.

Managing or unmanaging a widget does not affect the managed state of childwidgets. However, if a widget is unmanaged then neither it nor any of its childrenwill participate in geometry management. By default a widget is not managedwhen it is created.

3. Mapping a widgetTo map a widget, you specify that it is to appear on the display after it has beenrealized. Realizing a widget is described in “4. Realizing a widget”. By default, awidget is mapped automatically when it is managed. This is controlled by thesetting of the mappedWhenManaged widget resource, which defaults to true.Unmanaging a widget also unmaps it.

It is possible for widgets to be created, managed, and realized, but left unmapped.The widget remains invisible until it is mapped. This technique is useful forquickly displaying frequently used dialog boxes.

Widgets are mapped using the mapWidget method, and unmapped using theunmapWidget method. Mapping or unmapping a widget maps or unmaps all childwidgets.

4. Realizing a widgetUntil a widget is realized, it is invisible. A widget can be created, managed in thetree, and mapped, but it will not appear on the screen until it is realized. Duringrealization, all widgets assume their initial geometry and create their visual

Chapter 7. Common Widgets 139

Page 154: IBM Smalltalk: Programmer's Reference

appearance. Widgets are realized by sending the realizeWidget message to thetopmost widget in the hierarchy, or shell widget. Realizing a widget realizes all ofits children recursively. Widgets created, mapped, and managed as children ofalready realized widgets are automatically realized on creation.

In the following example, the CwTopLevelShell widget has been realized, and theCwRowColumn has positioned its three label children.

CwLabel 1 CwLabel 2 CwLabel 3

Widget tree is created, managed, and mappedand is now realized

The widget tree is displayedon the screen

CwTopLevelShell

CwRowColumn

CwLabel 1

CwLabel 2

CwLabel 3

5. Destroying a widgetWhen a widget is no longer required, it is destroyed. A widget can be implicitlydestroyed by the user, for example by clicking on a close box. Alternatively, awidget can be destroyed under application control by sending it the destroyWidgetmessage. The widget is removed from the display and released from memory.Destroying a widget recursively destroys all child widgets.

Widget tree is destroyedand released from memory

Widget hierarchy is removedfrom the screen

Mapping and unmapping widgetsA widget that is managed but not mapped still participates in geometrymanagement, that is, it takes up space in its parent, but it is not actually drawn.Normally this results in a blank area in the parent where the widget wouldotherwise appear.

In the following example, assume that the widget tree is created, managed andrealized, but the second CwLabel is subsequently unmapped. Notice that the labelis removed from the screen, but its parent still reserves its position in the

140 IBM Smalltalk: Programmer’s Reference

Page 155: IBM Smalltalk: Programmer's Reference

row-column widget.

CwLabel 1 CwLabel 3

How the widget tree appears on the display

CwLabel 1

CwLabel 3

CwRowColumn

CwTopLevelShell

CwLabel 2

Widget tree is in memoryand CwLabel 2 is unmapped

Managing and unmanaging widgetsWhen a widget is unmanaged, its parent can reclaim the space the widgetoccupies. If the parent widget is a composite that performs layout of its children, itwill adjust child layout accordingly. A row-column was chosen for this examplebecause it provides a visual demonstration of the difference between mapping andmanaging widgets.

In this example, assume that the widget tree is created, managed and realized, butCwLabel 2 is subsequently unmanaged. Not only is the button removed from thescreen, or unmapped, but it also loses its position in the row-column widget.

CwLabel 1 CwLabel 2 CwLabel 3

CwTopLevelShell

CwRowColumn

How the widget tree appears on the display

The widget tree is in memory and CwLabel 2 is unmanaged

CwLabel 1

CwLabel 3

Widget resources and functionsWidgets are configured and controlled by the application through resources andfunctions. Widget resources define the behavior and appearance of a widget.Widget functions are messages that can be sent to a widget to tell it to dosomething.

In IBM Smalltalk, resource accessors and functions are implemented as Smalltalkmethods in widget classes. Widget resource methods provide access to a widget’sresources. All methods that are not resource methods are widget functionmethods. A method’s comments and its message specification indicate whether it isa resource method or a function method.

ResourcesResources are somewhat analogous to Smalltalk instance variables, and resourceset and get methods are similar to instance variable accessor methods. However,there are several important differences:v Resources might or might not be implemented using instance variables, and the

implementation varies from platform to platform.v Changes to values in widget resources are immediately reflected in the

appearance of the widget.

Chapter 7. Common Widgets 141

Page 156: IBM Smalltalk: Programmer's Reference

v On platforms running Motif as the native widget system, IBM Smalltalk widgetresource values can be set using standard X resource files, like any other Motifapplication.

All widgets have a core set of resources. For example, all widgets have width andheight resources. A widget can also have resources specific to its behavior. Forexample, the items resource of the CwList widget defines what items are displayedin the widget. Default values are provided for all of a widget’s resources.

Resources defined by a widget’s superclasses are inherited. For example, considerthe widget class CwPushButton. This class is a subclass of CwLabel, CwPrimitive,CwBasicWidget, and CwWidget. CwPushButton inherits resources from all of itssuperclasses, and defines additional resources of its own. The default value of aninherited resource can be overridden.

The following table illustrates the resources that are available for a CwPushButtonwidget. Many of the resources are provided by CwWidget, and these are availableto all widgets.

Table 31. Widget resources for the CwPushButton classCwWidget CwPrimitive CwLabel CwPushButton.

ancestorSensitiveborderWidthdepthdestroyCallbackheight

mappedWhenManagedresizableresizeCallbacksensitiveuserDatawidthxy

(plus 16 attachment-related resources)

backgroundColor

foregroundColorhelpCallback

navigationTypetraversalOn

acceleratoracceleratorTextalignmentfontListlabelIconlabelInsensitiveIcon

labelInsensitivePixmaplabelPixmaplabelStringlabelTypemarginBottommarginHeightmarginLeftmarginRightmarginTopmarginWidthmnemonicrecomputeSize

activateCallbackarmCallback

disarmCallback

showAsDefault

Note: “Appendix A. Widget resources and callbacks” on page 469 provides a tablefor each class in the CwWidget hierarchy.

A widget’s resources are set or retrieved using the set and get accessor methods ofthe widget, which are the names that correspond directly to the associated resourcename. Resource setting methods have a special property that can be sent to awidget to set initial state during widget creation, from inside a create argBlock.

Not all widget resources can be modified or retrieved at any time. Widgetresources have a resource access designator that indicates when the resource can beset or retrieved. Resources are tagged with the letters C, S, or G to indicate whenthe resource can be modified or retrieved, as follows:v The application can set the resource at creation time only (C).v The application can set the resource at any time (S).v The application can retrieve, or get, the resource at any time after the widget is

created (G).

142 IBM Smalltalk: Programmer’s Reference

Page 157: IBM Smalltalk: Programmer's Reference

Resources are manipulated using get and set accessor methods derived from theOSF/Motif name for the resource by removing the ‘XmN’ prefix. For example, theMotif resource XmNheight for a widget is retrieved and modified using the heightand height: methods, respectively. The specification for each resource methodprovides the resource access designation information (C, S, G).

Create-only (C) resources can only be set using an argBlock at widget creation time.An argBlock is a single argument Smalltalk block of code that is evaluated with thewidget being created as its argument. Resources with an (S) designation can alsobe set in the argBlock. The argBlock is evaluated before the widget is fully created,that is, while it is still under construction, but after a Smalltalk object has beencreated to represent the widget. If argBlock is not required, nil can be used for theargBlock argument, rather than unnecessarily creating an empty block.

Tip: Always set resources in the create argBlock wherever possible. Also, unlessnames are needed for X resource files, use the widget’s name to establish adefault resource value as described in the widget creation section on page “1.Creating a widget” on page 138. If the system has more information availableat the time of widget creation, it can perform more optimization. On someplatforms a significant performance advantage is achieved by settingresources in the create argBlock rather than immediately after creation, whichmight cause default widget configuration to have to be “undone”.

In the following example, the width and height resources for a drawing area areexplicitly set in an argBlock when the drawing area widget is created. These specifythe size in pixels of the drawing area widget. The size of the shell widget iscalculated based on the size of the drawing area widget. In general, when the sizeof a widget is not explicitly specified, it is calculated based on the size of itschildren, recursively. The string arguments in the creation messages specify thenames of the widgets. By default, the name of the top-level shell appears as thewindow title.| shell drawingArea |shell := CwTopLevelShell

createApplicationShell: 'ShellName'argBlock: nil.

drawingArea := shellcreateDrawingArea: 'draw'argBlock: [:w | w width: 100; height: 100].

drawingArea manageChild.shell realizeWidget

Resources with set (S) and get (G) designations can be set and retrieved,respectively, after widget creation using the appropriate set and get methods.

Multiple resources with set (S) designation can also be set simultaneously after thewidget is created using the setValuesBlock: message, which takes an argBlock asargument. The setValuesBlock: method is the recommended way of setting multipleresources for a widget after the widget is created. Normally, after a widget hasbeen created and a resource is modified, which changes a widget’s appearance, thewidget is redisplayed to show the change. Using a setValuesBlock is more efficientthan setting the resources outside the block because the widget can then optimizeupdates together, even if several of them change the widget’s appearance. Theblock passed to setValuesBlock: has the same format as the argBlock used whencreating a widget.

In the following example, the geometry of a shell widget is changed. Assume thatthe variable shell is a top-level shell that has been created and realized.

Chapter 7. Common Widgets 143

Page 158: IBM Smalltalk: Programmer's Reference

"Set widget geometry using a series of set accessor methods.The shell is redrawn up to four times, after for each resource change."shell

x: 10;y: 10;width: 100;height: 100.

"Set widget geometry using a set values block.The shell is redrawn only after, with the final dimensions,at the final position."shell

setValuesBlock: [:w |w

x: 10;y: 10;width: 100;height: 100].

Tip: Some resources change their values when the value of a different resource inthe same widget is changed. To avoid this “push-down-here-pop-up-there”effect, such resources must be set simultaneously using an argBlock, either oncreation or after creation using setValuesBlock:.This situation occurs withleft/right and top/bottom CwForm attachment resources, which shouldalways be set in pairs.

Function methodsWidget methods that are not resource set or get methods are widget functionmethods. Unlike resource setting messages, function messages can only be sent towidgets after they have been created. While resource methods are used to access orchange widget state, function methods typically perform more complex operations,and in some cases modify resource values. While resource get and set methodsuniformly require zero arguments and one argument respectively, widget functionmethods take varying numbers of arguments, depending on the particularfunction. The manageChild method is an example of a widget function.

Functions often alter the resource values of a widget as a side effect. For example,the setString: function for text widgets alters the value resource of the widget. Insome cases it is possible to achieve the same effect using either a resource methodor a function method.

Tip: Do not call function methods from inside a create argBlock. Because thewidget is not fully created when the create argBlock is evaluated, invokingwidget functions results in errors.

CwConstants pool dictionaryThe Common Widgets subsystem uses a pool dictionary called CwConstants toprovide pool variables for constant values. For example, pool variables such asXmATTACHFORM and XmNactivateCallback are used as arguments to CommonWidgets methods. These pool variable names should be used rather than directlyusing their constant values. All classes that require these Common Widgets poolvariable names must include the CwConstants pool dictionary in their classdefinition.

Example code to create a widget treeThe following code illustrates how to create the example widget tree shown above:

144 IBM Smalltalk: Programmer’s Reference

Page 159: IBM Smalltalk: Programmer's Reference

| shell main form drawArea rowColumn button1 button2 button3 |shell := CwTopLevelShell

createApplicationShell: 'shell'argBlock: [:w | w title: 'Graphics Example'].

"A top-level shell is created. A mainWindow widget is created. The parent is shell."

main := shellcreateMainWindow: 'main'argBlock: nil.

main manageChild.

"A form widget is created as a child of main."form := main

createForm: 'form'argBlock: nil.

form manageChild.

"A drawArea widget is created as a child of form."drawArea := form

createDrawingArea: 'drawing'argBlock: [:w |

w"Its width and height are set to 300 pixels."

width: 300;height: 300;

"Its border width is set to 1 pixel."borderWidth: 1].

drawArea manageChild.

"A rowColumn widget is created as a child of form."rowColumn := form

createRowColumn: 'buttons'argBlock: nil.

rowColumn manageChild.

"In addition, three push buttons are created as children of rowColumn.By default, the names of the buttons ('1', '2', '3')will appear as the button labels. rowColumn willdetermine its size based on the sizes of the buttons."button1 := rowColumn

createPushButton: '1'argBlock: nil.

button1 manageChild.

button2 := rowColumncreatePushButton: '2'argBlock: nil.

button2 manageChild.

button3 := rowColumncreatePushButton: '3'argBlock: nil.

button3 manageChild.

"Form constraints for each child widget within form are specified.rowColumn is offset from the edge of form by 2 pixels on all sides,and attached to the edge of form on the top, bottom, and left sides."rowColumn

setValuesBlock: [:w |w

topAttachment: XmATTACHFORM;topOffset: 2;bottomAttachment: XmATTACHFORM;bottomOffset: 2;leftAttachment: XmATTACHFORM;leftOffset: 2].

"drawArea is attached to form on the top, bottom and right. On the left side,it is attached to rowColumn."drawArea

setValuesBlock: [:w |

Chapter 7. Common Widgets 145

Page 160: IBM Smalltalk: Programmer's Reference

wbottomAttachment: XmATTACHFORM;bottomOffset: 4;topAttachment: XmATTACHFORM;topOffset: 2;

rightAttachment: XmATTACHFORM;rightOffset: 4;leftAttachment: XmATTACHWIDGET;leftWidget: rowColumn;leftOffset: 2].

"Finally, the realizeWidget message is sent to the topmost widget.All widgets are now shown on the screen."shell realizeWidget

Tip: Form constraints are described in detail in “Form widgets” on page 167.

When this code is run, a window titled “Graphics Example” appears on the screen.The widgets behave as expected, but the application is not notified when a buttonis pressed or when the mouse is moved. For the application to be notified of theuser’s interaction with the widgets, event handlers and callbacks are required.

1

2

3

Graphics Example

Widget event handling and callbacksAn event is the mechanism that notifies the application when the user performs amouse or keyboard operation. The application can be notified about key pressesand releases, mouse button presses and releases, and mouse movements. Eventsare handled by adding an event handler to a widget.

A callback is the mechanism that notifies the application when some higher levelaction is performed on a widget. For example, the XmNactivateCallback is used toinform the application that a CwPushButton has been pressed and released. Asanother example, all widgets support the XmNdestroyCallback that is invoked justbefore a widget is destroyed.

The following example illustrates how callbacks and event handlers are defined.For detailed information on callbacks and event handlers, see “Callbacks” on page150 and “Event handlers” on page 154.

Example of using an event handler and a callbackIn the following example, a small graphics application interface is created. Thewidget tree created by the code is illustrated on the right.

146 IBM Smalltalk: Programmer’s Reference

Page 161: IBM Smalltalk: Programmer's Reference

The code to create this tree is similar to that for the example on page “Examplecode to create a widget tree” on page 144, but in this example event and callbackhandler code (bold text) has been added. This code registers the event and callbackhandlers just after the widgets are created.

When the push-button widget is pressed (that is, when the user clicks mousebutton 1 while the mouse pointer is over the push-button widget), thepressed:clientData:callData: method is run. When the mouse is moved in the drawingarea with button 1 held down, the button1Move:clientData:event: method is run.

| shell main form drawArea button |shell := CwTopLevelShell

createApplicationShell: 'shell'argBlock: [:w |

w title: 'Graphics Example'].

main := shellcreateMainWindow: 'main'argBlock: nil.

main manageChild.

form := maincreateForm: 'form'argBlock: nil.

form manageChild.

Graphics Example

drawArea := formcreateDrawingArea: 'drawing'argBlock: [:w |

wwidth: 300;height: 300;borderWidth: 1].

"After the drawing area is created, an event handler is added to the widgetThe method specifies that the application shall be notified of Button1Motionevents (button 1 is down and the mouse is moving) within the drawing area.When mouse events occur, the button1Move:clientData:event message is sentto self (the application)."drawArea

addEventHandler: Button1MotionMaskreceiver:selfselector: #button1Move:clientData:event:clientData:nil.

drawArea manageChild.

button := formcreatePushButton: '1'argBlock: nil.

"Here a callback is added to the newly created push-button widget.The method specifies that the application shall be notified ofactivate callback (the button is pressed and released). When thebutton is activated, the pressed:clientData:callData: message issent to self."button

addCallback:XmNactivateCallbackreceiver: selfselector: #pressed:clientData:callData:clientData:nil.

button manageChild.

drawAreasetValuesBlock: [ :w |

wtopAttachment: XmATTACHFORM;topOffset: 2;

Chapter 7. Common Widgets 147

Page 162: IBM Smalltalk: Programmer's Reference

bottomAttachment: XmATTACHFORM;bottomOffset: 2;leftAttachment: XmATTACHWIDGET;leftWidget: button;leftOffset: 2;rightAttachment: XmATTACHFORM;rightOffset: 2].

buttonsetValuesBlock: [ :w |

wtopAttachment: XmATTACHFORM;topOffset: 2;leftAttachment: XmATTACHFORM;leftOffset: 2].

shell realizeWidget.

Creating and using widgetsThe previous section provided an overview of how widgets are created andconfigured, and how they interact with an application. This section describes howto create and use specific widgets in the Common Widgets subsystem. A moredetailed description of callbacks and event handlers is also provided.

The following widgets are discussed:

ShellsCwTopLevelShell, CwDialogShell, CwOverrideShell

Main windows and scrolled windowsCwMainWindow and CwScrolledWindow

Text editors and drawing areasCwText andCwDrawingArea

Layout widgetsCwForm and CwRowColumn

Buttons and labelsCwLabel, CwDrawnButton, CwPushButton, CwToggleButton

Menus and menu itemsCwRowColumn, CwCascadeButton, CwPushButton

Lists and combo boxesCwList and CwComboBox

Composite boxesCwBulletinBoard, CwCompositeBox, CwMessageBox, CwSelectionBox

Note: These widgets have many resources and callbacks. This section discussesonly the most commonly used resources and callbacks. For a complete list,see “Appendix A. Widget resources and callbacks” on page 469.

Widget creation convenience methodsWidgets might be created using convenience methods implemented as instancemethods of CwWidget or as class methods of CwShell and its subclasses. Theseconvenience methods are sent to the widget that will be the new widget’s parent.As a shell does not need a parent, shell creation convenience methods are sent tothe class. Convenience methods are provided to create the following:v All of the standard widgets; for example, CwPushButton, CwList, and

CwTopLevelShell

148 IBM Smalltalk: Programmer’s Reference

Page 163: IBM Smalltalk: Programmer's Reference

v Commonly used configurations of some standard widgets; for example,CwRowColumn widgets preconfigured for use as menus or radio boxes

v Special pseudowidgets that appear to be composite arrangements of standardwidgets; for example, scrolled list and scrolled text. Due to platformoptimizations, such pseudowidgets might not actually be implemented ascomposites of platform widgets

Because convenience methods do not automatically manage the widgets that theycreate, the new widgets must be explicitly managed after they are created. Inaddition, because some convenience functions actually create composite widgetsubtrees, the widget returned might not be a direct child of the widget the creationmessage was sent to. For an example of this, see “Scrolled lists” on page 188.

Tip: Widgets can also be created by sending messages directly to the widgetclasses. However, widgets created in this way bypass normal initializationand configuration, and might have different behavior than widgets createdusing convenience functions. Always use the convenience function to create awidget, if one is available.

The code fragment below illustrates how to create a push-button widget using aconvenience method. Top level shells are created by sending a message directly tothe CwTopLevelShell class.| shell button |shell := CwTopLevelShell

createApplicationShell: 'shell'argBlock: nil.

button := shellcreatePushButton: 'Button1'argBlock: nil.

button manageChild.shell realizeWidget.

Some convenience methods do more than create a widget. For example, thecreateScrolledList:argBlock: method creates a pseudowidget that appears, in manyrespects, to be a scrolled window, scroll bars, and a list widget. The relationshipbetween the scrolled window, the scroll bars, and the list is defined such that thelist can be scrolled using the scroll bars of the scrolled window. The createoperation returns the list widget, and is treated by the application as any other listwidget. However, the widget system created is tightly coupled and on someplatforms might be implemented using a single widget, to maximize performanceand platform look and feel. For these reasons, the application should not attemptto reconfigure the “hidden” parts of such pseudowidgets.

Tip: Do not attempt to reconfigure the ″hidden″ parts of pseudowidgets such asscrolled lists or scrolled texts. A scrolled text or list might be implementedusing a single platform widget and might not behave in exactly the same wayas a CwText or CwList created as a child of a CwScrolledWindow.

Following is a list of the shell widget creation convenience methods that are classmethods of CwShell and its subclasses:

createPopupShell:parent:argBlock:createApplicationShell:argBlock:

Following is a list of the widget creation convenience methods that are instancemethods of CwWidget:

createArrowButton:argBlock:createBulletinBoard:argBlock:

Chapter 7. Common Widgets 149

Page 164: IBM Smalltalk: Programmer's Reference

createBulletinBoardDialog:argBlock:createCascadeButton:argBlock:createComboBox:argBlock:createDialogShell:argBlock:createDrawingArea:argBlock:createDrawnButton:argBlock:createErrorDialog:argBlock:createForm:argBlock:createFormDialog:argBlock:createFrame:argBlock:createInformationDialog:argBlock:createLabel:argBlock:createList:argBlock:createMainWindow:argBlock:createMenuBar:argBlock:createMessageBox:argBlock:createMessageDialog:argBlock:createOptionMenu:argBlock:createPopupMenu:argBlock:createPromptDialog:argBlock:createPulldownMenu:argBlock:createPushButton:argBlock:createQuestionDialog:argBlock:createRadioBox:argBlock:createRowColumn:argBlock:createScale:argBlock:createScrollBar:argBlock:createScrolledList:argBlock:createScrolledText:argBlock:createScrolledWindow:argBlock:createSelectionBox:argBlock:createSelectionDialog:argBlock:createSeparator:argBlock:createSimpleCheckBox:argBlock:createSimpleMenuBar:argBlock:createSimpleOptionMenu:argBlock:createSimplePopupMenu:argBlock:createSimplePulldownMenu:argBlock:createSimpleRadioBox:argBlock:createText:argBlock:createToggleButton:argBlock:createWarningDialog:argBlock:createWorkArea:argBlock:createWorkingDialog:argBlock:

CallbacksActions performed on widgets by the user must be communicated back to theapplication. One mechanism used for this communication is a callback. A callbackmethod defines actions to perform in response to some occurrence in a widget.Callbacks are normally registered just after widgets are created. For example, whena push-button widget is created, the application usually registers an activatecallback that is run when the button is activated by the user clicking on it.Although it is not necessary for the application to register callbacks, without themthe application is unable to take action based on the user’s interaction with thewidgets.

150 IBM Smalltalk: Programmer’s Reference

Page 165: IBM Smalltalk: Programmer's Reference

Callbacks are registered using the addCallback:receiver:selector:clientData: method.

Tip: The argBlock argument of a widget creation message can only be used to setwidget resources. The addCallback: message cannot be used within the createargBlock. Callbacks are usually registered immediately after the widget hasbeen created, and before it is realized.

The addCallback:receiver:selector:clientData: method takes four parameters:

callbackNameA constant specifying which callback is being registered, for example,XmNactivateCallback

receiverThe object that will receive the callback message

selectorThe 3-parameter callback message selector

clientDataOptional data that will be passed to the callback when it is run

When a callback method is run, it is passed three arguments:v The widget that caused the callbackv The client data specified when the callback was registeredv Information specific to the type of callback, called the call data

The following example illustrates how to register a callback. First a button iscreated, in this case, as the child of a shell, and then an XmNactivateCallback isadded to the button.| shell button |

shell := CwTopLevelShellcreateApplicationShell: 'shell'argBlock: nil.

button := shellcreatePushButton: 'OK'argBlock: nil.

button"Name of the callback to add"

addCallback: XmNactivateCallback

"Receiver of the callback message, usually self"receiver:self

"Name of method to execute"selector: #pressed:clientData:callData:

"Data to be passed unmodified to the callback method"clientData: 'Test data'.

button manageChild.

shell realizeWidget.

When an activate callback occurs due to the button being pressed, thepressed:clientData:callData: method, shown below, is run. The method prints thestring ‘Test data’ on the Transcript Window. The widget issuing the callback ispassed as the widget parameter. In this case, this is the push-button widget. Thestring ‘Test data,’ specified as the client data when the callback was added, ispassed as the clientData parameter. Callback-specific data is passed as the callDataparameter. For the activate callback of push-button widgets, however, the call dataprovides no new information.

Chapter 7. Common Widgets 151

Page 166: IBM Smalltalk: Programmer's Reference

pressed: widget clientData: clientData callData: callData"The push button has been pressed."

Transcript cr; show: clientData

The following table describes the class hierarchy and data accessor method namesfor call data objects. All classes are concrete classes. A description of each accessormethod can be found in the source or comment for each method.

Table 32. Call data class hierarchy

Class hierarchy Responsibility Data accessor methods

CwAnyCallbackData Provides call data for mostcallbacks.

reason (a constant,prefixed by ‘XmCR’)

CwComboBoxCallbackData Provides call data for combobox singleSelectionCallback.

itemitemPosition

CwConfirmationCallbackData Provides call data forcallbacks such as the shellwindowCloseCallback. Thiscallback can be canceled bythe application.

doitdoit:

CwTextVerifyCallbackData Provides call data for textand combo-boxmodifyVerifyCallback. Thesecallbacks can be canceled bythe application.

currInsertendPosstartPostexttext:

CwDrawingCallbackData Provides call data forcallbacks such as compositeexpose and interceptExposecallbacks, drawing area inputcallbacks, and drawn-buttonactivate and exposecallbacks.

eventwindow

CwListCallbackData Provides call data forcallbacks such as listbrowseSelect, singleSelect,multipleSelect,extendedSelect, anddefaultAction callbacks.

itemitemPositionselectedItemCount

selectedItemPositionsselectedItems

CwRowColumnCallbackData Provides call data forcallbacks such asrow-column entryCallback.

widgetdatacallbackData

CwToggleButtonCallbackData Provides call data forcallbacks such as thetoggle-buttonvalueChangedCallback.

set

CwValueCallbackData Provides call data forcallbacks such as scale andscroll bar drag andvalueChangedCallback, andscroll bar decrement,increment, pageDecrement,pageIncrement, toBottom,and toTop callbacks.

value

Tip: Call data objects are only valid during the callback. Do not store a call dataobject in a callback method and attempt to reference it later.

152 IBM Smalltalk: Programmer’s Reference

Page 167: IBM Smalltalk: Programmer's Reference

The following table lists the callbacks supported by each widget.

Table 33. Callbacks supported by each widget

Widgets Callbacks supported

CwArrowButton activate, arm, destroy, disarm, help, resize

CwBasicWidget destroy, resize

CwBulletinBoard destroy, expose, focus, help, interceptExpose, losingFocus,map, resize, unmap

CwCascadeButton cascading, destroy, help, resize

CwComboBox activate, destroy, focus, help, losingFocus, modifyVerify,popdown, popup, resize, singleSelection, valueChanged

CwComposite destroy, expose, focus, help, interceptExpose, losingFocus,resize

CwCompositeBox destroy, expose, focus, help, interceptExpose, losingFocus,map, ok, resize, unmap

CwDialogShell destroy, focus, iconify, popdown, popup, resize,windowClose

CwDrawingArea destroy, expose, focus, help, input, interceptExpose,losingFocus, resize

CwDrawnButton activate, arm, destroy, disarm, expose, focus, help,losingFocus, resize

CwForm destroy, expose, focus, help, interceptExpose, losingFocus,map, resize, unmap

CwFrame destroy, expose, focus, help, interceptExpose, losingFocus,resize

CwLabel destroy, help, resize

CwList browseSelection, defaultAction, destroy, extendedSelection,help, multipleSelection, resize, singleSelection

CwMainWindow destroy, expose, focus, help, interceptExpose, losingFocus,resize

CwMessageBox cancel, destroy, expose, focus, help, interceptExpose,losingFocus, map, ok, resize, unmap

CwOverrideShell destroy, popdown, popup, resize

CwPrimitive destroy, help, resize

CwPushButton activate, arm, destroy, disarm, help, resize

CwRowColumn destroy, entry, expose, focus, help, interceptExpose,losingFocus, map, resize, simple, unmap

CwScale destroy, drag, expose, focus, help, interceptExpose,losingFocus, resize, valueChanged

CwScrollBar decrement, destroy, drag, help, increment, pageDecrement,pageIncrement, resize, toBottom, toTop, valueChanged

CwScrolledWindow destroy, expose, focus, help, interceptExpose, losingFocus,resize

CwSelectionBox apply, cancel, destroy, expose, focus, help, interceptExpose,losingFocus, map, noMatch, ok, resize, unmap

CwSeparator destroy, help, resize

CwShell destroy, popdown, popup, resize

Chapter 7. Common Widgets 153

Page 168: IBM Smalltalk: Programmer's Reference

Table 33. Callbacks supported by each widget (continued)

Widgets Callbacks supported

CwText activate, destroy, help, focus, losingFocus, modifyVerify,resize, valueChanged

CwToggleButton arm, destroy, disarm, help, resize, valueChanged

CwTopLevelShell destroy, focus, iconify, popdown, popup, resize,windowClose

CwWidget destroy, dragDetect, resize

CwWMShell destroy, focus, iconify, popdown, popup, resize,windowClose

Event handlersEvent handlers are another mechanism used to inform the application of inputactions by the user. While callbacks notify the application of high level interactionssuch as the selection of items in a list widget, event handlers notify the applicationof low level interactions, including the following:v Mouse pointer motionv Mouse button presses and releasesv Individual key presses and releases

Register event handlers using theaddEventHandler:receiver:selector:clientData: method.

Tip: The argBlock argument of a widget-creation message can only be used to setwidget resources. The addEventHandler: message cannot be used within thecreate argBlock. Event handlers are usually registered immediately after thewidget has been created, and before it is realized.

The addEventHandler:receiver:selector:clientData: method takes four parameters:

eventMaskA bit mask specifying which events to notify the receiver of

receiverThe object that receives the event handler message

selectorThe 3-parameter event handler message selector

clientDataOptional data that is passed to the event handler when it is run

The eventMask is specified as the bitwise-OR of one or more of the bit masksdescribed in the following table.

Table 34. Common widgets event masks

Event masks Description

KeyPressMask Keyboard key down events

KeyReleaseMask Keyboard key up events

ButtonPressMask Mouse button down events

ButtonReleaseMask Mouse button up events

PointerMotionMask All pointer motion events

Button1MotionMask Pointer motion events while button 1 is down

154 IBM Smalltalk: Programmer’s Reference

Page 169: IBM Smalltalk: Programmer's Reference

Table 34. Common widgets event masks (continued)

Event masks Description

Button2MotionMask Pointer motion events while button 2 is down

Button3MotionMask Pointer motion events while button 3 is down

ButtonMotionMask Pointer motion events while any button is down

ButtonMenuMask Button menu request events

When an event handler method is run, it is passed three arguments:v The widget to which the handler was added and in which the event occurredv The client data specified when the event handler was registeredv An object describing the event, called the event

The following table describes the class hierarchy for event objects. Classes in italicsare abstract classes.

Table 35. Event class hierarchyClass hierarchy Responsibility.CwEvent Defines common behavior for event data in event

handlers.CwExposeEvent Provides event data for expose events in expose

callbacks (see Note below).CwInputEvent Defines common behavior for button, key, and

motion event objects.CwButtonEvent Provides event data for mouse button-press/release

events.CwKeyEvent Provides event data for key-press/release events.CwMotionEvent Provides event data for mouse motion events.

Tip: An expose event handler cannot be explicitly added to a widget. ACwExposeEvent object is passed to an application as part of the call data for anexposeCallback.

The following messages can be sent to the event object to retrieve informationabout the event. The methods for all events (CwEvent) include the following:

type The type of event that occurred. This has one of the following values:ButtonPress, ButtonRelease, Expose, KeyPress, KeyRelease, and MotionNotify.

windowThe CgWindow associated with the widget for which the event wasgenerated.

display The CgDisplay associated with the event.

For expose events (CwExposeEvent), the method include the following:

count The number of expose events which remain for the affected CgWindow. Asimple application might want to ignore all expose events with a nonzerocount, and perform a full redisplay if the count is zero.

rectangleA rectangle describing the damaged area, in the coordinate system of theaffected CgWindow.

x The x-coordinate of the origin of the damaged rectangle.

y The y-coordinate of the origin of the damaged rectangle.

Chapter 7. Common Widgets 155

Page 170: IBM Smalltalk: Programmer's Reference

height The height, in pixels, of the damaged rectangle.

width The width, in pixels, of the damaged rectangle.

For input events (CwButtonEvent, CwKeyEvent, and CwMotionEvent), the methodsare as follows:

state A bit mask representing the logical state of modifier keys and pointerbuttons just prior to the event. Possible bit masks include: ControlMask,ShiftMask, LockMask, Mod1Mask to Mod5Mask, and Button1Mask toButton3Mask.

x The x-coordinate of the pointer, relative to the widget in which the eventoccurred.

y The y-coordinate of the pointer, relative to the widget in which the eventoccurred.

point x @ y

xRoot A coordinate of the pointer, relative to the screen.

yRoot A coordinate of the pointer, relative to the screen.

pointRootxRoot @ yRoot

time The time, in milliseconds, at which the event occurred.

For mouse button events (CwButtonEvent), the methods are as follows:

button The number of the button that was pressed or released (1, 2 or 3).

For key events (CwKeyEvent), the methods are as follows:

keysym A constant describing the keyboard key that was pressed or released. Theseconstants are found in the CwConstants pool dictionary, and are prefixedwith ‘XK.’

characterThe Character describing the keyboard key that was pressed or released, ornil if it does not represent a valid character.

There are two common uses of event handlers. The first is for handling input in adrawing area widget. For example, in a graphical drawing application a drawingarea widget would be used to display the drawing under construction. Eventhandlers would be registered to notify the application of pointer motion, mousebutton, and key press events, allowing text strings to be edited and graphicalobjects to be positioned and changed using the mouse.

The second common use is for handling pop-up menus. An event handler is addedfor the ButtonMenuMask event. When the event handler is called, the applicationpops the menu up.

Mouse button 3 is used as the menu button. However, some platforms trigger thebutton menu event when the button is pressed, and others when the button isreleased. The ButtonMenuMask event hides this difference. It should be used, ratherthan the other button events, to support pop-up menus in a platform-independentmanner.

Tip: On some platforms it is possible for a button release event to be deliveredwithout a corresponding button press event. Applications should be prepared

156 IBM Smalltalk: Programmer’s Reference

Page 171: IBM Smalltalk: Programmer's Reference

to ignore such spurious button release events by only processing a buttonrelease event that is received after a matching button press event.

In the following example, a drawing area is created, and an event handler is addedto notify the application of mouse button presses, key presses, and pointer motion.Label widgets are used to display information about the events. The variable labelswould be implemented as an instance variable for the class.| shell rowColumn label labels drawing |shell := CwTopLevelShell

createApplicationShell: 'shell'argBlock: [:w | w title: 'Event Handler Example'].

rowColumn := shellcreateRowColumn: 'rowColumn'argBlock: nil.

rowColumn manageChild.

labels := Array new: 3.1 to: 3 do: [:i |

label := rowColumncreateLabel: 'label'argBlock: nil.

label manageChild.labels at: i put: label].

(labels at: 1) labelString: 'Position: '.(labels at: 2) labelString: 'Button pressed at position: '.(labels at: 3) labelString: 'Keysym of last pressed key: '.

drawing := rowColumncreateDrawingArea: 'drawing'argBlock: [:w |

wborderWidth: 1;width: 300;height: 300].

drawingaddEventHandler: ButtonPressMask | KeyPressMask | PointerMotionMaskreceiver: selfselector: #eventHandler:clientData:event:clientData: nil.

drawing manageChild.shell realizeWidget

When an event occurs, the following method is run. Information about the event isdetermined from the event argument and is displayed in the label widgets.eventHandler: widget clientData: clientData event: event"Handle an input event."

event type = MotionNotifyifTrue: [(labels at: 1) labelString: 'Position: ',

event point printString].

event type = ButtonPressifTrue: [(labels at: 2) labelString: 'Button ', event

button printString, ' pressed at position: ',event point printString].

event type = KeyPressifTrue: [(labels at: 3) labelString: 'Keysym of last pressed key: ',

event keysym printString].

Chapter 7. Common Widgets 157

Page 172: IBM Smalltalk: Programmer's Reference

Shell widgetsShell widgets provide the interface between an application and the platform’swindow manager. A shell widget looks like a window on the screen and containsexactly one child. The window manager is the part of the platform window systemthat manages the geometry, appearance, and stacking order of windows on thedisplay. The window manager can add window decorations to a window, such as aframe, a title, resize handles, minimize and maximize buttons, and a close button.Window decorations are described in more detail in “Top-level shell widgets” onpage 158. The window manager also keeps track of which window has input focus,that is, which window receives keyboard input. A shell can receive a focus callbackwhen focus is either lost or gained.

A CwTopLevelShell provides a normal window with standard appearance anddecorations, and does not have a parent. CwTopLevelShell widgets are described indetail in the next section. CwOverrideShell and CwDialogShell widgets must have aparent widget. These shells are described in this section.

CwDialogShell widgets are pop-up windows used to implement modal or modelessdialog windows. The child of a CwDialogShell is typically an instance of a subclassof CwBulletinBoard. A CwDialogShell and its child are typically created automaticallyby using one of the dialog convenience methods. Unlike other types of shells, aCwDialogShell popped up by managing its child. The parent of a CwDialogShell canbe any widget, and the dialog always appears over the window containing itsparent widget. For further information on dialog shells and dialogs, see the sectionon “Composite-box widgets” on page 190.

CwOverrideShell widgets are used for pop-up windows that bypass windowmanagement and appear in front of all other windows. They do not have awindow frame, and cannot be moved, resized, or iconified by the user. CreateCwOverrideShell widgets using the CwShell class methodcreatePopupShell:parent:argBlock:. Make a CwOverrideShell visible by sending it thepopup message.

Top-level shell widgetsThis section describes how to create and use top-level shell widgets(CwTopLevelShell). Some commonly used shell resources and callbacks arediscussed. A list of all resources and callbacks used by top-level shells is in“Appendix A. Widget resources and callbacks” on page 469.

The root of a widget tree must be a CwTopLevelShell. A top level shell widget hasno parent. Top-level shells are created using the createApplicationShell:argBlock:method, which is sent to the CwTopLevelShell class. A top-level shell widget musthave a child widget before it can be realized.

Tip: A common programming error is to attempt to realize a top level shell thathas no child widget, or whose child widget computes an initial size with zerowidth or height. On a Motif platform this normally causes the application toexit with the message: “Error: Shell widget has zero width or height.” IBMSmalltalk detects most common cases and prevents the application fromexiting.

The following example creates a top-level shell with a main window widget as itschild. In this example, the main window’s width and height are explicitly set.

158 IBM Smalltalk: Programmer’s Reference

Page 173: IBM Smalltalk: Programmer's Reference

However a main window is not usually given explicit dimensions. It is usually leftto calculate its dimensions based on the needs of its children.| shell mainWindow |

shell := CwTopLevelShellcreateApplicationShell: 'shell'argBlock: [:w | w title: 'Shell Example 1'].

mainWindow := shellcreateMainWindow: 'main'argBlock: [:w | w width: 100; height: 100].

mainWindow manageChild.shell realizeWidget.

The resources for CwTopLevelShell include title, mwmDecorations, icon, iconPixmap,and iconMask. The mwmDecorations resource indicates which decorations are to beadded to the shell. The following table lists the bit masks used to specifydecorations. The icon (or iconPixmap) resources indicate the icon (or pixmap) to beused by the window manager for the application’s icon, and the iconMask resourceindicates the pixmap to clip to if the icon is non-rectangular.

Table 36. TopLevel shell decoration resource flags

Decoration Literal Definition

MWMDECORALL If set, changes the meaning of the other flags to indicate thatthe specified decoration should be removed from the defaultset.

MWMDECORBORDER Include a border.

MWMDECORRESIZEH Include resize frame handles.

MWMDECORTITLE Include title bar.

MWMDECORMENU Include window close/system menu.

MWMDECORMINIMIZE Include minimize window button.

MWMDECORMAXIMIZE Include maximize window button.

Tip: The top-level shell decorations settings indicate the preferred configurationfor the window. The window manager can alter or ignore the settings ifparticular combinations are not supported by the platform.

In the following example, the shell’s mwmDecorations resource is explicitly alteredin the create argBlock to specify that the minimize button should not be provided.| shell main |shell := CwTopLevelShell

createApplicationShell: 'shell'argBlock: [:w |

wtitle: 'Shell Example 2';mwmDecorations: MWMDECORALL | MWMDECORMINIMIZE].

main := shellcreateMainWindow: 'main'argBlock: [:w | w width: 100; height: 100].

main manageChild.shell realizeWidget.

Chapter 7. Common Widgets 159

Page 174: IBM Smalltalk: Programmer's Reference

Scrolled-window widgetsThe scrolled-window widget (CwScrolledWindow) can scroll any other widget bypositioning it behind a clipping area. No special processing by the application isrequired to implement scrolling. Any widget tree can be scrolled simply by makingit the work region of a CwScrolledWindow or CwMainWindow widget.

Create a scrolled-window widget by sending the createScrolledWindow:argBlock:message to its parent. Next, create the widget to be scrolled. Make it the workregion for the scrolled window by using the setAreas:verticalScrollbar:workRegion:message.

Scrolled-window widgets support two scrolling policies, specified by thescrollingPolicy resource. These are XmAPPLICATIONDEFINED (the default) andXmAUTOMATIC. When the scrolling policy is XmAUTOMATIC, the scrolledwindow handles all aspects of scrolling, including creation of the scroll bars. Theapplication can be notified of scroll bar movements by adding callbacks.

When the scrolling policy is XmAPPLICATIONDEFINED, the application musthandle all aspects of scrolling, including creation of scroll bars. Set the scroll barsusing the setAreas:... message.

The scrollBarDisplayPolicy resource defines whether or not scrollbars are alwaysshowing (XmSTATIC) or displayed only if the work region exceeds the clip area(XmASNEEDED).

Tip: The scrollingPolicy and scrollBarDisplayPolicy resources can only be set atcreation time.

The following example creates a scrolled window containing several buttons in avertical row-column. The scrolling policy is XmAUTOMATIC.

| shell scroll buttons |shell := CwTopLevelShell

createApplicationShell: 'shell'argBlock: [:w |

w title: 'Scrolled Buttons']."Creates a scrolled window with automaticscrolling policy. The defaultscrollBarDisplayPolicy, XmSTATIC, is used."scroll := shell

createScrolledWindow: 'scroll'"The default scrollBarDisplayPolicy."

argBlock: [:w | w scrollingPolicy: XmAUTOMATIC].

Scrolled Buttons

Array

ArrayedCollection

Bag

ByteArray

buttons := scroll"Creates a row-column that will contain the buttons to be scrolled."

createRowColumn: 'buttons'argBlock: nil.

buttons manageChild.

(Collection withAllSubclasses collect: [:class | class name])asSortedCollection do: [:name |

(buttons"Creates the push buttons using the Collection class hierarchy names."

createPushButton: nameargBlock: nil)

manageChild].

160 IBM Smalltalk: Programmer’s Reference

Page 175: IBM Smalltalk: Programmer's Reference

"Sets the scrolled-window areas."scroll"Only the work region needs to be set."setAreas: nil"The scroll bars are created automatically because the scrolling policyis XmAUTOMATIC."

verticalScrollbar: nilworkRegion: buttons.

scroll manageChild.shell realizeWidget.

Main-window widgetsThe main-window widget (CwMainWindow) is used to organize the application’smenu bar and the widgets that define the application’s work region. As a subclassof CwScrolledWindow, CwMainWindow class also includes all of the functionalityprovided by the CwScrolledWindow class and can provide scroll bars for scrollingthe work region. If a main window is used, it must be the immediate child of atop-level or dialog shell.

A main-window widget is created by sending the createMainWindow:argBlock:message to a shell widget.

A CwMainWindow must always be created as the child of a CwTopLevelShell orCwDialogShell. Creating it as the child of any other widget is an error.

Main windows and geometry managementLike other composite widgets, a main-window widget manages the geometry of itschildren.

shell

In order to manage its children correctly, a main-window widget must know whichwidget is the menu bar, which widget is the work region, and which widgets arethe scroll bars. The setAreas:horizontalScrollbar:verticalScrollbar:workRegion: messageexplicitly tells the main window which of its child widgets are to be used for thesepurposes. In the following example, an empty menu bar and a drawing areawidget are created as children of the main window. The setAreas: message is sent tothe main window to explicitly set menuBar as the main window’s menu bar, anddrawingArea as the main window’s work region. Because no scroll bars are beingdefined by the application, nil is passed in for the scroll bar arguments. For moreinformation on menus and menu bars, see “Menus” on page 178.| shell main menuBar drawingArea |

shell := CwTopLevelShellcreateApplicationShell: 'shell'argBlock: nil.

main := shellcreateMainWindow: 'main'argBlock: nil.

main manageChild.

Chapter 7. Common Widgets 161

Page 176: IBM Smalltalk: Programmer's Reference

menuBar := maincreateSimpleMenuBar: 'menu'argBlock: [:w | w buttons: #('')].

menuBar manageChild.

drawingArea := maincreateDrawingArea: 'draw'argBlock: [:w | w width: 300; height: 300].

drawingArea manageChild.

mainsetAreas: menuBar

horizontalScrollbar: nilverticalScrollbar: nilworkRegion: drawingArea.

shell realizeWidget.

Text widgetsThe text widget (CwText) provides text viewing and editing capabilities to theapplication. Create text widgets using the createText:argBlock: andcreateScrolledText:argBlock: convenience methods. The latter method makes the textscrollable, but otherwise provides basically the same functionality.

Set and retrieve the entire contents of the text widget using the setString: andgetString methods.

When a scrolled text widget is created using createScrolledText:argBlock:, aCwScrolledWindow widget is inserted between the text widget and the originalparent. This is important to know when setting CwForm attachments, because inthis case the attachments must be set on the text widget’s parent (the scrolledwindow) rather than the text widget itself. See “Scrolled lists” on page 188 for anexample. See “Form widgets” on page 167 for a description of attachments.

Two of the text widget’s resources are editMode and wordWrap. The editModeresource specifies whether the widget supports single-line or multiline editing oftext. It can be set to XmSINGLELINEEDIT (the default) or XmMULTILINEEDIT.The wordWrap resource specifies whether lines are to be broken at word breaks sothat text does not go beyond the right edge of the window. The default setting forwordWrap is false.

Tip: Word wrap and horizontal scrolling are incompatible. In order for word wrapto work, the text widget must be configured without a horizontal scroll bar bysetting the scrollHorizontal resource to false.

The following example creates a scrollable, multiline text widget with word wrapon.

| shell text |shell := CwTopLevelShell

createApplicationShell: 'shell'argBlock: [:w |

w title: 'Text Widget Example'].

text := shell"A scrollable text widget is created and managed."

Text Widget Example

Edit me!

createScrolledText: 'text'argBlock: [:w |

w

162 IBM Smalltalk: Programmer’s Reference

Page 177: IBM Smalltalk: Programmer's Reference

"The widget is configured to support multiline editing and word wrap."editMode: XmMULTILINEEDIT;scrollHorizontal: false;wordWrap: true].

"The contents of the widget are set to a sample string."text setString: 'Edit me!'.text manageChild.shell realizeWidget.

CwText widgets also have resources to control the initial number of rows andcolumns they contain, the position of the insertion point, the width of the tabcharacter, and whether or not the CwText is editable. For a complete list of CwText’sresources and callbacks, see “Appendix A. Widget resources and callbacks” onpage 469. CwText widgets can also set, get, cut, copy, and paste a selection, scroll toa given line, and insert or replace text at a given position.

A CwText widget has input focus when it can accept keyboard input. A CwTextusually provides some visual indication that the widget has focus, such asdisplaying the insertion position as a flashing I-beam or drawing a thicker border.Application developers can add a focusCallback or a losingFocusCallback to a CwTextif additional behaviour is required when the widget either gains or loses focus. Forfurther discussion on the concept of focus, see “Shell widgets” on page 158. Youcan see an example of a losingFocusCallback with a single-line text widget in“Example: a primitive extended widget” on page 203.

Two other callbacks provided by CwText widgets are modifyVerifyCallback, calledjust before text is deleted from or inserted into a CwText, and valueChangedCallback,called after text is deleted from or inserted into a CwText. The following exampleuses a modifyVerifyCallback to allow only uppercase letters to be entered into asingle-line CwText.

Object subclass: #TextExampleinstanceVariableNames: ''classVariableNames: ''poolDictionaries: 'CwConstants '

CAPS ONLY

Text Widget Example

open| shell text |

shell := CwTopLevelShellcreateApplicationShell: 'shell'argBlock: [:w | w title: 'Text Widget Example'].

text := shellcreateText: 'text'argBlock: [:w | w columns: 18].

textaddCallback: XmNmodifyVerifyCallbackreceiver: selfselector: #modifyVerify:clientData:callData:clientData: nil.

text manageChild.

shell realizeWidget.

modifyVerify: widget clientData: clientData callData: callData

"Update the stored version of the string in the callData, so that thetext widget inserts capital letters instead of the real text typed orpasted by the user."

callData text: callData text asUppercase

Chapter 7. Common Widgets 163

Page 178: IBM Smalltalk: Programmer's Reference

Drawing area widgetsThe drawing area (CwDrawingArea) widget provides an application with an area inwhich application-defined graphics can be drawn using Common Graphicsoperations such as fillRectangle:, drawArc:, and drawString:. Consult the CommonGraphics chapter for an explanation of drawing and other graphics operations.

Drawing is actually done on the CgWindow associated with the CwDrawingArea.Every CwWidget has a corresponding CgWindow, obtained by sending window to awidget, that can be used for drawing. Although any widget can be drawn on inthis manner, CwDrawingArea widgets are typically used because they provideadditional drawing-related functionality. Create CwDrawingArea widgets using thecreateDrawingArea:argBlock: convenience method.

A CwDrawingArea can be told to notify the application with an expose callbackwhenever a part of the drawing area needs to be redrawn. The expose callbackcontains an expose event with a rectangle describing the damaged area of thewidget’s CgWindow.

The following example is a simple application that draws a mandala. (A mandalais a drawing of lines connecting each of a given number of points on thecircumference of a circle to every other such point.) Four callbacks that are oftenused in conjunction with drawing areas are illustrated: exposeCallback (describedabove), resizeCallback, inputCallback, and destroyCallback.

The resize callback is called when the drawing area changes size, usually due to achange in the size of a parent widget. If an expose callback is triggered as a resultof a resize, the resize callback is always sent before the expose callback. It ispossible for the resize callback to be run before the window has been realized. Theresize callback handler should handle the case where the window message returnsnil.

The input callback is called when a mouse button is pressed or released inside thewidget or a key on the keyboard has been pressed or released. The destroycallback, run when the widget is about to be destroyed, is a good place to free anygraphics resources that have been allocated for drawing.Object subclass: #DrawingAreaExampleinstanceVariableNames: 'gc radius segments 'classVariableNames: ''poolDictionaries: 'CwConstants CgConstants '

example1"Open the drawing area example."

| diameter shell draw |"Initialize the radius instance variable and calculate the diameterof the mandala."

radius := 150.diameter := radius * 2.

shell := CwTopLevelShellcreateApplicationShell: 'shell'argBlock: [:w | w title: 'Drawing Area Example'].

draw := shell"Create a drawing area widget, with its width and height set to thediameter of the mandala"

createDrawingArea: 'draw'argBlock: [:w |

164 IBM Smalltalk: Programmer’s Reference

Page 179: IBM Smalltalk: Programmer's Reference

wwidth: diameter;height: diameter].

draw manageChild.

draw"Add an expose callback that is run when a portion of the drawing areaneeds redrawing."

addCallback: XmNexposeCallbackreceiver: selfselector: #expose:clientData:callData:clientData: nil;

"Add a resize callback that is run when the drawing area is resizedas a result of the user resizing the shell."

addCallback: XmNresizeCallbackreceiver: selfselector: #resize:clientData:callData:clientData: nil;

"Add an input callback that is run when the drawing area receives akey or mouse button event."

addCallback: XmNinputCallbackreceiver: selfselector: #input:clientData:callData:clientData: nil;

"Add a destroy callback that is run when the drawing area is destroyed.The destroy callback is a good place to free any allocated graphicsresources."

addCallback: XmNdestroyCallbackreceiver: selfselector: #destroy:clientData:callData:clientData: nil.

"Realize the widgets".shell realizeWidget.

expose: widget clientData: clientData callData: callData"Redraw the contents of the drawing area."

gc isNil ifTrue : [gc := widget window

"On the first expose, create a graphics context with a foreground colorof black."

createGC: Nonevalues: nil.

gc setForeground: widget window blackPixel].

callData event count = 0ifTrue: [

segments isNilifTrue: [self recalculateSegments: widget].

widget window"Draw the line segments."

drawSegments: gcsegments: segments].

recalculateSegments: widget"Recalculate the coordinates of the mandala's line segments."

| n points x y |

n := 20.

Chapter 7. Common Widgets 165

Page 180: IBM Smalltalk: Programmer's Reference

points := OrderedCollection new."Calculate the points of the mandala."

0 to: Float pi * 2 by: Float pi * 2 / n do: [:angle |x := (angle cos * radius) rounded + (widget width // 2).y := (angle sin * radius) rounded + (widget height // 2).points add: x@y].

segments := OrderedCollection new."Calculate the line segments of the mandala.Each point is connected to every other point."

1 to: points size - 1 do: [:i |i + 1 to: points size do: [:j |segments add:(CgSegment

point1: (points at: i)point2: (points at: j))]].

resize: widget clientData: clientData callData: callData"The drawing area has been resized."

widget window notNilifTrue: [

"Recalculate the radius of the mandala. Force a recalculation ofsegments on expose."

radius := (widget width min: widget height) // 2.segments := nil].

input: widget clientData: clientData callData: callData"The drawing area has received an input callback (button or key event).Explicitly destroy the widget if one of three things has happened:

- the user typed 'Q' or 'q'.- the user typed 'control-DownArrow'.- the user did a 'shift-click' (shift key pressed, click left

mouse button)."| event quit |

quit := false.event := callData event.

"$Q, $q, or control-End typed"event type = KeyPress

ifTrue: [quit := ('Qq' includes: event character)

or: [(event state & ControlMask) = ControlMaskand: [event keysym = XKdownarrow]]].

"Shift-click"(event type = ButtonPress and: [event button = 1])

ifTrue: [quit := (event state & ShiftMask) = ShiftMask].

quit ifTrue: [widget shell destroyWidget].

destroy: widget clientData: clientData callData: callData"The drawing area has been destroyed.

Free any allocated graphics resources."gc notNil ifTrue: [

"Free the graphics context."gc freeGC].

Adding an event handler to a drawing areaIn the following example, a button press event handler is used to detectdouble-clicks in a drawing area. The open method creates the widgets, and thebuttonPress:clientData:event: method handles button press events.

166 IBM Smalltalk: Programmer’s Reference

Page 181: IBM Smalltalk: Programmer's Reference

Object subclass: #DoubleClickinstanceVariableNames: 'clickStartTime 'classVariableNames: ''poolDictionaries: 'CgConstants CwConstants '

open"Create a drawing area inside a shell."

| shell drawingArea |

clickStartTime := 0.shell := CwTopLevelShell

createApplicationShell: 'shell'argBlock: [:w | w title: 'Double-click test'].

(drawingArea := shellcreateDrawingArea: 'draw'argBlock: [:w |

wwidth: 100;height: 100])

manageChild.

drawingAreaaddEventHandler: ButtonPressMaskreceiver: selfselector: #buttonPress:clientData:event:clientData: nil.

shell realizeWidget.

buttonPress: widget clientData: clientData event: event"Detect double click by checking whether the time between successivepresses of the left mouse button is less than the system-defineddouble-click time."

event button = 1ifTrue: [

event time - clickStartTime < widget display doubleClickIntervalifTrue: [

clickStartTime := 0.Transcript cr; show: 'DOUBLE CLICK' ]

ifFalse: [clickStartTime := event time ]].

Tip: Adding a mouse down event handler to a widget that processes mouse eventsinternally, such as a CwPushButton, might result in unpredictable behaviour.To detect double-clicks in a CwList, use the defaultAction callback.

Layout widgetsThe form (CwForm) and row-column (CwRowColumn) widgets are compositewidgets that allow the application to specify how child widgets of the compositeshould be laid out relative to each other and relative to the composite.

Form widgetsCreate form widgets using the createForm:argBlock: convenience method. Positionform widget children by attaching their sides to other objects. Specify attachmentsby setting each child’s leftAttachment, rightAttachment, topAttachment andbottomAttachment resources. A side can be attached either to a given position, toanother widget, or to the edge of the form. The attachment types are listed below.The first four types are the most commonly used. All are described in terms of theleftAttachment, but the same attachment types apply to the other sides, withcorresponding behavior.

XmATTACHNONEDefault. Do not attach this side.

Chapter 7. Common Widgets 167

Page 182: IBM Smalltalk: Programmer's Reference

XmATTACHFORMAttach the left side of the child to the left side of the form.

XmATTACHWIDGETAttach the left side of the child to the right side of the widget specified inthe leftWidget resource.

XmATTACHPOSITIONAttach the left side of the child to a relative position in the form. Thisposition is specified by the leftPosition resource, and is a fractional value ofthe width of the form, with the default range being from 0 to 100. Theposition is relative to the left side of the form for left and right attachments,and to the top of the form for top and bottom attachments. A position of 0places the left side of the child at the left side of the form. A position of100 places the left side of the child at the right side of the form.

XmATTACHOPPOSITEFORMAttach the left side of the child to the right side of the form.

XmATTACHOPPOSITEWIDGETAttach the left side of the child to the left side of the widget specified inthe leftWidget resource.

XmATTACHSELFAttach the left side of the child to its initial position in the form.

Tip: It is an error for attachments to be recursively defined. For example, if awidget A is attached to a widget B, then widget B. cannot be attached towidget A. More generally, there must not be a cycle in the widgetattachments.

If the attachment is XmATTACHFORM or XmATTACHWIDGET, an offset can alsobe specified that adds space between the side of the widget and the object towhich it is attached. Offsets are specified by the leftOffset, rightOffset, topOffset, andbottomOffset resources. Offsets are specified in units of pixels.

Tip: The results are undefined if an offset setting is used with an attachment typeof XmATTACHPOSITION.

If attachments have been set on all sides of a widget, the size of the widget iscompletely determined by the form and the other child widgets. However, if a sideis left unattached, the widget will use its preferred size in the correspondingdimension. This is useful for allowing widgets to size themselves automaticallybased on their font size, contents, and other attributes.

Some convenience methods, such as those used to create a scrolled list or a scrolledtext, actually create a widget subtree, but instead of returning the root of thesubtree, the child is returned. In these cases, the form attachments must be set onthe returned widget’s parent, rather than on the widget itself. For an example, see“Scrolled lists” on page 188.

The following diagram illustrates a form containing a drawing area and a textwidget. The right side of the drawing area is attached to a position two-thirds (67per cent) of the way from left to right. The left side of the text widget is attachedto the right side of the drawing area. The remaining sides of the text and drawingarea widgets are attached to the form. The widgets are offset from each other bytwo pixels. (Offsets in the diagram have been exaggerated to show the

168 IBM Smalltalk: Programmer’s Reference

Page 183: IBM Smalltalk: Programmer's Reference

attachments.)

Drawing area widget Text widget

To form

To form

To form

To form

To form

To form

To drawing area

To position

Form widget

Shell widget

Form Example

The following code example creates the widget tree illustrated above:| shell form drawing text |

shell := CwTopLevelShellcreateApplicationShell: 'shell'argBlock: [:w | w title: 'Form Example'].

form := shellcreateForm: 'form'argBlock: nil.

form manageChild.

drawing := formcreateDrawingArea: 'drawing'argBlock: [:w |

wborderWidth: 1;width: 200;height: 200;leftAttachment: XmATTACHFORM;leftOffset: 2;

rightAttachment: XmATTACHPOSITION;rightPosition: 67;topAttachment: XmATTACHFORM;topOffset: 2;bottomAttachment: XmATTACHFORM;bottomOffset: 2].

drawing manageChild.

text := formcreateText: 'text'argBlock: [:w |

wleftAttachment: XmATTACHWIDGET;leftWidget: drawing;leftOffset: 2;rightAttachment: XmATTACHFORM;rightOffset: 2;topAttachment: XmATTACHFORM;topOffset: 2;bottomAttachment: XmATTACHFORM;bottomOffset: 2].

text manageChild.shell realizeWidget.

Row-column widgetsThe row-column widget (CwRowColumn) positions its children in rows or columns.CwRowColumn widgets are frequently used to lay out groups of buttons, including

Chapter 7. Common Widgets 169

Page 184: IBM Smalltalk: Programmer's Reference

pop-up and pull-down menus. You can also use them to lay out widgets in a table.Create row-column widgets using the createRowColumn:argBlock: conveniencemethod.

Some commonly used row-column resources are the orientation, marginWidth,marginHeight and spacing resources. The orientation resource specifies that the layoutis either row major or column major. In a column major layout, specified byXmVERTICAL, the children are laid out in columns top to bottom. In a row majorlayout, specified by XmHORIZONTAL, the children are laid out in rows. Thedefault orientation is XmVERTICAL. The marginWidth and marginHeight resourcesspecify the size of the margin between the child widgets and the edges of therow-column. The spacing resource specifies the spacing between child widgets.

In the following illustration, the buttons on the left are organized in a row-columnwidget. The row-column and the drawing area are contained in a form, similar tothe previous example.

RowColumn Example

Dining Room

Kitchen

Living Room

Washroom

Bedroom

Workshop

The following code creates the example shown above:| shell form rowColumn drawing |shell := CwTopLevelShell

createApplicationShell: 'shell'argBlock: [:w | w title: 'RowColumn Example'].

form := shellcreateForm: 'form'argBlock: nil.

form manageChild.

rowColumn := formcreateRowColumn: 'rooms'argBlock: [:w |

worientation: XmVERTICAL;marginWidth: 10;marginHeight: 10;spacing: 20;leftAttachment: XmATTACHFORM;topAttachment: XmATTACHFORM;bottomAttachment: XmATTACHFORM].

rowColumn manageChild.

#('Kitchen' 'Dining Room' 'Living Room' 'Washroom' 'Bedroom' 'Workshop')do: [:room |

(rowColumncreatePushButton: roomargBlock: nil)

manageChild].

170 IBM Smalltalk: Programmer’s Reference

Page 185: IBM Smalltalk: Programmer's Reference

drawing := formcreateDrawingArea: 'drawing'argBlock: [:w |

wborderWidth: 1;width: 300;leftAttachment: XmATTACHWIDGET;leftWidget: rowColumn;leftOffset: 2;rightAttachment: XmATTACHFORM;rightOffset: 2;topAttachment: XmATTACHFORM;topOffset: 2;bottomAttachment: XmATTACHFORM;bottomOffset: 2].

drawing manageChild.shell realizeWidget.

Button and label widgetsThe Common Widgets subsystem allows applications to create static text labels(CwLabel) and several types of buttons:v Push buttons (CwPushButton)v Cascade buttons (CwCascadeButton)v On/off toggle buttons (CwToggleButton)v Application-drawn buttons (CwDrawnButton)

Buttons and labels can display either strings, pixmaps or icons as their contents,depending on the value of the labelType resource. See “Icon and pixmap label andbutton widgets” on page 176 for more detail on labelType.

The following resources define the visual appearance of labels and buttons: x, y,height, width, marginTop, marginBottom, marginHeight, marginWidth, marginLeft, andmarginRight. These are illustrated in the following figure:

marginHeightmarginTop

marginBottommarginHeight

width

heig

ht

(x,y)

mar

ginW

idth

mar

ginL

eft

mar

ginR

ight

mar

ginW

idth

Widget Label

The marginTop, marginBottom, marginRight, and marginLeft resources are typicallycontrolled by subclasses of CwLabel or by the label’s parent. For example, aCwToggleButton could increase marginRight to make space for the toggle indicator.The marginHeight and marginWidth resources are usually left alone by subclasses,and can be manipulated by the application if desired.

Tip: The margin resource settings indicate the preferred appearance of the widget.They might be ignored if they are not supported by the platform or conflictwith the platform’s look and feel.

By default, the name given in a label or button creation message is used as thewidget’s labelString. The contents of a label or button widget are changed using thelabelString: resource method.

Chapter 7. Common Widgets 171

Page 186: IBM Smalltalk: Programmer's Reference

CwLabel provides accelerator and acceleratorText resources for adding an acceleratorkey to a toggle button or push button that is in a pop-up or pull-down menu. Anaccelerator key will activate a button at any time, provided the parent menu ismanaged. The accelerator resource is set to an instance of CwAccelerator createdusing the mask:keysym: class method, which takes the following arguments:

mask The modifier key mask, which consists of a logical-OR of zero or more ofthe following: Mod1Mask, ControlMask, or ShiftMask.

keysymThe unmodified key, which must be a lowercase letter or special key,represented by a CwConstants ‘XK’ keysym value.

The acceleratorText resource describes the string that is displayed beside the buttonin the menu.

Note: On some platforms, accelerators are case sensitive. A keysym value of XKnonly fires with a lowercase accelerator key press.

Static label widgetsCreate static label widgets (CwLabel) using the createLabel:argBlock: conveniencemethod. Static labels do not provide any special callbacks. The following codecreates the example to its right.

| shell label |shell := CwTopLevelShell

createApplicationShell: 'shell'argBlock: [:w | w title: 'Label Example'].

label := shellcreateLabel: 'label'argBlock: nil.

This is a label.

label labelString: 'This is a label.'.label manageChild.shell realizeWidget.

Push-button widgetsCreate push-button widgets (CwPushButton) using the createPushButton:argBlock:convenience method.

Push

Push buttons call their activate callback when they are pressed and released.

In the following example, three buttons are created in a row-column. An activatecallback has been added to each button. The same callback message is used in allthree cases. The client data of the callback is used to identify which button waspressed. For simplicity, the shell is not shown in the diagram.

| shell rowColumn row b1 b2 b3 |shell := CwTopLevelShell

createApplicationShell: 'Test'argBlock: nil.

rowColumn := shellcreateRowColumn: 'buttons'argBlock: nil.

rowColumn manageChild.

Top

Middle

Bottom

172 IBM Smalltalk: Programmer’s Reference

Page 187: IBM Smalltalk: Programmer's Reference

b1 := rowColumncreatePushButton: 'Top'argBlock: nil.

b1addCallback: XmNactivateCallbackreceiver: selfselector: #button:clientData:callData:clientData: 'top'.

b1 manageChild.

b2 := rowColumncreatePushButton: 'Middle'argBlock: nil.

b2addCallback: XmNactivateCallbackreceiver: selfselector: #button:clientData:callData:clientData: 'middle'.

b2 manageChild.

b3 := rowColumncreatePushButton: 'Bottom'argBlock: nil.

b3addCallback: XmNactivateCallbackreceiver: selfselector: #button:clientData:callData:clientData: 'bottom'.

b3 manageChild.shell realizeWidget.

Here is the activate callback used in the code:button: widget clientData: clientData callData: callData"A button has been pressed."

Transcript cr; show: 'The ', clientData, ' button has been pressed.'

Toggle-button widgetsCreate toggle-button widgets (CwToggleButton) using the createToggleButton:argBlock:convenience method.

Toggle buttons have two states: on and off. The state of a toggle button can bequeried and changed using the getState and setState:notify: messages, respectively.Toggle buttons call their valueChanged callback when their state is changed.

Toggle buttons are typically used to create radio-button and check-box groupsusing row column convenience methods described in the next sections. Thetoggle-button indicatorType resource controls whether the toggle button has aradio-button or a check-box appearance. When the resource value is set toXmONEOFMANY, the button has a radio-button appearance. When the value is setto XmNOFMANY, the button has a check-box appearance.

Tip: On some platforms, toggle buttons turn on when they are given focus.

Chapter 7. Common Widgets 173

Page 188: IBM Smalltalk: Programmer's Reference

Radio-button groupsA row-column widget containing several toggle-button widgets (CwToggleButton)can be configured to have radio-button behavior.

Hello

Bonjour

Hola

When a button is selected in this mode, any other selected buttons in the group areautomatically deselected, leaving only one button selected at any time. TheradioBehavior resource of the CwRowColumn widget controls this behavior.

Create a CwRowColumn with radioBehaviour set to true using the conveniencemethod createRadioBox:argBlock:.

Tip: As a side effect of createRadioBox:argBlock:, the CwRowColumn isHomogeneousresource is set to true. Children of a homogeneous row-column widget mustall be of the same type. In this case, they must all be CwToggleButton widgets.

You can select or deselect a toggle button using the setState:notify: method. Its statecan be queried using the getState method. The valueChanged callback of a togglebutton is run whenever the state of the button changes.

Tip: The valueChanged callback is run when a button is deselected as well as whenit is selected. The state of the widget should be checked in the callback usingthe getState method, or by checking the set field of the callback data.

In the following example, a radio-box row-column is created. Three toggle buttonsare added. The same valueChanged callback is added to each toggle button, withthe client data used to identify the selected button. The resulting radio-buttongroup is shown in the left margin. For simplicity, the shell is not shown.| shell rowColumn button buttonNames initialValues languageNames |shell := CwTopLevelShell

createApplicationShell: 'shell'argBlock: [:w | w title: 'Radio Box Example'].

rowColumn := shellcreateRadioBox: 'radio'argBlock: nil.

rowColumn manageChild.

buttonNames := #('Hello' 'Bonjour' 'Hola').initialValues := (Array with: true with: false with: false).languageNames := #('English' 'French' 'Spanish').

1 to: buttonNames sizedo: [:i |

button := rowColumn

"The state of each toggle button is set on creation accordingto the corresponding value in the initialValues array. In thisexample, Hello is selected."

createToggleButton: (buttonNames at: i)argBlock: [:w | w set:

(initialValues at: i)].

buttonaddCallback: XmNvalueChangedCallbackreceiver: selfselector: #language:clientData:callData:clientData: (languageNames at: i).

button manageChild].

174 IBM Smalltalk: Programmer’s Reference

Page 189: IBM Smalltalk: Programmer's Reference

shell realizeWidget.

The valueChanged callback used by the code is shown below. The selectedlanguage is indicated by the clientData argument. A message is written to thetranscript whenever a new language is chosen.language: widget clientData:clientData callData: callData

"A toggle button has changed state."callData set

ifTrue: [Transcript cr; show: 'The selected language is now ',clientData, '.'].

Check boxesCheck boxes consist of several toggle buttons that present a set of options to theuser. The user can choose none, all, or any combination of the buttons. ACwRowColumn widget can be used to contain the buttons. When the row-column’sradioBehavior resource is false, its default, more than one toggle button can beselected at a time.

The code that follows creates the toggle-button group shown on the right.

| shell rowColumn button buttonNames initialValues |shell := CwTopLevelShell

createApplicationShell: 'shell'argBlock: [:w | w title: 'Check Box Example'].

rowColumn := shellcreateRowColumn: 'group'argBlock: nil.

rowColumn manageChild.

Item1

Item2

Item3

buttonNames := #('Item 1' 'Item 2' 'Item 3').initialValues := (Array with: false with: true with: true).

1 to: buttonNames sizedo: [:i |

button := rowColumncreateToggleButton: (buttonNames at: i)

"The state of each toggle button is set on creation according to thecorresponding value in the initialValues array. In this example, Item2and Item3 are both selected, and this is indicated by an X."

argBlock: [:w | w set: (initialValues at: i)].button

addCallback: XmNvalueChangedCallbackreceiver: selfselector: #valueChanged:clientData:callData:clientData: nil.

button manageChild].shell realizeWidget.

The valueChanged callback used by the code is shown below. A message is writtento the transcript whenever a button is selected or deselected.valueChanged: widget clientData:clientData callData: callData

"A toggle button has changed state."Transcript cr; show: widget labelString, ' has been '.callData set

ifTrue: [Transcript show: 'selected.']ifFalse: [Transcript show: 'deselected.'].

Chapter 7. Common Widgets 175

Page 190: IBM Smalltalk: Programmer's Reference

Icon and pixmap label and button widgetsThe contents of CwLabel, CwPushButton,CwCascadeButton, and CwToggleButtonwidgets can be a string, an icon or a pixmap.

?When the labelType resource is XmSTRING, the labelString resource specifies thestring to display. The default type is string. When labelType is XmICON, labelIconspecifies the icon to use, and when labelType is XmPIXMAP, labelPixmap specifiesthe pixmap to display. Consult “Using pixmaps” on page 106 for more informationon using pixmaps and icons.

The code below creates a widget tree containing a pixmap button. Icon buttonsand labels are created in a similar manner. Note that pixmap is an instance variable.| shell button questionMark pixmap |shell := CwTopLevelShell

createApplicationShell: 'shell'argBlock: [:w | w title: 'Pixmap Button Example'].

button := shell"Create the push button."

createPushButton: 'button'argBlock: nil.

buttonaddCallback: XmNdestroyCallbackreceiver: selfselector: #destroy:clientData:callData:clientData: nil.

questionMark :="Initialize the data for the pixmap."

#(0 0 0 0 255 0 192 255 3 224 255 7240 255 15 248 255 31 248 255 31 252 255 63252 227 63 252 193 63 252 193 63 252 193 63248 224 63 248 240 31 0 248 31 0 252 150 252 7 0 254 3 0 254 3 0 254 10 254 1 0 252 0 0 252 0 0 0 00 252 0 0 254 1 0 254 1 0 254 10 254 1 0 252 0 0 0 0 0 0 0).

"Realize the shell without mapping it so we have access to thebutton's window and palette without making the shell appear."

shellmappedWhenManaged: false;realizeWidget.

pixmap := button screen rootWindow"Create the pixmap. Note that the background color of the pixmap will bethe same as the button's background color."

createPixmapFromBitmapData: questionMarkwidth: 24height: 32fg: button window blackPixelbg: (button window getPalette

nearestPixelValue: button backgroundColor)depth: button depth.

buttonsetValuesBlock: [:w |

w

176 IBM Smalltalk: Programmer’s Reference

Page 191: IBM Smalltalk: Programmer's Reference

"Complete the button's initialization."labelType: XmPIXMAP;labelPixmap: pixmap].

button manageChild.

shell mapWidget.

destroy: widget clientData: clientData callData: callData

pixmap freePixmap.

Application-drawn buttonsApplication-drawn button widgets (CwDrawnButton) enable the application todraw arbitrary graphics on a button. Drawn buttons behave like push buttonsexcept that they can be drawn on like drawing area widgets. See the examplebelow.

As with the push-button widget, the application can add an activate callback to berun when the button is pressed. As with the drawing area widget, expose and resizecallbacks can be added to notify the application when the button requiresredrawing and when it has changed size. Consult “Drawing operations” on page89 chapter for more information on drawing graphics.

In the code below, a drawn button is created and drawn.Object subclass: #DrawnButtonExampleinstanceVariableNames: 'gc 'classVariableNames: ''poolDictionaries: 'CwConstants CgConstants '

open| shell button |

shell := CwTopLevelShellcreateApplicationShell: 'shell'argBlock: [:w | w title: 'Drawn Button Example'].

button := shellcreateDrawnButton: 'button'argBlock: nil.

buttonaddCallback: XmNactivateCallbackreceiver: selfselector: #button:clientData:callData:clientData: nil;addCallback: XmNexposeCallbackreceiver: selfselector: #expose:clientData:callData:clientData: nil;

addCallback: XmNdestroyCallbackreceiver: selfselector: #destroy:clientData:callData:clientData: nil.

button manageChild.shell realizeWidget.

Chapter 7. Common Widgets 177

Page 192: IBM Smalltalk: Programmer's Reference

gc := button windowcreateGC: Nonevalues: nil.

activate: widget clientData: clientData callData: callData"The drawn button has been pressed."

Transcript cr; show: 'The pixmap button has been pressed.'.

expose: widget clientData: clientData callData: callData"The drawn button has been exposed. Redraw the button."

| x |

callData event count = 0ifTrue: [

0 to: 10 do: [:i |x := widget width * i // 10.

widget windowdrawLine: gcx1: xy1: 0x2: widget width - xy2: widget height - 1]].

destroy: widget clientData: clientData callData: callDatagc freeGC.

MenusMenus are used extensively in most graphical user interfaces. Common Widgetsprovides protocol for pop-up menus, option menus and menu bars containingpull-down menus. Menu bars and menus are built using CwRowColumn widgets.Items in a menu bar are cascade buttons, which are buttons that drop down amenu when selected. Pop-up menus and pull-down menus within a menu bar arealso represented by CwRowColumn widgets. Items within a menu are separators,labels, push buttons, toggle buttons, or cascade buttons for submenus. There aretwo ways to create menus: using simple menu convenience methods and usingnon-simple widget creation methods.

Greying out buttonsWhen you create buttons, they are active by default. You can set the state ofbuttons (sensitive or not sensitive) using the method setSensitive: or sensitive:. If theargument is true, then the button will be active. If the argument is false, then thebutton will be deactivated (greyed out).

You can query the state of a button by sending it the message sensitive.

Note that any button can be deactivated, including menu buttons.

The following example creates two buttons, then deactivates one of them. You canexecute this example in a Workspace or the Transcript.| shell button1 button2 rowColumn |shell := CwTopLevelShell

createApplicationShell: 'Shell'argBlock: nil.

rowColumn := shellcreateRowColumn: 'buttons'argBlock: nil.

rowColumn manageChild.

button1 := rowColumn

178 IBM Smalltalk: Programmer’s Reference

Page 193: IBM Smalltalk: Programmer's Reference

createPushButton: 'One'argBlock: nil.

button1 manageChild.

button2 := rowColumncreatePushButton: 'Two'argBlock: nil.

button2 manageChild.

shell realizeWidget.button2 sensitive: false.

Simple menus and menu barsSimple menu convenience methods create row-columns which are configured assimple menu bars or simple menus. These convenience methods are the preferredmethod of creating a menu system for the following reasons:v Simple menus are easier to programv Simple menus use fewer operating system resources on some platformsv Simple menus are created faster on some platforms

Create a simple menu or menu bar using one of the following simple menuconvenience methods:

createSimpleMenuBar:argBlock:Creates a simple menu bar

createSimplePulldownMenu:argBlock:Creates a simple pull-down menu

createSimplePopupMenu:argBlock:Creates a simple pop-up menu

The menu or menu bar is entirely defined by the creation message and resourcesset in the argBlock. The resources that can be set to define a simple menu orsimple menu bar are listed in the following table. The first three resources arearrays whose elements each represent a single menu bar item. These arrays mustcontain the same number of items, and must describe corresponding items in thesame sequence, in order for the menu or menu bar to be correctly defined.

Table 37. Simple Menu and Simple Menu Bar Resources

Resource Name Description Value(s)

buttons An array of strings specifying theitem labels.

Stringv String is ignored for

separators, but must bepresent.

Chapter 7. Common Widgets 179

Page 194: IBM Smalltalk: Programmer's Reference

Table 37. Simple Menu and Simple Menu Bar Resources (continued)

Resource Name Description Value(s)

buttonType An array of constants specifyingthe item types.

XmCASCADEBUTTONv A cascade button for a

submenuv Default type for menu bar

XmPUSHBUTTONv A normal menu itemv Default type for menu

XmSEPARATORv A line separating menu items

XmDOUBLESEPARATORv A double line separating items

XmRADIOBUTTONv A radio-button menu item

XmCHECKBUTTONv A check-button menu item

XmTITLEv A title menu item

buttonMnemonics An array of characters specifyingthe item mnemonics.

Characterv Character is ignored if it is not

in the corresponding itemstring. The code ″0asCharacter″ is useful forspecifying no mnemonic.

postFromButton Only used for pull-down menucreation. An integer specifyingthe zero-based index of thecascade button specified as theparent of the pull-down menu.

Integer

Row-columns configured as simple menus or menu bars provide a simple callbackthat is run whenever any item in a menu is selected. The clientData argument ofthe callback method is an integer indicating the zero-based position of the selectedbutton in the menu (separators are ignored when determining the buttonpositions).

Tip: When you add a simple callback to a row-column configured as a simplemenu or simple menu bar, the clientData argument is ignored.

Creating a menu bar and pull-down menu using simple menuprotocol

The following code creates a window with a menu bar containing the menuillustrated at right. Simple menu creation methods are used.

| shell main menuBar fileMenu |shell := CwTopLevelShell

createApplicationShell: 'shell'argBlock: [:w |

w title: 'Pull-down Menu Example'].

180 IBM Smalltalk: Programmer’s Reference

Page 195: IBM Smalltalk: Programmer's Reference

main := shellcreateMainWindow: 'main'argBlock: nil.

main manageChild.

"A simple menu bar is created as a child of the main window.The label for the button and its mnemonic is specified. In amenu bar, all items are cascade buttons, so the buttonTyperesource need not be explicitly set."menuBar := main

createSimpleMenuBar: 'bar'argBlock: [:w | w

buttons: #('File');buttonMnemonics: #($F)].

menuBar manageChild.

fileMenu := menuBar"A simple pull-down menu is created as a child of the menu bar."

createSimplePulldownMenu: 'file'argBlock: [:w |

wbuttons: #('Open' 'separator' 'Close');buttonType: (Array

"Two normal items and a separator are specified"with: XmPUSHBUTTONwith: XmSEPARATORwith: XmPUSHBUTTON);

buttonMnemonics: (Arraywith: $Owith: 0 asCharacterwith: $C);

"The menu is attached to (dropped down from) the first(0th) item i the menu bar: the File cascade button."

postFromButton: 0].

fileMenu"A simple callback runs whenever an item is selected from the File menu."

addCallback: XmNsimpleCallbackreceiver: selfselector: #fileMenu:clientData:callData:clientData: nil.

mainsetAreas: menuBarhorizontalScrollbar: nilverticalScrollbar: nilworkRegion: nil.

shell realizeWidget.

fileMenu: widget clientData: clientData callData: callData"Execute the desired operation."

self perform: (#(#doOpen #doClose) at: clientData + 1).

Creating a secondary menu using simple menu protocolThe following code creates a window with a menu bar containing the menu andsecondary menu illustrated at right. The menu bar contains one item, File, thatdrops down a menu containing two items, Open and Close. If Close is selected, thefileMenu:clientData:callData: method is invoked. If Open is selected, a secondarymenu containing three items is dropped down. Choosing one of the three itemsinvokes the openMenu:clientData:callData: method.

Chapter 7. Common Widgets 181

Page 196: IBM Smalltalk: Programmer's Reference

| shell main menuBar fileMenu openMenu |

shell := CwTopLevelShellcreateApplicationShell: 'shell'argBlock: [:w |

w title: 'Secondary Menu Example'].

main := shellcreateMainWindow: 'main'argBlock: nil.

main manageChild.

menuBar := maincreateSimpleMenuBar: 'bar'argBlock: [:w |

w

"File defaults to a cascade button because it is in a menu bar."buttons: #('File');buttonMnemonics: #($F)].

menuBar manageChild.

fileMenu := menuBarcreateSimplePulldownMenu: 'file'argBlock: [:w |

wbuttons: #('Open' 'separator' 'Close');

"Open must be explicitly created as a cascade button, becausebuttons in a menu default to push buttons."

buttonType: (Arraywith: XmCASCADEBUTTONwith: XmSEPARATORwith: XmPUSHBUTTON);

buttonMnemonics: (Arraywith: $Owith: 0 asCharacterwith: $C);

postFromButton: 0].

fileMenuaddCallback: XmNsimpleCallbackreceiver: selfselector: #fileMenu:clientData:callData:clientData: nil.

openMenu := fileMenu"The secondary pull-down menu is created as a child of fileMenu."

createSimplePulldownMenu: 'open'argBlock: [:w |

wbuttons: #('Read only' 'Write only' 'Read write');

"The secondary menu is activated when the 0th item from fileMenu is selected(Open)."

postFromButton: 0].

openMenuaddCallback: XmNsimpleCallbackreceiver: selfselector: #openMenu:clientData:callData:clientData: nil.

mainsetAreas: menuBarhorizontalScrollbar: nilverticalScrollbar: nilworkRegion: nil.

shell realizeWidget

182 IBM Smalltalk: Programmer’s Reference

Page 197: IBM Smalltalk: Programmer's Reference

fileMenu: widget clientData: clientData callData: callData"Execute the desired operation."self perform: (#(#doNothing #doClose) at: clientData + 1).

openMenu: widget clientData: clientData callData: callData"Execute the desired operation."self

perform: (#(#doOpenReadOnly #doOpenWriteOnly #doOpenReadWrite)at: clientData + 1).

Creating a pop-up menu using simple menu protocolA pop-up menu is independent of a menu bar. It is popped up in response to amouse button-3 press, or release, depending on the platform. In order for theapplication to be notified of the mouse button event, an event handler must beadded to the appropriate widget.

Tip: Some platforms cause pop-up menus to appear on a mouse up event, andsome on a mouse down event. The correct event for the platform must beused, or unpredictable behavior might result. To ensure that the correct eventis used, specify ButtonMenuMask as the event mask when adding the eventhandler.

The open method of the class below opens a window containing a label widget.When a menu is requested over the label, a pop-up menu (shown at right)appears. The pop-up menu is created using a simple menu creation method. Themenu is popped up by managing the row-column widget that represents themenu. It is automatically unmanaged when the menu is canceled by the user.

"This class illustrates the use of pop-up menus. Note thatthe pop-up menu is kept in an instance variable so that itcan be referenced by the button event handler."Object subclass: #PopupMenuExample

instanceVariableNames: 'menu 'classVariableNames: ''poolDictionaries: 'CwConstants '

open"Open the pop-up menu example."

| shell label |

shell := CwTopLevelShellcreateApplicationShell: 'shell'argBlock: [:w | w title: 'Popup Menu Example'].

label:= shellcreateLabel: 'main'argBlock: [:w | w labelString:

'Push the menu button over this message'].

label"An event handler is added to the label widget. ButtonMenuMask labelindicates that the event handler should be activate when the menubutton on the mouse is pressed or released."

addEventHandler: ButtonMenuMask

receiver: selfselector: #button:clientData:event:clientData: nil.

label manageChild.

"The pop-up menu is created. Note that the menu is not managed at thisstage. It will be managed when the event handler pops the menu up."menu := label

createSimplePopupMenu: 'menu'

Chapter 7. Common Widgets 183

Page 198: IBM Smalltalk: Programmer's Reference

argBlock: [:w |w

buttons: #('Add' 'Change' 'Delete')].

"Three menu items are specified. A callback is registered,to be run when an item is selected."menu

addCallback: XmNsimpleCallback

receiver: selfselector: #menuItem:clientData:callData:clientData: nil.

"When the shell is realized, the shell and the label widgetsappear, but the menu does not, because it is not managed."shell realizeWidget

button: widget clientData: clientData event: event"Handle a menu button press event. The call data event structure ischecked for a mouse-button press. If it was not the menu button,the menu is not popped up."

event button = 3 ifFalse: [|self]."Position and pop up the menu by managing it."menu"The menu is positioned using the event object. It is popped up bymanaging it."

menuPosition: event;manageChild

menuItem: widget clientData: clientData callData: callData"Display the index of the selected menu item in the transcript."

Transcript cr; show: 'Menu item ', clientData printString,' was selected from the pop-up menu.'

Non-simple menus and menu barsThe other way to create a menu or menu bar is to create a CwRowColumn widgetconfigured as a menu or menu bar, and add individual button and separatorwidgets for the menu items. Convenience methods are provided for creatingCwRowColumn widgets that behave as menu bars or as pop-up and pull-downmenus. Although non-simple menus allow separate callbacks to be registered foreach menu item, they are more cumbersome to program than simple menus.

Non-simple menu exampleThe following code creates a window with a menu bar containing the same Filemenu illustrated in “Creating a menu bar and pull-down menu using simple menuprotocol” on page 180, except that this time, non-simple widget creation methodsare used.| shell main menuBar menu1 menu1Title item1 item2 item3 |shell := CwTopLevelShell

createApplicationShell: 'shell'argBlock: [:w | w title: 'Pull-down Menu Example'].

main := shellcreateMainWindow: 'main'argBlock: nil.

main manageChild.

menuBar := main"First, a menu bar is created as a child of the main window."

createMenuBar: 'bar'argBlock: nil.

menuBar manageChild.

184 IBM Smalltalk: Programmer’s Reference

Page 199: IBM Smalltalk: Programmer's Reference

menu1 := menuBar"Second, a pull-down menu is created as a child of the menu bar."

createPulldownMenu: 'menu'argBlock: nil.

menu1Title := menuBar"Third, a cascade button is added to the menu bar. It is associatedwith the pull-down menu using the subMenuId: method. The name ofthe cascade button appears in the menu bar. Note that the pull-downmenu is created before the cascade button."

createCascadeButton: 'File'argBlock: [:w |

wsubMenuId: menu1].

menu1Title manageChild.

item1 := menu1"Fourth, a push-button widget is created. The parent is menu1.When the File menu is clicked on, a pull-down menu appearswith Open as the first entry. If Open is selected, anXmNactivateCallback is issued and the messageopen:clientData:callData is sent to the receiver."

createPushButton: 'Open'argBlock: nil.

item1addCallback: XmNactivateCallbackreceiver: selfselector: #open:clientData:callData:clientData: nil.

item1 manageChild.

item2 := menu1"Fifth, a separator widget is created as a child of menu1,to separate the first and third menu items. The separatorTyperesource is set to a single line separator."

createSeparator: 'sep'argBlock: [:w |

wseparatorType: XmSINGLELINE].

item2 manageChild.

item3 := menu1"Finally, another push-button widget is created for the third menu item.If Close is selected, an XmNactivateCallback is issued and the messageclose:clientData:callData: is sent to the receiver."

createPushButton: 'Close'argBlock: nil.

item3addCallback: XmNactivateCallbackreceiver: selfselector: #close:clientData:callData:clientData: nil.

item3 manageChild.

shell realizeWidget.

List widgetsList widgets (CwList) present a list of items and allow the user to select one ormore items from the list. List widgets are created using thecreateList:argBlock:andcreateScrolledList:argBlock: convenience methods. The latter method makes the listscrollable, but otherwise provides basically the same functionality. Scrolled lists arediscussed on “Scrolled lists” on page 188.

The items in the list and the selected items are specified by the items andselectedItems resources, respectively. The selectionPolicy resource specifies the policyfor selecting items. It has four possible settings:

Chapter 7. Common Widgets 185

Page 200: IBM Smalltalk: Programmer's Reference

XmBROWSESELECTAllows only single selection. Behavior might vary from platform toplatform, but normally the selection moves when the mouse is dragged.This is the default selection policy.

XmSINGLESELECTAllows only single selection. Behavior might vary from platform toplatform, but normally the selection remains the same when the mouse isdragged.

XmMULTIPLESELECTAllows multiple items to be selected. The selection of an item is toggledwhen it is clicked on. Clicking on an item does not deselect previouslyselected items.

XmEXTENDEDSELECTAllows multiple items to be selected, either by dragging the selection or byclicking on items with a modifier key held down. Behavior might varyfrom platform to platform, but normally clicking on an item without amodifier key held down deselects all previously selected items.

Tip: On some platforms, browse select and single select work the same way.

List widgets provide several methods for adding, deleting and replacing items andselected items in the list.

The selectionPolicy resource determines which callback is used to notify theapplication of changes in the selection. List widgets support the followingcallbacks:

browseSelectionCallbackExecuted when an item is selected in browse selection mode

singleSelectionCallbackExecuted when an item is selected in single selection mode

multipleSelectionCallbackExecuted when an item or group of items is selected in multiple selectionmode

extendedSelectionCallbackExecuted when an item or group of items is selected in extended selectionmode

defaultActionCallbackExecuted when an item is double clicked (all modes)

The call data of the selection callback specifies the item or items that were selected,and the position(s) of the selected item(s) in the list. Item positions in the list arenumbered starting from one.

Single selection listsIn the following example, the list widget shown at right is created with itsselection policy set to XmSINGLESELECT. A single selection callback is added, tocorrespond with the selection policy.

186 IBM Smalltalk: Programmer’s Reference

Page 201: IBM Smalltalk: Programmer's Reference

| items shell list |items := #('item1' 'item2' 'item3' 'item4' 'item5').

shell := CwTopLevelShellcreateApplicationShell: 'shell'argBlock: nil.

list := shellcreateList: 'list'argBlock: [:w |

wselectionPolicy: XmSINGLESELECT;items: items].

listaddCallback: XmNsingleSelectionCallbackreceiver: selfselector: #singleSelect:clientData:callData:clientData: nil.

list manageChild.

shell realizeWidget.

The call data of the singleSelection callback specifies the item that was selected. Thecallback method below prints the entire callback data on the transcript. Allcomponents of the call data can be retrieved using the corresponding accessormethod.singleSelect: widget clientData: clientData callData: callData

"Print the call data."Transcript cr; show: 'Single selection call data: ',

callData printString

If Item 2 is selected, as in the illustration, the transcript output is as follows:Single selection call data: CwListCallbackData(

reason -> 23item -> 'Item 2'itemPosition -> 2

"These three fields of the callback data are only used for multipleand extended select lists."selectedItems -> nilselectedItemCount -> nilselectedItemPositions -> nil)

Multiple selection listsIn the following example, the list widget shown at right is created with itsselection policy set to XmMULTIPLESELECT. A multiple selection callback isadded, to correspond with the selection policy.

| items shell list |items := #('item1' 'item2' 'item3' 'item4' 'item5').

shell := CwTopLevelShellcreateApplicationShell: 'shell'argBlock: nil.

list := shellcreateList: 'list'argBlock: [:w |

wselectionPolicy: XmMULTIPLESELECT;

Chapter 7. Common Widgets 187

Page 202: IBM Smalltalk: Programmer's Reference

items: items].list

addCallback: XmNmultipleSelectionCallbackreceiver: selfselector: #multipleSelect:clientData:callData:clientData: nil.

list manageChild.shell realizeWidget.

The call data of the multipleSelection callback specifies the items that were selected.The callback method below prints the entire callback data on the transcript. Allcomponents of the call data can be retrieved using the corresponding accessormethod.multipleSelect: widget clientData: clientData callData: callData

"Print the call data."Transcript cr; show: 'Multiple selection call data: ',

callData printString

If Item 2 and Item 3 were selected in order, as in the illustration, the transcriptoutput would be:Multiple selection call data: CwListCallbackData(

reason -> 24item -> 'Item 3'itemPosition -> 3selectedItems -> OrderedCollection ('Item 2' 'Item 3')selectedItemCount -> 2selectedItemPositions -> OrderedCollection(2 3))

Scrolled listsA scrolled list is a CwList widget with scrolling capability. All resources andcallbacks associated with lists can be applied to scrolled lists. The scrollingmechanism is handled automatically.

Item 1

Item 4Item 5

Item 2Item 3

Creating a scrolled list inserts a CwScrolledWindow parent between the list and thereceiver of the creation message. In other words, createScrolledList:argBlock: returnsan instance of CwList (the child of a CwScrolledWindow); however, theCwScrolledWindow is the child of the form. Form attachment messages musttherefore be sent to the CwList’s parent.

In the following example, a scrolled list widget is created as a child of a form. Thelist selection policy is set to XmSINGLESELECT. A singleSelection callback is added,corresponding to the selection policy.| items shell form list |items := OrderedCollection new."20 items are initialized as the list contents."1 to: 20 do: [:i |

items add: 'Item ', i printString].

shell := CwTopLevelShellcreateApplicationShell: 'shell'argBlock: [:w | w title: 'Scrolled List Example'].

188 IBM Smalltalk: Programmer’s Reference

Page 203: IBM Smalltalk: Programmer's Reference

form := shellcreateForm: 'form'argBlock: nil.

form manageChild.

list := form"Create the scrolled list. The list widget is answered, not the scrolled window."

createScrolledList: 'list'argBlock: [:w |

w"Set the scrolling policy to single selection, the number of visible itemsto one-half of the number of items, and the list's items to items."

selectionPolicy: XmSINGLESELECT;visibleItemCount: items size // 2;items: items].

listaddCallback: XmNsingleSelectionCallbackreceiver: selfselector: #singleSelect:clientData:callData:clientData: nil.

list manageChild.

"Note that the attachments are set on the parent of the list (whichis a CwScrolledWindow). The scrolled window is the child of the form,not the list widget."list parent setValuesBlock: [:w |

wtopAttachment: XmATTACHFORM;topOffset: 10;bottomAttachment: XmATTACHFORM;bottomOffset: 10;leftAttachment: XmATTACHFORM;leftOffset: 10;rightAttachment: XmATTACHFORM;rightOffset: 10].

shell realizeWidget

Tip: If other children of a form are to be attached to a scrolled list, which is a childof the form, using XmATTACHWIDGET, they must be attached to the scrolledlist’s parent.

Combo-box widgetsLike list widgets, combo-box widgets (CwComboBox) enable the user to select froma list of available items. A combo box also displays the last selected item in a textbox above the list. Combo-box widgets can only have one item selected at a time.Combo-box widgets are created using the createComboBox:argBlock: conveniencemethod.

There are two styles of combo boxes, specified by the comboBoxType resource:

XmDROPDOWNThe list is displayed only when dropped down by pressing a button besidethe text box. When a selection is made, the list disappears (default).

XmSIMPLEThe list is always displayed.

As with the list widget, the items in the combo box are specified by the itemsresource. The application can add a singleSelection callback to be run whenever theselection changes. Several methods are provided for adding, deleting, andreplacing items in the list.

Chapter 7. Common Widgets 189

Page 204: IBM Smalltalk: Programmer's Reference

The contents of the text part of the combo box can be set and retrieved using thesetString: and getString methods.

The following example creates the drop down combo box shown at right. Its itemsare set, the contents of the text box are initialized to the first item, and asingleSelection callback is added.

| items shell combo |items := #('Item 1' 'Item 2' 'Item 3' 'Item 4').

shell := CwTopLevelShellcreateApplicationShell: 'shell'argBlock: [:w |

w title: 'Combo Box Example'].

Item 1Item 2

Item 4Item 3

Item 3

combo := shellcreateComboBox: 'combo'argBlock: [:w |

wcomboBoxType: XmDROPDOWN;items: items].

combo setString: items first.combo

addCallback: XmNsingleSelectionCallbackreceiver: selfselector: #singleSelect:clientData:callData:clientData: nil.

combo manageChild.

shell realizeWidget.

The call data of the singleSelection callback specifies the item that was selected. Thecallback method below prints the entire callback data on the transcript. Allcomponents of the call data can be retrieved using the corresponding accessormethod.singleSelect: widget clientData: clientData callData: callData

"Print the call data."Transcript cr; show: 'Single selection call data: ',

callData printString

If Item 2 is selected, as in the illustration, the transcript output is as follows:Single selection call data: CwListCallbackData(

reason -> 23item -> 'Item 2'itemPosition -> 2

"These three fields of the callback data are only used for multipleand extended select lists."selectedItems -> nilselectedItemCount -> nilselectedItemPositions -> nil)

Composite-box widgetsThere are two types of composite-box widgets: CwMessageBox and CwSelectionBox.Both are subclasses of CwCompositeBox. CwCompositeBox is itself a subclass ofCwBulletinBoard, which provides useful dialog-related resources such asautoUnmanage, dialogStyle, and dialogTitle.

190 IBM Smalltalk: Programmer’s Reference

||||

||||

|

|||||||||

Page 205: IBM Smalltalk: Programmer's Reference

MessageBox widgetsMessage-box widgets (CwMessageBox) are used for common interaction tasks suchas displaying messages, asking questions and reporting errors. A message boxwidget consists of a message string, an optional symbol such as an exclamation orquestion mark, and three buttons. By default, the buttons are labelled OK, Cancel,and Help, and there is no symbol displayed.

A message box is usually created in a dialog shell to notify the user of some event.Message-box widgets are created using the createMessageBox:argBlock: andcreateMessageDialog:argBlock: convenience methods. The latter method is similar tothe first, but also creates a CwDialogShell as the parent of the CwMessageBox so thatit can be popped up separately from the main widget tree. As with pop-up menus,the message-box/dialog shell combination (message dialog) can be created and leftunmanaged until it is to be presented to the user. It is popped up by sending themessage box the manageChild message. The default behavior is to remain open untileither the OK or Cancel button is pressed, or the dialog’s close box isdouble-clicked. The application can explicitly close the dialog by sendingunmanageChild to the message box.

The message shown in a message box is specified by the messageString resource.When the message box is in a dialog shell, the dialogTitle resource specifies the titleof the dialog shell. The symbol shown is specified by the dialogType resource,which can have one of the following values:

XmDIALOGMESSAGEMessage only, no symbol (default)

XmDIALOGINFORMATIONInformation symbol (an i on some plaforms)

XmDIALOGERRORError symbol (a stop sign on some platforms)

XmDIALOGWARNINGWarning symbol (an ! on some platforms)

XmDIALOGQUESTIONQuestion mark symbol

XmDIALOGWORKINGWorking symbol

The following figure shows an example message dialog:

OK Cancel Help

CwMessageBox Example

Warning: This is awarning message.

The dialogStyle resource specifies the input mode while the dialog is active, and canhave one of the following values:

XmDIALOGAPPLICATIONMODALUsed for dialogs that must be responded to before some other interactions

Chapter 7. Common Widgets 191

Page 206: IBM Smalltalk: Programmer's Reference

in ancestors of the widget. This value is the same asXmDIALOG_PRIMARY_APPLICATION_MODAL and remains forcompatibility.

XmDIALOGWORKAREAUsed for BulletinBoard widgets whose parents are not DialogShells. This isthe default when the parent of the BulletinBoard is not a DialogShell.

XmDIALOGMODELESSUsed for dialogs that do not interrupt interaction of any application(default).

XmDIALOGPRIMARYAPPLICATIONMODALUsed for dialogs that must be responded to before any other interaction inancestors of the widget.

XmDIALOGFULLAPPLICATIONMODALUsed for dialogs that must be responded to before any other interaction inthe same application.

XmDIALOGSYSTEMMODALUsed for dialogs that must be responded to before any other interaction inany application.

If a platform does not support the specified prompter style, the style is promotedto the next most restrictive style. If the next most restrictive style is not supported,the style is demoted to the next less restrictive style.

The widgets comprising the message box can be retrieved using the getChild:method. If a button or other widget is not required by the application, it can beretrieved and unmanaged. Possible arguments for the getChild: method are:v XmDIALOGCANCELBUTTONv XmDIALOGDEFAULTBUTTONv XmDIALOGHELPBUTTONv XmDIALOGMESSAGELABELv XmDIALOGOKBUTTONv XmDIALOGSEPARATORv XmDIALOGSYMBOLLABEL

The okCallback, cancelCallback, and helpCallback of the message box are called whenthe corresponding buttons are pressed. If a callback is not added, thecorresponding button will still appear, but nothing will happen when it is pressed.If the message box is in a dialog shell, it is unmanaged when the OK or Cancelbutton is pressed, unless the autoUnmanage resource is set to false.

The following code creates an application modal information message dialog that ispopped up when a button is pressed. Only the OK button of the message dialog isshown. The remaining ones are hidden (unmanaged). A callback is added for theOK button. Because the dialog is application modal, the user must close the dialogbefore the application can receive further input.

192 IBM Smalltalk: Programmer’s Reference

Page 207: IBM Smalltalk: Programmer's Reference

Object subclass: #MessageDialogExampleinstanceVariableNames: 'messageBox 'classVariableNames: ''poolDictionaries: 'CwConstants'

open| shell button | OK

Message Dialog

This is amessage dialog.i

shell := CwTopLevelShellcreateApplicationShell: 'shell'argBlock: [:w | w title: 'Message Dialog Example'].

button := shellcreatePushButton: 'Push me for dialog'argBlock: nil.

buttonaddCallback: XmNactivateCallbackreceiver: selfselector: #button:clientData:callData:clientData: nil.

button manageChild.

messageBox := shellcreateMessageDialog: 'message'argBlock: [:w |

wdialogTitle: 'Message Dialog';dialogStyle: XmDIALOGFULLAPPLICATIONMODAL;messageString: 'This is a message dialog.';dialogType: XmDIALOGINFORMATION].

messageBoxaddCallback: XmNokCallbackreceiver: selfselector: #ok:clientData:callData:clientData: nil.

(messageBox getChild: XmDIALOGCANCELBUTTON) unmanageChild.(messageBox getChild: XmDIALOGHELPBUTTON) unmanageChild.

shell realizeWidget

button: widget clientData: clientData callData: callData"The button has been pressed. Pop up the message dialog."

messageBox manageChild

ok: widget clientData: clientData callData: callDataTranscript

cr; show: 'The OK button in the dialog has been pressed.';cr; show: 'The dialog is about to disappear.'.

SelectionBox widgetsSelection-box widgets (CwSelectionBox) are used to obtain a selection from a list ofalternatives provided to the user. A selection box can contain some or all of thefollowing components: a scrollable list of alternatives, an editable text field for theselected alternative, labels for the list and text field, and four buttons. By default,the buttons are labelled OK, Apply, Cancel and Help.

A selection box is usually created in a dialog shell to prompt the user to select alist item. Selection-box widgets are created using the createSelectionBox:argBlock: andcreateSelectionDialog:argBlock: convenience methods. The latter method is similar tothe first, but also creates a CwDialogShell as the parent of the CwSelectionBox so thatit can be popped up separately from the main widget tree. As with pop-up menusa selection dialog can be created and left unmanaged until it is to be presented tothe user. It is popped up by sending the selection box the manageChild message.

Chapter 7. Common Widgets 193

Page 208: IBM Smalltalk: Programmer's Reference

The default behavior is to remain open until either the OK or Cancel button ispressed, or the dialog’s close box is double-clicked. The application can explicitlyclose the dialog by sending unmanageChild to the selection box.

The dialogType resource specifies which selection-box components actually appear.It can have one of the following values:

XmDIALOGPROMPTAll standard children except the list and list label are created and all exceptthe Apply button are managed.

XmDIALOGSELECTIONAll standard children are created and managed. This is the default if theparent is a dialog shell.

XmDIALOGWORKAREAAll standard children are created, and all except the Apply button aremanaged. This is the default if the parent is not a dialog shell.

When the selection box is in a dialog shell, the dialogTitle resource specifies the titleof the dialog shell, and the dialogStyle resource specifies the input mode while thedialog is active.

The labels for the list widget and the text widget are set using theselectionLabelString: and textLabelString: methods respectively.

An example selection dialog is shown in the diagram below.

OK Apply Cancel Help

CwSelectionBox Example

Select a bitmap file:

Desktop background:

stars.bmpstripes.bmpcats.bmpdogs.bmp

cats.bmp

The list contents can be set or retrieved using the listItems resource. The textcontents can be set or retrieved using the textString resource.

The widgets comprising the selection box can be retrieved using the getChild:method. If a button or other widget is not required by the application, it can beretrieved and unmanaged. Possible arguments to the getChild: method are:v XmDIALOGAPPLYBUTTONv XmDIALOGCANCELBUTTONv XmDIALOGDEFAULTBUTTONv XmDIALOGHELPBUTTONv XmDIALOGLISTv XmDIALOGLISTLABELv XmDIALOGOKBUTTONv XmDIALOGSELECTIONLABELv XmDIALOGSEPARATORv XmDIALOGTEXT

194 IBM Smalltalk: Programmer’s Reference

Page 209: IBM Smalltalk: Programmer's Reference

v XmDIALOGWORKAREA

The okCallback, applyCallback, cancelCallback, and helpCallback of the selection box arerun when the corresponding buttons are pressed. If a callback is not added, thecorresponding button will still appear, but nothing will happen when it is pressed.When the selection box is in a dialog shell, it is unmanaged when the OK orCancel button is pressed, unless the autoUnmanage resource is set to false.

Using the mustMatch resource, the selection box can be configured to test whetherthe text typed in the text widget matches any item in the list. If mustMatch is trueand the text does not match any item in the list when the OK button is pressed,the noMatch callback is run, otherwise the ok callback is run. Note that if thenoMatch callback is run, a selection dialog will not be unmanaged.

The code below creates the following modeless selection dialog that is popped upwhen a button is pressed. The name of the Apply button has been changed toShow, and the Help button is hidden.

OK Show Cancel

Selection Dialog

Items:

Item:

Item 1Item 2Item 3Item 4

Item 2

The mustMatch resource and noMatch callback are used to test when the text doesnot match any item in the list. Because the dialog is modeless, the user can click ortype in any other widget without having to close the dialog first.Object subclass: #SelectionDialogExample

instanceVariableNames: 'selectionBox 'classVariableNames: ''poolDictionaries: 'CwConstants'

open| items shell button |

items := OrderedCollection new.1 to: 20 do: [:i |

items add: 'Item ', i printString].

shell := CwTopLevelShellcreateApplicationShell: 'shell'argBlock: [:w | w title: 'Selection Dialog Example'].

button := shellcreatePushButton: 'Push me for selection box'argBlock: nil.

buttonaddCallback: XmNactivateCallbackreceiver: selfselector: #button:clientData:callData:clientData: nil.

button manageChild.

selectionBox := shellcreateSelectionDialog: 'selection'argBlock: [:w |

w

Chapter 7. Common Widgets 195

Page 210: IBM Smalltalk: Programmer's Reference

dialogTitle: 'Selection Dialog';dialogStyle: XmDIALOGMODELESS;dialogType: XmDIALOGSELECTION;listLabelString: 'Items:';selectionLabelString: 'Selection:';applyLabelString: 'Show';listItems: items;mustMatch: true].

selectionBoxaddCallback: XmNokCallbackreceiver: selfselector: #ok:clientData:callData:clientData: nil;

addCallback: XmNapplyCallbackreceiver: selfselector: #show:clientData:callData:clientData: nil;

addCallback: XmNcancelCallbackreceiver: selfselector: #cancel:clientData:callData:clientData: nil;

addCallback: XmNnoMatchCallbackreceiver: selfselector: #noMatch:clientData:callData:clientData: nil.

(selectionBox getChild: XmDIALOGHELPBUTTON) unmanageChild.

shell realizeWidget

button: widget clientData: clientData callData: callData"The button has been pressed. Pop up the selection dialog."

selectionBox manageChild

ok: widget clientData: clientData callData: callData"The OK button in the dialog has been pressed.The dialog will be automatically unmanaged."

Transcript cr; show: 'The final selection is: ' , widget textString

show: widget clientData: clientData callData: callData"The Show button in the dialog has been pressed.The dialog will NOT be automatically unmanaged."

Transcript cr; show: widget textString

cancel: widget clientData: clientData callData: callData"The Cancel button in the dialog has been pressed.The dialog will be automatically unmanaged."

Transcript cr; show: 'The selection dialog was canceled.'

noMatch: widget clientData: clientData callData: callData"The OK button in the dialog was pressed,but the textString did not match any item inthe items list. The dialog will NOT be automatically unmanaged."

Transcript cr; show: 'The selection does not match any item in the list.'

Dialog convenience methodsCommon Widgets provides several dialog creation convenience methods. Thefollowing methods create a CwMessageBox as the child of a CwDialogShell, and setthe dialogType resource as indicated so that an appropriate icon is displayed:

createMessageDialog:argBlock:XmDIALOGMESSAGE

196 IBM Smalltalk: Programmer’s Reference

Page 211: IBM Smalltalk: Programmer's Reference

createErrorDialog:argBlockXmDIALOGERROR

createInformationDialog:argBlock:XmDIALOGINFORMATION

createQuestionDialog:argBlock:XmDIALOGQUESTION

createWarningDialog:argBlock:XmDIALOGWARNING

createWorkingDialog:argBlock:XmDIALOGWORKING

The following methods create a CwSelectionBox as the child of a CwDialogShell, andset the dialogType resource as indicated:

createSelectionDialog:argBlock:XmDIALOGSELECTION

createPromptDialog:argBlock:XmDIALOGPROMPT

Here are two additional dialog creation convenience methods:

createBulletinBoardDialog:argBlock:Creates an empty CwBulletinBoard widget within a dialog shell, allowingthe application to define the entire contents of the dialog

createFormDialog:argBlock:Creates an empty CwForm widget within a dialog shell, allowing theapplication to define the entire contents of the dialog

Creating and using promptersCommonWidgets provides three prompters that can be used to prompt the user forinformation required by the application. The user must reply to the prompt beforethe application can continue execution. The following three prompters areprovided:

CwMessagePrompterDisplays a message and waits for the user to press a button in response

CwTextPrompterDisplays a message and prompts the user for a single line of text as a reply

CwFileSelectionPrompterPrompts the user for the path name of a file

Prompters are an extension of the OSF/Motif API implemented using theplatform’s native prompters, where available. Prompters are not widgets, butprovide a convenient, portable mechanism to access platform-specific promptingservices.

The CwMessagePrompter provides functionality similar to the CwMessageBox widgetdescribed earlier. The difference is that CwMessagePrompter uses the platform’smessage prompter, whereas CwMessageBox provides the behavior of the Motifmessage box. On Motif platforms, CwMessagePrompter is implemented usingCwMessageBox.

Chapter 7. Common Widgets 197

Page 212: IBM Smalltalk: Programmer's Reference

Prompters can be created in two ways:v With an associated parent widget tree, using an expression such as

<prompterClass> for: aCwWidget

v Without an associated parent widget tree, using an expression such as<prompterClass> new

A prompter can be configured with several settings, described below. Defaultvalues are provided for all settings of a prompter.

The modality of a prompter can be changed using the prompterStyle: method. Validprompter styles, in order of restrictiveness, are:

XmPRIMARYAPPLICATIONMODALThe user must respond to the prompter before being able to resumeinteraction with the receiver’s parent window. Interaction with otherwindows is still possible.

XmFULLAPPLICATIONMODALThe user must respond to the prompter before being able to resumeinteraction with any window belonging to the receiver’s application.Interaction with windows from other applications is still possible.

XmSYSTEMMODALThe user cannot interact with the windows of any application untilresponding to the prompter.

If a platform does not support the specified prompter style, the style is promotedto the next most restrictive style. If no more restrictive style exists, the style isdemoted to the next less restrictive style.

The title of the prompter can be set using the title: method.

A prompter is popped up using the prompt method. Control is not returned to theapplication until the user responds to the prompter. The value returned by theprompt method is nil if the user cancels the prompter. If the user replies to theprompter without cancelling, the value returned depends on the type of prompter.

Message prompterA CwMessagePrompter displays a message to the user and waits for a button to bepressed. A message prompter from the OS/2 platform is illustrated below.

Is this a message prompter?

Message Prompter Example

?Yes No Cancel

The message displayed by a message prompter is set using the messageString:method.

The buttons displayed by the prompter can be changed using the buttonType:method. Valid values are:XmOK

OK button only

198 IBM Smalltalk: Programmer’s Reference

Page 213: IBM Smalltalk: Programmer's Reference

XmOKCANCELOK and Cancel buttons (default setting)

XmRETRYCANCELRetry and Cancel buttons

XmABORTRETRYIGNOREAbort, Retry, and Ignore buttons

XmYESNOYes and No buttons

XmYESNOCANCELYes, No, and Cancel buttons

The button selected by default if the user presses the return key can be changedusing the defaultButtonType:method. Valid values are:XmDEFAULTBUTTON1

The first button is the default (default setting)XmDEFAULTBUTTON2

The second button is the defaultXmDEFAULTBUTTON3

The third button is the default

The icon displayed in the message box can be changed using the iconType: method.Valid values are:XmNOICON

No iconXmICONINFO

Info icon (default setting)XmICONWARNING

Warning iconXmICONERROR

Error iconXmICONQUESTION

Question icon

The prompt method returns one of the following values, depending on whichbutton was pressed:

true The OK, Yes, or Retry button was pressed

false The No or Abort button was pressed

nil The Cancel or Ignore button was pressed

The message prompter shown above is created by the following code.| reply |reply :=

CwMessagePrompter newtitle: 'Message Prompter Example';messageString: 'Is this a message prompter?';buttonType: XmYESNOCANCEL;defaultButtonType: XmDEFAULTBUTTON1;iconType: XmICONQUESTION;prompt.

Transcript cr; show: 'The reply was: ', reply printString

Chapter 7. Common Widgets 199

Page 214: IBM Smalltalk: Programmer's Reference

Text prompterA CwTextPrompter prompts the user for a single line of text, in response to a query.A text prompter from the OS/2 platform is illustrated below.

The message displayed by a text prompter is set using the messageString: method.

The initial contents of the text box for the user’s answer can be set using theanswerString: method.

The prompt method returns nil if the prompter was cancelled, or the contents of thetext box if the user pressed the return key or the OK button.

The text prompter shown above is created by the following code.| reply |reply :=

CwTextPrompter newtitle: 'Text Prompter Example';messageString: 'What is your name?';answerString: 'Enter your name here';prompt.

Transcript cr; show: 'The reply was: ', reply printString.

File selection prompterA CwFileSelectionPrompter prompts the user to choose a file from a directory in thefile system. A file selection prompter from the OS/2 platform is shown in thefollowing illustration:

<All Files>

AUTOEXEC.BATCOMMAND.COMCONFIG.001CONFIG.SYS

C: [C_DOS5]

BINCOMPLIBDOS5

*.*

Open filename:

Type of file:

File:

Drive:

Directory:

File Selection Prompter Example

OK Cancel

C:\

The following methods are used to configure a file selection prompter:

200 IBM Smalltalk: Programmer’s Reference

Page 215: IBM Smalltalk: Programmer's Reference

searchPath:Sets the string specifying the initial directory path presented to the user.The default is a platform-specific string denoting the current workingdirectory.

searchMask:Sets the string used to filter the file names; an asterisk (*) within the stringdenotes a wildcard. The default is a platform-specific string denoting allnormal files.

fileName:Sets the string to use as the default file name presented to the user. Thedefault is an empty string.

accessMode:Hint provided by the application to indicate whether the applicationintends to open or save a file.

fileExtension:Hint provided by the application to indicate the preferred file extension forthe return value. On some platforms, the prompter ensures that the returnvalue has the correct extension if fileExtension is set. The default is anempty string.

The prompt method returns nil if the prompter is cancelled. If a file is properlyselected, a string specifying the full path name of the file is returned.

The file selection prompter shown above is created by the following code.| reply |reply :=

CwFileSelectionPrompter newtitle: 'File Selection Prompter Example';searchPath: 'c:\';searchMask: '*.*';prompt.

Transcript cr; show: 'The reply was: ', reply printString.

Extended widgetsCommon Widgets provides a framework for developing custom widgets based onexisting widgets. These are called extended widgets. If the IBM Smalltalk portableAPI is used to develop an extended widget, it will be portable between allplatforms supported by IBM Smalltalk. Extended widgets are often implementedusing a CwDrawingArea, with its visual appearance drawn using CommonGraphics calls, and with user input processed using event handlers.

Consider the following subset of the CwWidget class hierarchy:

CwWidgetCwBasicWidget

CwCompositeCwPrimitiveCwShell

CwExtendedWidgetCwExtendedCompositeCwExtendedPrimitive

Chapter 7. Common Widgets 201

Page 216: IBM Smalltalk: Programmer's Reference

The CwWidget class defines behavior common to all widgets. The CwBasicWidgethierarchy provides the basic widgets described thus far, such as CwShell, CwText,CwList, CwPushButton, CwForm and CwRowColumn. Basic widgets are implementedusing the native widgets provided by each platform. The implementation of basicwidgets is not portable.

The CwExtendedWidget class is the abstract superclass of all extended widgets. Aswith the basic widget class hierarchy, it is divided up into primitive widgets(CwExtendedPrimitive) and composite widgets (CwExtendedComposite).

Writing an extended widgetThe first step in writing an extended widget is to create a subclass of theappropriate extended widget framework class. Extended widgets that are notintended to contain child widgets should be implemented as subclasses ofCwExtendedPrimitive. Those that are intended to contain child widgets should beimplemented as subclasses of CwExtendedComposite. It is important to understandthis difference:v A subclass of CwExtendedPrimitive can be implemented using a primary widget

with child widgets, however an application programmer making use of this type ofextended widget can not add any children to it.

v A subclass of CwExtendedComposite can be implemented using just a single widget,say for example a CwForm with no children, but the same applicationprogrammer can create this type of extended widget and add as many childrenas are permitted by the extended widget’s API.

After the subclass has been created, it should define an instance variable for eachresource and callback provided by the extended widget, as well as instancevariables required for any other aspects of the widget’s implementation.

Defining the extended widget classAn extended widget is implemented using a widget tree consisting of other basicor extended widgets. This tree is called the primary widget tree. The root of theprimary widget tree is known as the primary widget. The extended widget classmust override the createPrimaryWidget:parent:argBlock: method. This method createsand answers the primary widget, but does not create the children of the primarywidget. If the primary widget tree consists of more than one widget, the extendedwidget class must override createWidgetSystem. This method creates the remainderof the primary widget tree, that is, the children of self primaryWidget.

InitializationThree methods can be overridden to initialize the state of the widget. The initializemethod is run as the first step in extended widget creation. It is useful forinitializing the internal state of the widget, except for resources. TheinitializeResources method initializes the instance variables representing resources.Both of these methods are run before the primary widget tree has been created.The initializeAfterCreate method is run after the primary widget tree has beencreated. It is useful for configuring widgets after they have been created, and forinitializing graphics resources.

ResourcesSet and get accessor methods should be added for each resource provided by theextended widget. Usually, the get method simply answers the correspondinginstance variable. The set method usually sets the corresponding instance variableand makes any required changes in the primary widget tree.

202 IBM Smalltalk: Programmer’s Reference

Page 217: IBM Smalltalk: Programmer's Reference

CallbacksSet and get accessor methods must be added for each callback provided by theextended widget. The set accessor method simply sets the instance variable used tostore an ordered collection of CwCallbackRec objects for the particular callback. It istypically only called by the get method to initialize the ordered collection. ThevalueChangedCallback: method in the example that follows is a callback set accessor.

The get accessor method for a callback is a little more involved. In order to workproperly with methods inherited from CwExtendedWidget, the constant used tospecify the type of the callback—for example, XmNactivateCallback for an activatecallback—is a pool variable that must be equal to the get method’s selector—forexample, activateCallback. The valueChangedCallback method in the example is acallback get accessor. Callback type specifiers are already defined in theCwConstants pool dictionary, however, if a new name is desired, it can be added toan application-specific pool dictionary using the same naming convention.

The get accessor must answer an ordered collection, to which callback descriptorsare added whenever a callback is registered. If the callback resource isuninitialized, the get method must set the callback resource to a newOrderedCollection, and answer that.

Registered callbacks can be run by the extended widget using thecallCallbacks:callData: method. The example extended widget calls its valueChangedcallback in the valueChangedCallback: method.

Widget-specific methodsAn extended widget works by forwarding most widget messages to its primarywidget. All of the methods inherited from CwWidget are automatically forwardedto the primary widget if they are not explicitly overridden. In simple cases, anextended widget’s behavior can be implemented simply by adding resource andcallback methods as described above. For more complicated widgets, it is usuallynecessary to extend the basic widget protocol by providing methods to support thenew operations on the extended widget.

Using an extended widgetAfter an extended widget class has been defined, application developers can createinstances of the extended widget by sending the createWidget:parent:argBlock: orcreateManagedWidget:parent:argBlock: method to the extended widget’s class. Thecreate argBlock should only set resources that are defined for the extended widgetor in CwWidget, and should not assume a particular underlying implementation.

Example: a primitive extended widgetTwo example extended widgets are provided in the next two sections. The first,below, is a subclass of CwExtendedPrimitive, and the second, on page “Example: acomposite extended widget” on page 207, is a subclass of CwExtendedComposite. Theprefix ‘Cew’ is used to differentiate these new widgets from basic widgets. Forsimplicity, the examples do not include robust error-checking, nor does eachwidget provide a complete set of resources.

The CewEntryField widget, shown below, has a label on the left and a text box onthe right. It allows a user to enter text into its text box, and it invokes avalueChanged callback if a new value is present when the user either hits the tabkey or clicks on a different widget.

The extended widget is implemented using a CwForm as the primary widget withCwLabel and CwText children. A losingFocus callback on the CwText enables the

Chapter 7. Common Widgets 203

Page 218: IBM Smalltalk: Programmer's Reference

widget to test entered data, and possibly call any registered valueChanged callbacks.

Your name here aCewEntryFieldName :

CwExtendedPrimitive subclass: #CewEntryFieldinstanceVariableNames: 'label value valueChangedCallback labelWidget textWidget 'classVariableNames: ''poolDictionaries: ''

createPrimaryWidget: theName parent: parent argBlock: argBlock"Private - Create and answer the basic widget that is the root of thewidget hierarchy for the receiver's widget system."

|self parentcreateForm: theName, 'Form'argBlock: argBlock

createWidgetSystem"Private - Create the children of the receiver's primary widget which form thewidget hierarchy."

| pw |

pw := self primaryWidget.self labelWidget:

(pwcreateLabel: pw name , 'Label'argBlock: [:w | w labelString: self label])

manageChild.

self textWidget:(pw

createText: pw name , 'Text'argBlock: [:w |

wborderWidth: 1;value: self value])

manageChild.self textWidget

addCallback: XmNlosingFocusCallbackreceiver: selfselector: #losingFocus:clientData:callData:clientData: nil.

"Add form attachments for the two children."self labelWidget

setValuesBlock: [:w |w

topAttachment: XmATTACHFORM;leftAttachment: XmATTACHFORM;rightAttachment: XmATTACHNONE;bottomAttachment: XmATTACHFORM].

self textWidgetsetValuesBlock: [:w |

wtopAttachment: XmATTACHFORM;leftAttachment: XmATTACHWIDGET;leftWidget: self labelWidget;rightAttachment: XmATTACHFORM;bottomAttachment: XmATTACHFORM].

initializeResources"Private - Set the default extended widget resource values. This is sentduring create with isCreated set to false. All extended resourcevariables should be initialized to default values here."

label := String new.value := String new.

204 IBM Smalltalk: Programmer’s Reference

Page 219: IBM Smalltalk: Programmer's Reference

initializeAfterCreate"Private - Perform any widget-specific post-create initialization."

self primaryWidgethorizontalSpacing: 4;verticalSpacing: 4;borderWidth: 1.

"Resources that involve the children of the primary widget have to be setafter the children are created."

self labelWidget labelString: label.self textWidget value: value.

label"Answer the value of the label resource.Resource type: StringDefault setting: ''Resource access: CSGDescription:

Specifies the string for the CewEntryField's label.This label is to the left of the CewEntryField's text box."

|labellabel: resourceValue"Set the value of the label resource to resourceValue.Resource type: StringDefault setting: ''Resource access: CSGDescription:

Specifies the string for the CewEntryField's label.This label is to the left of the CewEntryField's text box."label := resourceValue.self isCreated

ifTrue: [labelWidget labelString: resourceValue]

value"Answer the value of the value resource.Resource type: StringDefault setting: 'Resource access: CSGDescription:

Specifies the string for the CewEntryField's value.This value is displayed in the CewEntryField's text box ifset using the #value: message, or if a valid string followedby a tab key is entered by the user.Note that while the user is typing, the string displayed in thetext box might not be the same as the CewEntryField's value."

|valuevalue: resourceValue"Set the value of the value resource to resourceValue.Resource type: StringDefault setting: 'Resource access: CSGDescription:

Specifies the string for the CewEntryField's value.This value is displayed in the CewEntryField's text box ifset using the #value: message, or if a valid string followedby a tab key is entered by the user.Note that while the user is typing, the string displayed in thetext box might not be the same as the CewEntryField's value."

value := resourceValue.self isCreated

ifTrue: [textWidget value: resourceValue]

valueChangedCallback"Private - Answer the value of valueChangedCallback."

valueChangedCallback isNilifTrue: [self valueChangedCallback: OrderedCollection new].

|valueChangedCallback

Chapter 7. Common Widgets 205

Page 220: IBM Smalltalk: Programmer's Reference

valueChangedCallback: resourceValue"Set the value of the XmNvalueChangedCallback resource to resourceValue.Resource type: OrderedCollection of CwCallbackRecDefault setting: OrderedCollection newResource access: CCallback reason: XmCRVALUECHANGEDCalldata structure: CwValueCallbackDataDescription:

Specifies the list of callbacks that is called when the valueof the CewEntryField has changed. The reason sent by thecallback is XmCRVALUECHANGED. The structure returnedby this callback is CwValueCallbackData."

valueChangedCallback := resourceValue.

labelWidget"Private - Answer the value of labelWidget."

|labelWidget

labelWidget: aCwLabel"Private - Set the value of labelWidget to aCwLabel."

labelWidget := aCwLabel.

textWidget"Private - Answer the value of textWidget."

|textWidget

textWidget: aCwText"Private - Set the value of textWidget to aCwText."

textWidget := aCwText.

losingFocus: widget clientData: clientData callData: callData"Private - Process a losing focus callback for the primary widget."

| newValue |

newValue := self textWidget value.

"If the new value is different, invoke the entryField widget'svalueChanged callback."

self value = newValueifTrue: [

selfvalue: newValue;callCallbacks: XmNvalueChangedCallbackcallData: (CwValueCallbackData new value: newValue)].

Using the CewEntryField primitive extended widgetThe following code creates a CewEntryField instance, sets its name and labelresources inside the create argBlock, and hooks a valueChanged callback to it. Thenew widget is shown in the diagram at the beginning of this section, on page“Example: a primitive extended widget” on page 203.| shell entryField |

shell := CwTopLevelShellcreateApplicationShell: 'CewEntryField Test'argBlock: nil.

entryField := CewEntryFieldcreateManagedWidget: 'entryField'parent: shellargBlock: [:w |

wlabel: 'Name :';value: 'Your name here'].

206 IBM Smalltalk: Programmer’s Reference

Page 221: IBM Smalltalk: Programmer's Reference

entryFieldaddCallback: XmNvalueChangedCallbackreceiver: selfselector: #valueChanged:clientData:callData:clientData: nil.

shell realizeWidget.

valueChanged: widget clientData: clientData callData: callData"Display the new value on the transcript."

Transcript cr; show: 'Value changed to: ' , callData value printString.

The CewEntryField class can be subclassed to provide a slightly different extendedwidget by simply overriding one method, as in the following class definition forCewNumericEntryField:CewEntryField subclass: #CewNumericEntryField

instanceVariableNames: ''classVariableNames: ''poolDictionaries: ''

losingFocus: widget clientData: clientData callData: callData"Private - Process a losing focus callback for the primary widget."

| newValue |

newValue := self textWidget value.

"Verify that the new value string represents a number.If it doesn't, reset the text widget and return."

(newValue notEmpty and: [newValue conform: [:c | c isDigit]])ifFalse: [ |self value: value ].

"If the new value is different, invoke the entryField widget'svalueChanged callback."

self value = newValueifTrue: [

selfvalue: newValue;callCallbacks: XmNvalueChangedCallbackcallData: (CwValueCallbackData new value: newValue)]

Example: a composite extended widgetThe CewTitleFrame widget draws a rounded-corner rectangle around its singlechild, and displays its title in the upper-left portion of the rectangle. This widget issimilar to CwFrame, and, like CwFrame, does not support any special callbacks. Itspurpose is to provide decoration, not interactive behavior.

The extended widget is implemented using a CwDrawingArea for the primarywidget, with an expose callback to draw the frame and title, and a resize callbackto make sure the child always fits inside the frame.

Direction

Up

DownaCewTitleFrame

with a 2-button radio box child

CwExtendedComposite subclass: #CewTitleFrameinstanceVariableNames: 'title borderInset childInset radius angles gc

lineSegments arcOrigins'classVariableNames: ''poolDictionaries: ''

Chapter 7. Common Widgets 207

Page 222: IBM Smalltalk: Programmer's Reference

createPrimaryWidget: theName parent: parent argBlock: argBlock"Private - Create and answer the basic widget that is the root ofthe widget hierarchy for the receiver's widget system."

|parentcreateDrawingArea: theName , 'DrawingArea'argBlock: argBlock

initialize"Private - Perform any private widget-specific state initialization. This is sentbefore any other initialization begins. borderInset, radius, and angles are neededfor drawing the frame. lineSegments is set to nil to ensure that the lineSegmentsand arcOrigins collections are calculated on first expose. childInset used to sizechild in resize callback."

selfradius: 15;angles: #(90 0 270 180);borderInset: (CgFontStruct default height) // 2 + 4;childInset: self borderInset * 2.

initializeResources"Private - Set the default extended widget resource values. This is sent duringcreate with isCreated set to false. All extended resource variables should beinitialized to default values here."

title := String new.

initializeAfterCreate"Private - Perform any widget-specific post-create initialization."

self primaryWidgetmarginHeight: self childInset;marginWidth: self childInset;addCallback: XmNexposeCallback

receiver: selfselector: #expose:clientData:callData:clientData: nil;

addCallback: XmNresizeCallbackreceiver: selfselector: #resize:clientData:callData:clientData: nil.

title"Answer the value of the title resource.Resource type: StringDefault setting: ''Resource access: CSGDescription:

Specifies the string for the CewTitleFrame's title.This title is displayed in the upper left portion of therounded-corner rectangle that frames the child widget."

|title

title: resourceValue"Set the value of the title resource to resourceValue.Resource type: StringDefault setting: ''Resource access: CSGDescription:

Specifies the string for the CewTitleFrame's title.This title is displayed in the upper left portion of therounded-corner rectangle that frames the child widget."title := resourceValue.

borderInset"Private - Answer the value of borderInset."

|borderInset

208 IBM Smalltalk: Programmer’s Reference

Page 223: IBM Smalltalk: Programmer's Reference

borderInset: anInteger"Private - Set the value of borderInset to anInteger."

borderInset := anInteger.

childInset"Private - Answer the value of childInset."

|childInset

childInset: anInteger"Private - Set the value of childInset to anInteger."

childInset := anInteger.

radius"Private - Answer the value of radius."

|radius

radius: anInteger"Private - Set the value of radius to anInteger."

radius := anInteger.

angles"Private - Answer the value of angles."

|angles

angles: anArray"Private - Set the value of angles to anArray."

angles := anArray.

lineSegments"Private - Answer the value of lineSegments."

|lineSegments

lineSegments: anOrderedCollection"Private - Set the value of lineSegments to anOrderedCollection."

lineSegments := anOrderedCollection.

arcOrigins"Private - Answer the value of arcOrigins."

|arcOrigins

arcOrigins: anArray"Private - Set the value of arcOrigins to anArray."

arcOrigins := anArray.

gc"Private - Answer the value of gc. Create if not already created."

gc isNilifTrue: [self initializeGraphics].

|gc

gc: aCgGC"Private - Set the value of gc to aCgGC."

gc := aCgGC

initializeGraphics"Private - Set the receiver's palette and create a GC. This method is calledby the #gc method if gc is nil."

| pw colors |pw := self primaryWidget.colors := Array

with: pw backgroundColor "pixel 0"with: pw foregroundColor. "pixel 1"

"The palette must be set on the shell window."

Chapter 7. Common Widgets 209

Page 224: IBM Smalltalk: Programmer's Reference

pw shell windowsetPalette: (CgIndexedPalette colors: colors).

self gc: (pw windowcreateGC: GCForeground | GCBackground | GCFontvalues: (CgGCValues new

background: 0;foreground: 1;font: pw display defaultFont)).

recalculateSegmentsAndArcs"Private - Calculate the line segments and arc origins to draw the frame aroundthe child widget at the current size."

| border offset diam width height |

border := self borderInset.offset := border + self radius.diam := self radius * 2.width := self width.height := self height.

self lineSegments: (OrderedCollection newadd: (CgSegment

point1: offset @ borderpoint2: (width - offset) @ border);

add: (CgSegmentpoint1: (width - border) @ offsetpoint2: (width - border) @ (height - offset));

add: (CgSegmentpoint1: (width - offset) @ (height - border)point2: offset @ (height - border));

add: (CgSegmentpoint1: border @ (height - offset)point2: border @ offset)).

self arcOrigins: (Arraywith: (border @ border)with: (width - (diam + border)) @ borderwith: (width @ height) - (diam + border)with: border @ (height - (diam + border))).

expose: widget clientData: clientData callData: callData"Private - Process an expose callback for the primary widget bydrawing the rounded-corner rectangle frame and title."

| border offset diam |border := self borderInset.offset := border + self radius.diam := self radius * 2.

self lineSegments isNilifTrue: [self recalculateSegmentsAndArcs].

widget windowdrawSegments: self gc segments: self lineSegments.

self arcOriginswith: self angles do: [ :p :angle |

widget windowdrawArc: self gc

x: p xy: p ywidth: diamheight: diamangle1: 64 * angleangle2: 64 * 90 ].

widget windowdrawImageString: self gcx: offset + 20y: border + (widget display defaultFontStruct ascent // 2)string: ' ' , self title , ' '.

210 IBM Smalltalk: Programmer’s Reference

Page 225: IBM Smalltalk: Programmer's Reference

resize: widget clientData: clientData callData: callData"Private - Process a resize callback for the primary widget byresizing the primary widget's child to fit inside the frame."

| child offset |

(child := widget children) notEmptyifTrue: [

offset := self childInset * 2.child first

resizeWidget: self width - offsetheight: self height - offsetborderWidth: child first borderWidth ].

"Force a recalculation of line segments and arc origin based on the new size.Recalculation will occur at next expose."

self lineSegments: nil.

"Clear the widget and force an expose event."widget window clearArea: 0 y: 0 width: 0 height: 0 exposures: true.

Using the CewTitleFrame composite extended widgetThe following code creates a CewTitleFrame instance with a radio-box child (aCwRowColumn with radioBehaviour set to true). The radio box then creates twoCwToggleButton children. This is shown in the diagram at the beginning of thissection, on page “Example: a composite extended widget” on page 207.| shell titleFrame radioBox |

shell := CwTopLevelShellcreateApplicationShell: 'CewTitleFrame Test'argBlock: nil.

titleFrame := CewTitleFramecreateManagedWidget: 'titleFrame'parent: shellargBlock: [:w | w title: 'Direction'].

(radioBox := titleFramecreateRadioBox: 'radio'argBlock: nil)

manageChild.

(radioBoxcreateToggleButton: 'Up'argBlock: [:w | w set: true])

manageChild.

(radioBoxcreateToggleButton: 'Down'argBlock: nil)

manageChild.

shell realizeWidget

FontsThe font used by certain widgets can be specified by the application. The followingwidgets allow their font to be changed: CwLabel, CwPushButton, CwToggleButton,CwCascadeButton, CwText, CwList, CwComboBox, and CwScale. The font is changedusing the fontList: method. The font to use is specified by a CwFontList object.

To create a CwFontList, the fontStruct: class method of CwFontList is passed aCgFontStruct describing a Common Graphics font. A CgFontStruct can be loadedusing the loadQueryFont: method of CgDisplay. For further details on fonts, consult“Using fonts” on page 93.

Chapter 7. Common Widgets 211

Page 226: IBM Smalltalk: Programmer's Reference

The following code creates a multiline text widget and sets its font to themonospaced font named ‘8x13.’| shell fontStruct fontList text |shell := CwTopLevelShell

createApplicationShell: 'shell'argBlock: [:w | w title: 'Font List Example'].

fontStruct := shell display loadQueryFont: '8x13'.fontList := CwFontList fontStruct: fontStruct.

text := shellcreateText: 'text'argBlock: [:w | w

editMode: XmMULTILINEEDIT;fontList: fontList].

text setString: 'This text is displayed using the 8x13 font.'.text manageChild.

shell realizeWidget

Using the system browser fontAll of the browsers in IBM Smalltalk are subclasses of EtWindow. This class keepsone font that every browser uses. You can find the browser font name byevaluating:EtWindow fontName.

You can change the browser font from the File menu. If the browser font has notbeen changed, then the EtWindow class method fontName returns nil. If yourwindow will use the browser font, then you can make the window a subclass ofEtWindow. Your subclass should provide the instance method fontSettableWidgets,which answers a collection of all the widgets to be notified in case the fontchanges. EtWindow calls all of these widgets for you and tells them to change tothe new font.

You can still use the browser font, even if your window does not subclassEtWindow. The following example creates a new window with the system font. Theclass method fontList in EtWindow returns either the current CwFontList, or nil if thefont has not been changed.|shell text fontList|shell := CwTopLevelShell

createApplicationShell: 'shell'argBlock: [:w | w title: 'Browser Font' ].

fontList := EtWindow fontList.fontList isNil ifTrue: [

fontList := CwFontList fontStruct:(CgDisplay default defaultFontStruct) ].

text := shellcreateText: 'text'argBlock: [:w | w

columns: 60;editMode: XmMULTILINEEDIT;fontList: fontList ].

text setString: 'This font is the system browser font.'.text manageChild.shell realizeWidget

212 IBM Smalltalk: Programmer’s Reference

Page 227: IBM Smalltalk: Programmer's Reference

ColorsThe background and foreground color of widgets can be set and queried by theapplication using the backgroundColor and foregroundColor resources. TheforegroundColor is used for text or other foreground graphics, and thebackgroundColor is used to fill the background of the widget. The color values arespecified using CgRGBColor objects which allow the application to specify the red,green, and blue components of the desired color. See “Specifying colors” onpage 113 for more information concerning the use of CgRGBColor objects. There areplatform-specific limitations concerning setting the colors of certain widgets. See“Appendix E. Common widgets platform differences” on page 517 for the details ofthese limitations.

Tip: Due to platform-specific limitations, a widget might not take on a requestedcolor setting, or it might take on a slightly different color setting thanrequested. To determine the exact color a widget is using, the resource can bequeried after it is set. Querying the color resource always returns the color thewidget is actually using. For details on platform limitations, see “Appendix”.

The following code creates a multiline text widget and sets its foregroundColor toblack and its backgroundColor to blue.| shell text |shell := CwTopLevelShell

createApplicationShell: 'shell'argBlock: [:w | w title: 'Color Example'].

text := shellcreateText: 'text'argBlock: [:w | w

editMode: XmMULTILINEEDIT;columns: 50;rows: 4;value: 'Hello';foregroundColor: CgRGBColor white;backgroundColor: (shell screen lookupColor: 'blue')].

text manageChild.

shell realizeWidget

Clipboard operationsCommon Widgets provides operations to interact with the platform clipboard,which holds data to be transferred between applications. An application can copydata from Smalltalk to the clipboard, and paste data from the clipboard intoSmalltalk.

Data stored in the clipboard has an associated format name, which applications useto identify the type of data. Common Widgets automatically handles twopredefined formats, string and pixmap, which are mapped to the correspondingplatform-specific format during clipboard operations. Applications can also workwith platform-specific formats, or define new proprietary formats. The formatnames and corresponding buffer object classes used to represent data whenworking with the clipboard include the following:STRING

StringPIXMAP

CgPixmapAll others

ByteArray

Chapter 7. Common Widgets 213

Page 228: IBM Smalltalk: Programmer's Reference

The class CgDisplay implements the clipboard operations. All operations require aCgWindow parameter, which identifies the application to the OS window system.The window can be any valid CgWindow. The available clipboard operationsinclude the following:

clipboardStartCopy:clipLabel:itemIdReturn:Sets up OS clipboard storage and data structures to receive data

clipboardCopy:itemId:formatName:buffer:privateId:Copies data to the clipboard

clipboardCancelCopy:itemId:Cancels a copy operation that has been started

clipboardEndCopy:itemId:Ends a copy to the clipboard

clipboardInquireCount:countReturn:Returns the number of data item formats in the clipboard

clipboardInquireFormat:index:formatNameReturn:Returns the format of a data item

clipboardInquireLength:formatName:lengthReturn:Returns the length of the stored data

clipboardStartRetrieve:Starts a copy from the clipboard

clipboardRetrieve:formatName:bufferReturn:privateIdReturn:Retrieves a data item from the clipboard

clipboardEndRetrieve:Ends a copy from the clipboard

clipboardLock:Locks the clipboard

clipboardUnlock:Unlocks the clipboard

clipboardRegisterFormat:formatLength:Registers a new format

Examples for using the clipboardThe following examples show how to copy String data to and from the clipboard.

Example 1: copying data to the clipboard| window itemId copyText |

window := CgWindow default.copyText := 'This text will be copied'.itemId := ReturnParameter new.

"Set up storage and data structures."window display

clipboardStartCopy: windowclipLabel: 'STRING'itemIdReturn: itemId.

"Copy a data item of String format to temporary storage."window display

clipboardCopy: windowitemId: itemId valueformatName: 'STRING'

214 IBM Smalltalk: Programmer’s Reference

Page 229: IBM Smalltalk: Programmer's Reference

buffer: copyTextprivateId: 0.

"End the clipboard transaction."window display

clipboardEndCopy: windowitemId: itemId value.

Example 2: retrieving data from the clipboard| window status bufferHolder lengthHolder |

window := CgWindow default.

"Ask for the length of the string in the clipboard."status := window display

clipboardInquireLength: windowformatName: 'STRING'lengthReturn: (lengthHolder := ReturnParameter new).

status = ClipboardSuccessifTrue: [

Transcript cr; show: 'XmClipboardStatus...', status printString; cr.|self].

"Retrieve a string from the clipboard and place it in bufferHolder."status := window display

clipboardRetrieve: windowformatName: 'STRING'bufferReturn: (bufferHolder := ReturnParameter new)privateIdReturn: ReturnParameter null. "Ignore result"

status = ClipboardSuccessifTrue: [

Transcript cr; show: 'XmClipboardStatus...', status printString; cr.|self].

|bufferHolder value

Platform-integrated drag and dropCommon Widgets provides platform-integrated drag and drop capabilities toVisualAge applications. Common Widgets drag and drop gives applications accessto the native drag and drop systems of each platform, and minimizes the need towrite platform-specific code. Common Widgets drag and drop is based on theOSF/Motif R1.2 drag and drop model.

Platform-integrated drag and drop involves two sides: the source and thedestination. The source and destination can be the same application or differentapplications. For example, a user can drag from a widget that is part of applicationA and drop on that same widget, on another widget in application A, or on awidget in application B.

When a user performs a valid drop, data is transferred from the source to thedestination. In Common Widgets drag and drop, data transfer can be done atseveral levels of complexity. The levels of data transfer include the following,beginning with the simplest:v Data transfer using built-in types. For example, String data can be transferred

using ‘STRING’ and CgPixmap data can be transferred using ‘PIXMAP.’v ByteArray data transfer. This is the default.v Custom data transfer, which enables you to add to the set of built-in types.

To complete the first two levels of data transfer, you do not need to writeplatform-specific code. These types of data transfer are described in this section. To

Chapter 7. Common Widgets 215

Page 230: IBM Smalltalk: Programmer's Reference

complete a custom data transfer you must extend Common Widgets drag and dropby writing custom converters, which is not covered in this manual.

Target typesA target type is a string that represents the type of data transfer to perform whena valid drop occurs. Target types are equivalent to format names, which are usedby the Common Widgets clipboard. Common Widgets drag and drop provides twobuilt-in target types that are supported on all platforms:‘STRING’

Specifies that a String is transferred‘PIXMAP’

Specifies that a CgPixmap is transferred

Also can also use their own target types, for example, ‘EMPLOYEE.’ WhenCommon Widgets drag and drop encounters a target type that is not built in, aByteArray is transferred. An application must provide a ByteArray on the sourceside, and interpret the ByteArray data on the destination side. ByteArray datatransfer is a flexible way to transfer data without writing any platform-specificcode.

Transferring dataThree types of data transfers can be performed when a valid drop occurs: move(XmDROPMOVE), copy (XmDROPCOPY), or link (XmDROPLINK). The type oftransfer chosen depends on the advertised capabilities of each side involved in thetransfer and on the state of the keyboard at the time of the drop. If no type oftransfer can be chosen (XmDROPNOOP), then the drop is invalid. The user canaffect the type of transfer chosen by pressing the following keys while dragging:

Shift Forces a move if both sides support moving, otherwise no type of transfercan be chosen

Ctrl Forces a copy if both sides support copying, otherwise not type of transfercan be chosen

Ctrl+ShiftForces a link is both sides support linking, otherwise no type of transfercan be chosen

If no key is pressed while dropping, then the system chooses the first of move,copy, or link (in that order) that is supported by both sides. If no type of transfer issupported by both sides, then no type of transfer can be chosen.

Applications must ensure that the semantics of the data transfer are consistent withthe following conventions:

Move The destination first gets a copy of the data, then tells the source to deletethe data.

Copy The source and destination both keep a copy of the data.

Link The source keeps the only copy of the data, and the destination establishesa link to that copy.

216 IBM Smalltalk: Programmer’s Reference

Page 231: IBM Smalltalk: Programmer's Reference

Drag and drop objectsA drag and drop object is like a widget. It has resources that can be set andretrieved, and a mechanism for notifying an application of user actions. Most dragand drop object resources are set in the create argBlock. The notificationmechanism is implemented using procs.

ProcsA proc is like a callback. It can be hooked to a drag and drop object to notify anapplication of various events in the drag and drop process. A proc is specific to thetype of object and is represented by an instance of CwCallbackRec. When called, thethird parameter sent to a proc is a callData object created by Common Widgetsdrag and drop.

Unlike callbacks, only one of each type of proc can be hooked to a drag and dropobject at any given time, and most procs are mandatory. A proc must be hooked inthe create argBlock using a proc resource setter. The first parameter sent to a procis a drag and drop object or a widget, depending on the proc.

Common Widgets drag and drop classesThe public API of Common Widgets drag and drop includes the following classes,along with some methods in CwWidget and in callback data classes.

CwDragDropObject hierarchy

The CwDragDropObject class implements drag and drop objects. CwDragDropObjectis an abstract class that provides resource and proc methods to its subclasses. Thehierarchy looks like the following:

CwDragDropObjectCwDragContextCwDropSiteCwDropTransfer

CwDropTransferEntry

The CwDropTransferEntry class is used in the data transfer process. Instances ofCwDropTransferEntry contain a targetType and a transferClientData object.

Drag source widgets and the CwDragContext objectA drag source widget has a dragDetectCallback hooked that sends thedragStart:argBlock: method of CwWidget. To start a drag from a drag source widget,the user holds down a mouse button while over the widget and moves the mouseto a different location.

Note: The mouse button that initiates a drag is platform dependent. On Windowsplatforms, the left mouse button triggers a dragDetectCallback. On OS/2, theright mouse button triggers it. And, on OSF/Motif platforms, the middlemouse button triggers it.

Some platforms allow dragging with a button other than those listed above.To implement this behavior, applications call dragStart:argBlock: from abutton event handler.

The following example hooks a dragDetectCallback to a specified widget:

Chapter 7. Common Widgets 217

Page 232: IBM Smalltalk: Programmer's Reference

hookDragDetect: aCwWidget"Hook a dragDetect callback to the specified widget."aCwWidget

addCallback: XmNdragDetectCallbackreceiver:selfselector: #dragDetect:clientData:callData:clientData: nil.

When a drag begins over the widget, dragDetect:clientData:callData: is sent to thereceiver. The parameters to this callback are as follows:

widget The CwWidget to which the dragDetact callback hooks (aCwWidget)

clientDataThe clientData specified when the dragDetect callback was hooked (nil)

callDataAn instance of CwDragDetectCallbackData.

The CwDragDetectCallbackData instance contains a ButtonPress event that candetermine the mouse position and button when the button is pressed. The callDatareason is either XmCRDRAG or XmCRDRAGSELECT.

On platforms that allow the left mouse button to initiate a drag, normal dragselection might cause the dragDetectCallback to be amibiguous in certain widgets,such as text and list widgets. In these cases, the callData reason will beXmCRDRAGSELECT and the application can decide whether to allow the dragselection to continue, or set the callData doit to false and start a drag.

OSF/Motif platforms provide default drag behavior in text, label, and buttonwidgets. Common Widgets drag and drop turns off this behavior in a widget whena dragDetect callback is added.

Starting the drag—CwDragContextAn application starts a drag from a dragDetect callback handler by sendingdragStart:argBlock: with a CwDragContext create argBlock to the widget that receivedthe callback. Sending dragStart:argBlock: creates a CwDragContext which representsthe drag source for the duration of the drag and drop operation. Only one instanceof CwDragContext can exist at any time, and the instance ceases to exist when thedrag and drop operation is complete.

Note: The dragStart:argBlock: message must only be sent from a dragDetect callbackhandler or a button press event handler. The first parameter must be thebutton press event that initiated the drag.

The following drag context resources can be set in the create argBlock when thedrag starts:

sourceCursorAllThe CgIcon that replaces the mouse cursor during dragging.

dragOperationsThe operations that the drag source supports.

exportOperationsThe target types that the drag source supports, in order of sourcepreference with the most complete and accurate representation of the datafirst.

convertProcA proc that is received one or more times after a valid drop, in which the

218 IBM Smalltalk: Programmer’s Reference

Page 233: IBM Smalltalk: Programmer's Reference

source application must provide the dragged data in the format specifiedby the target type in the proc’s callData. The convert proc will be called asmany time as the destination requests, each time with a different targettype. A source must be preparted to provide the data in the proper formatfor any of the export targets it supports. It passes the data to thedestination by filling in the value field of the the proc’s callData.

The following code shows a typical dragDetect callback handler. It starts a drag,specifying the operations and targets that the drag source supports and hooking aconvertProc to handle the source side of the data transfer. Assume that self dragIconanswers a CgIcon.dragDetectCallback: aCwWidget clientData: clientData callData: callData

"Handle the dragDetect callback for the receiver."| startDrag |(startDrag := callData reason = XmCRDRAG)

ifFalse: ["The reason is XmCRDRAGSELECT.Decide if the user is doing a drag or a select."(self checkDragSourceCoordinates: callData event x @ callData event y)

ifTrue: ["Interpret the mouse action as a drag operationrather than a selection operation. Set the doit flag to false toprevent the widget from doing normal selection processing."callData doit: false.startDrag := true]].

startDragifTrue: [

aCwWidgetdragStart: callData eventargBlock: [:dragContext |

dragContextsourceCursorIcon: self dragIcon;dragOperations: XmDROPMOVE | XmDROPCOPY;exportTargets: #('STRING');convertProc: (CwCallbackRec

receiver: selfselector: #convertProc:clientData:callData:clientData: aCwWidget)]].

Drop site widgets and CwDropSite objectsA drop site widget is a widget that has been registered as a drop site. The user candrop onto a drop site widget by first dragging from a drag source widget, andthen moving the mouse over to the drop site widget and releasing the mousebutton.

Preparing to accept drops: CwDropSiteThe application registers a widget as a drop site by sending it the dropSiteRegister:message of CwWidget with a CwDropSite create argBlock. Sending dropSiteRegister:creates a CwDropSite which represents the drop site during any drag and dropoperation. The following drop site resources can be set in the create argBlock:

dropSiteOperationsThe operations that the drop site supports

importTargetsThe target types that the drop site supports, in order of drop sitepreference

Chapter 7. Common Widgets 219

Page 234: IBM Smalltalk: Programmer's Reference

dragProcAn optional proc that is received whenever the mouse moves over thedrop site widget during a drag. The callData reason can be one of thefollowing:Enter XmCRDROPSITEENTERMESSAGEMotion

XmCRDRAGMOTIONMESSAGELeave XmCRDROPSITELEAVEMESSAGEOperation changed

XmCROPERATIONCHANGEDMESSAGE

The destination application can check the location of the mouse todetermine whether a drop in that location is acceptable, and modify theoperation and dropSiteStatus fields of the proc’s callData accordingly.Modifications to these fields produces a corresponding change in theappearance of the drag cursor. In addition, a drag proc can be used toprovide visual feedback to the user about the drop site. For example, toindicate that the cursor is over some semantic area in the widget, anapplication might draw a border around the area.

dropProcA proc that is received when a mouse button is released over the drop site.The destination application must determine whether the drop operation isacceptable in that location. If the operation is valid, it must decide whichtarget types to request and then ask the drag context to start the datatransfer using those types.

The following code registers the specified widget as a drop site. This establishesthe operations and targets that the drop site supports, as well as hooking adragProc and a dropProc:registerDropSite: aCwWidget

"Register the specified widget as a drop site."aCwWidget

dropSiteRegister: [:dropSite |dropSite

dropSiteOperations: XmDROPMOVE | XmDROPCOPY;importTargets: #('STRING');dragProc: (CwCallbackRec

receiver: selfselector: #dragProc:clientData:callData:clientData: nil);

dropProc: (CwCallbackRecreceiver: selfselector: #dropProc:clientData:callData:clientData: nil)].

Note: OSF/Motif platforms provide default drop behavior in text widgets.Common Widgets drag and drop turns off this behavior in a widget whenthe widget is registered as a drop site.

The drag procThe dragProc resource is optional. A destination application can supply a dragproc when it creates a drop site if it wants to perform special drag-underanimation, or select the operation based on some internal state or the semanticlocation of the cursor in the drop site. The parameters to the dragProc are asfollows:widget The CwWidget that was registered as a drop siteclientData

The clientData specified when the dragProc was hooked

220 IBM Smalltalk: Programmer’s Reference

Page 235: IBM Smalltalk: Programmer's Reference

callDataAn instance of CwDragProcCallbackData

The following code shows a dragProc handler which does drag-under animationbased on the coordinates of the mouse in the callData, and chooses the operationbased on the mouse coordinates and the valid operations in the callData. Assumethe following:v dropRectanglesFor: answers a collection of rectangles that are acceptable drop

areas in the given widget.v operationForRectangle:widget:callData: answers the operation chosen by the

destination application, given a drop rectangle in the widget, and the operation,operations and dropSiteStatus of the callData.

v animateRectangle:widget:operation: does drag-under animation for a drop rectanglein a given widget, based on the selected operation.

v removeAllAnimation: removes all drag-under animation effects from the givenwidget.

dragProc: widget clientData: clientData callData: callData"Handle the drag proc for the receiver."| point rectangle op |

"Turn off platform drag-under animation."callData animate: false.

point := callData x @ callData y.(self dropRectanglesFor: widget)

do: [:rect |(rect containsPoint: point)

ifTrue: [rectangle := rect]].rectangle isNil

ifTrue: [op := XmDROPNOOP]ifFalse: [op := self

operationForRectangle: rectanglewidget: widgetcallData: callData].

op = XmDROPNOOPifTrue: [

"The point is not in a drop rectangle for the widget,or the operation is not valid for the drop rectangle."callData

operation: XmDROPNOOP;dropSiteStatus: XmDROPSITEINVALID.

self removeAllAnimation: widget]

ifFalse: ["The point is in one of the drop rectangles for the widget,and the operation is valid."callData

operation: op;dropSiteStatus: XmDROPSITEVALID.

self animateRectangle: rectangle widget: widget operation: op].

callData reason = XmCRDROPSITELEAVEMESSAGEifTrue: [self removeAllAnimation: widget].

The drop procThe destination application must supply a drop proc when it creates a drop site. Inthe drop proc, the destination determines if the drop is valid, and starts the dropdata transfer. The parameters to the dropProc are as follows:widget The CwWidget that was registered as a drop siteclientData

The clientData specified when the dropProc was hooked

Chapter 7. Common Widgets 221

Page 236: IBM Smalltalk: Programmer's Reference

callDataAn instance of CwDropProcCallbackData

Note: Some platforms allow the user to press the help key (usually F1) during adrag. In this case, a drop proc is sent with the dropAction field in the callDataset to XmDROPHELP.

Two different dropProc handlers are shown in the following code. Both examplescall startTransfer:targetTypes:clientData:. The code for this method is shown in thefollowing section on the CwDropTransfer object.

The first example shows a very simple dropProc handler. This drop site onlysupports the ’STRING’ target type. If the dropProc is called, the drop site knowsthat the operation is valid and the drag source also supports ’STRING,’ therefore itcan simply ask for the data in ’STRING’ format.dropProc: widget clientData: clientData callData: callData

"Handle the drop proc for the receiver."callData dropAction = XmDROPHELP

ifTrue: ["Help is not supported, therefore this is an invalid operation."|callData dropSiteStatus: XmDROPSITEINVALID].

"A valid drop has occurred. Start a transfer, requesting our only target type."self startTransfer: callData targetTypes: #('STRING') clientData: widget.

The second example dropProc is more complex. This drop site supports more thanone target type. In addition, the drop site cares about the semantic location of themouse, as did the example dragProc in the previous subsection, and it may decidethat the operation is invalid. Assume that intersectionOf: answers anOrderedCollection containing the intersection of two collections, and thatdropRectanglesFor: and operationForRectangle:widget:callData: are the same methodsused in the dragProc example.dropProc: widget clientData: clientData callData: callData

"Handle the drop proc for the receiver."| point rectangle op exportTargets importTargets intersection |

callData dropAction = XmDROPHELPifTrue: [

"Help is not supported, therefore this is an invalid operation."|callData dropSiteStatus: XmDROPSITEINVALID].

point := callData x @ callData y.(self dropRectanglesFor: widget)

do: [:rect |(rect containsPoint: point)

ifTrue: [rectangle := rect]].

op := rectangle isNilifTrue: [XmDROPNOOP]ifFalse: [self operationForRectangle: rectangle

widget: widget callData: callData].

op = XmDROPNOOPifTrue: [

"The point is not in a drop rectangle for the widget,or the operation is not valid for the drop rectangle."callData

operation: XmDROPNOOP;dropSiteStatus: XmDROPSITEINVALID]

ifFalse: ["The point is in one of the drop rectangles for the widget,and the operation is valid."callData operation: op].

222 IBM Smalltalk: Programmer’s Reference

Page 237: IBM Smalltalk: Programmer's Reference

callData dropSiteStatus = XmDROPSITEVALIDifTrue: [

"Valid drop. Start a transfer, requesting all possible target types."exportTargets := callData dragContext exportTargets.importTargets := widget dropSite importTargets.intersection := self intersectionOf: exportTargets and: importTargets.self startTransfer: callData targetTypes: intersection clientData: widget].

Data transfer and the CwDropTransfer objectThe data transfer is the final stage in the drag and drop process. Both the sourceapplication and the destination application are involved in the data transfer—thesource through the convertProc (described previously), and the destination throughthe transferProc (described below). The destination starts the data transfer from adropProc by specifying a list of one or more target types it would like the source toprovide. Common Widgets drag and drop takes over at this point. For each targettype requested, it sends a convertProc to the source to get the data, and then sendsa transferProc to the destination, containing the data from the source.

A destination can add target types to the list of requests during the transferprocess if necessary, permitting it to change what it requests based on datareceived. If the operation was a move, the destination must add the special‘DELETE’ target to the request list, which the system will send to the convertProc,so that the source knows when it is safe to delete the data.

Starting the data transfer—CwDropTransferThe data transfer is started from a dropProc handler by sending thedropTransferStart: message, with a CwDropTransfer create argBlock, to the dragcontext, which is provided in the dropProc’s callData.

Sending dropTransferStart: creates a CwDropTransfer which represents the datatransfer in progress. There can only be one instance of CwDropTransfer in existenceat any time and it ceases to exist when the data transfer is complete. The followingdrop transfer resources can be set in the create argBlock when the transfer isstarted:

dropTransfersAn OrderedCollection of CwDropTransferEntry objects. There is one entry foreach target type requested by the drop site.

transferStatusThe status of the transfer. It can be either success(XmTRANSFERSUCCESS), which is the default, or failure(XmTRANSFERFAILURE). transferStatus can be updated by the destinationapplication.

transferProcA proc that is received one or more times after a valid drop, in which thedestination application must use the data converted by the sourceapplication. The target type and converted value of the data are given inthe proc’s callData. The transfer proc will be called as many times as thedestination requests, each time with a different target that was converted.A destination must be prepared to use any of the target types it requests. Ifthe operation was a move, the transfer proc must add a ’DELETE’ targetwhen it has successfully received all of the converted data from the source.

The following example method was called from the dropProc example code in theprevious subsection. It creates a collection of CwDropTransferEntry objects using thespecified targetTypes and clientData, and starts the data transfer with these.

Chapter 7. Common Widgets 223

Page 238: IBM Smalltalk: Programmer's Reference

startTransfer: callData targetTypes: targetTypes clientData: clientData"Called from a dropProc to start the drop transfer."| dropTransfers |

dropTransfers := OrderedCollection new.targetTypes do: [:target |

dropTransfersadd: (CwDropTransferEntry

target: targettransferClientData: clientData)].

callData dragContextdropTransferStart: [:dropTransfer |

dropTransferdropTransfers: dropTransfers;transferProc: (CwCallbackRec

receiver: selfselector: #transferProc:clientData:callData:clientData: callData)].

The convert procThe source application must supply a convert proc when it creates a drag context.The convert proc is where the source provides the dragged data in the formatspecified by its callData target type. The parameters to the convertProc are asfollows:

aCwDragContextThe CwDragContext created for the drag

clientDataThe clientData specified when the convertProc was hooked

callDataAn instance of CwConvertProcCallbackData

The following code shows a typical convert proc. Assume that stringFromWidget:answers the selected string in the specified widget, and deleteStringFromWidget:deletes the selected string from the specified widget.

Note: You can use the clientData parameter to find out the drag source widgetinside the convert proc.

convertProc: aCwDragContext clientData: dragSource callData: callData"Handle the convert proc for the receiver."| target |(target := callData target) = 'STRING'

ifTrue: ["Convert to requested type, and set value."callData value: (self stringFromWidget: dragSource)]

ifFalse: [target = 'DELETE'

ifTrue: ["The operation was XmDROPMOVE, and the destinationsuccessfully received the data. Delete the data from the source."self deleteStringFromWidget: dragSource]].

Note: A convertProc is usually sent to the source application, and then thecorresponding transferProc is sent to the destination application. On someplatforms, the convertProc is called for all of the dragContext’s export targetswhen the drag starts. Thus, applications should not count on the order ofconvertProc and transferProc calls.

224 IBM Smalltalk: Programmer’s Reference

Page 239: IBM Smalltalk: Programmer's Reference

The transfer procThe destination application must supply a transfer proc when it creates a droptransfer. The transfer proc is where the destination receives the dragged data fromthe source in the format specified by the target type in the transfer proc’s callData.The parameters to the transferProc are as follows:

aCwDropTransferThe CwDropTransfer created for the data transfer

clientDataThe clientData specified when the transferProc was hooked

callDataAn instance of CwTransferProcCallbackData

The following code shows a typical transfer proc. Assume thatstringToWidget:string:x:y:link: writes a string into the drop site widget, given thestring, the coordinates of the drop, and a Boolean describing whether the dropoperation was XmDROPLINK. (XmDROPLINK is usually more meaningful fordata other than ‘STRING’). The drop site widget was passed to the proc (by thestartTransfer:targetTypes:clientData: example method) in the callData’stransferClientData.

Note: You can use the clientData parameter to find the dropProc’s callData inside thetransfer proc. The callData is usually necessary to know because it containsthe operation and the coordinates of the mouse at the drop.

transferProc: aCwDropTransfer clientData: dropProcCallData callData: callData"Handle the convert proc for the receiver."callData value isNil ifTrue: [

"Conversion failed. The source did not pass any data."|self errorMessage: 'Conversion failed.'].

callData target = 'STRING'ifTrue: [

selfstringToWidget: callData transferClientDatastring: callData valuex: dropProcCallData xy: dropProcCallData ylink: (dropProcCallData operation = XmDROPLINK)].

"If this was a move operation, and if we have just received thelast dropTransfer, then send a 'DELETE' target to the dragsource's convert proc."(dropProcCallData operation = XmDROPMOVE

and: [callData target = aCwDropTransfer dropTransfers last target])ifTrue: [

aCwDropTransferdropTransferAdd: (CwDropTransferEntry

target: 'DELETE'transferClientData: callData transferClientData)].

The user interface process modelThe Common Widgets user interface has been modeled based on the input eventprocessing model supported by OSF/Motif. A central event processing loop readsevents from the operating system and dispatches them to individual widgets thatprocess them appropriately. This event model, called polling, is the basis of mostmodern graphical user interfaces (GUIs) including OSF/Motif, Microsoft Windows,IBM OS/2 Presentation Manager, and the Apple Macintosh operating system.

Chapter 7. Common Widgets 225

Page 240: IBM Smalltalk: Programmer's Reference

In Common Widgets, the event polling loop has been implemented fully withinhigh-level Smalltalk code. This has a number of significant benefits to theapplication programmer:v Existing Motif application programmer knowledge is maintained, because

custom event loops can be constructed in the standard Motif style without fearof error-causing interactions with hidden event handling mechanisms.

v Event polling occurs only at controlled points during system execution, soapplication code runs at maximum speed.

v The system requires none of the cumbersome and error-prone low-levelsynchronization code required when systems attempt to hide the event loopbelow the control of the application programmer.

v Complex multithreaded applications can safely perform work in backgroundprocesses, while the user interface process continues to keep the user interfaceresponsive.

With Common Widgets, only the single Smalltalk user interface process ispermitted to dispatch events or directly perform user interface operations.Common Widgets facilitates a proactive approach to event management, asopposed to a defensive one. Rather than write code to defend themselves againstasynchronous user interface events, such as exposes, menu operations, or userinput, application developers control the user interface event processing. Eventprocessing is fully synchronous from the perspective of the user interface process,although it can be asynchronous from the perspective of non-UI processes.

Unfortunately, with increased capability comes increased responsibility. In the caseof the polled event model, application programmers are responsible for writingtheir applications in ways that allow polling to occur at frequent intervals. Theresponsiveness of an application (that is, the delay between the availability of anevent and processing of the event by the application) is directly effected by thefrequency at which the application polls. Although they vary in their sensitivity tofailures, all of the GUIs mentioned above specify that frequent polling is requiredto maintain application responsiveness.

Common Widgets provides support for maintaining application responsivenesswhile long-running tasks execute. This support is based on the Common ProcessModel together with a standard application program interface (API) for managingthe interactions between non-UI tasks and the user interface. This is discussed indetail in the following sections. First, a system view is presented, which providesan overview of the implementation of these mechanisms, and then an applicationview is presented, which discusses how the mechanisms are used in buildingapplications.

The system viewIn Smalltalk images that include a user interface (Common Widgets), the startUpclass (System startUpClass) is responsible for providing a polling loop for the userinterface process, an instance of UIProcess. The UIProcess sends the messagemessageLoop to the startUp class to start the polling loop. The startUp class,EsWindowSystemStartUp, implements a simple polling loop similar to the oneshown below:messageLoop

"Run the dispatch loop."[true] whileTrue: [

CwAppContext default readAndDispatchifFalse: [ CwAppContext default sleep ]]

226 IBM Smalltalk: Programmer’s Reference

Page 241: IBM Smalltalk: Programmer's Reference

In general, application programmers never need to modify this code because itprovides full functionality for all but the most exceptional circumstances. However,as mentioned above, application programmers can replace this loop with theirown.

The message loop makes use of two methods defined in class CwAppContext:

readAndDispatchReads a single event, if one is available, from the underlying operatingsystem, dispatches it to the appropriate widget, and handles any callbacksthat occur. In addition, it handles any pending requests for user interfaceoperations by non-UI processes, as shown below. Finally, it returns true ifan event was processed and false otherwise.

sleep Checks for user interface activity, and if none, removes the UIProcess fromthe ready-to-run queue. The system assumes there is user interface activityin the following cases:v There are events to processv There are background user interface requests to be runv There are work procs registeredv There are timer procs registered

As long as there is any activity in the user interface, the UIProcess will continue topoll for events as quickly as possible. As soon as the activity stops, the UIProcessbecomes inactive and suspends. This enables any other Smalltalk processes that arerunning at the the same or lower priority than the UIProcess to execute.

Because sending CwAppContext messageLoop can deactivate the UIProcess, theremust be a mechanism for reactivating it. To support this, sleep enables anoperating-system-specific mechanism that causes the private messageCwAppContext default wake to be sent when new events become available. This wakemethod is also sent by all other methods that generate user interface activity,causing the UIProcess to respond immediately.

If the underlying operating system does not provide any mechanism for triggeringuser-written code when events become available, the CwAppContext can stillfunction by generating a Smalltalk process that wakes the UIProcess at regularintervals. By default, this is called the “CwAsyncIOProcess”.

As previously mentioned, if there is no user interface activity the UIProcess isdeactivated, enabling other Smalltalk processes at the same or lower priority torun. However, if there are no other active processes to run, a system-provided“idle” process is run, which repeatedly sends the suspendSmalltalk message to thedefault CwAppContext:

suspendSmalltalkSuspends the entire IBM Smalltalk system, using an operating-system-specific facility, until there is event activity. When the IBM Smalltalksystem is suspended it consumes little or no processor resources. Undermultitasking operating systems this enables other applications full access tothe CPU.

As soon as input is available, both the IBM Smalltalk system and the UIProcess arereactivated, because they are higher priority than the idle process.

If the operating system does not provide a facility for suspending execution of anapplication until input is available, the suspendSmalltalk method simply returns to

Chapter 7. Common Widgets 227

Page 242: IBM Smalltalk: Programmer's Reference

its sender. In this case, Common Widgets continues to run normally, but IBMSmalltalk competes for resources with any other applications being run by theoperating system.

Note that there is an interaction between the suspendSmalltalk method and theSmalltalk Delay class. If the idle process runs because a higher priority process hassuspended on a Delay, the system must be reactivated when the Delay expires. Thissituation is handled in one of three ways depending on the capabilities of theoperating system:v With operating systems where the Delay class uses the same mechanism that

suspendSmalltalk uses to detect input activity, the system is reactivated with nofurther intervention.

v With operating systems where Delay uses a different mechanism thansuspendSmalltalk, but it is possible for a user written application to post a userinterface event, this facility is used to reactivate the system.

v If neither of the above mechanisms are available, IBM Smalltalk checks forDelays and deactivates the system only when there are none pending.

The application programmer’s viewThis section looks at the impact of the input polling method on application code.

When programming with OSF/Motif, or other modern window systems,application programmers writing simple applications typically do not worry muchabout the details of the input model. They simply define the the widgets that makeup their application windows, register the appropriate callbacks, or equivalent, forthe user actions of interest, and implement the code for these callbacks. Althoughthis is ideally true, one important aspect is sometimes not considered: becausecallbacks are run by the same process that is running the user interface, all of thecode that is run by the callback (an operation) is run before the application returnsto polling. Thus, when long-running operations are run, applicationresponsiveness, and whole system responsiveness on some operating systems isaffected.

In Common Widgets, programmers construct applications using the standardOSF/Motif model described above. However, additional facilities are provided toallow long running operations to execute without impacting responsiveness.

Because IBM Smalltalk provides support for multiple, priority-scheduled threads ofcontrol, or processes, operations that do not use user interface facilities can be runby a separate, low priority process, called a background process. The userinterface remains responsive because it is higher priority than the backgroundprocess and is activated whenever input is available.

Unfortunately, OSF/Motif itself does not use a multithreaded model and thus it isnot possible for multiple application processes to concurrently execute userinterface code, for example, redrawing a widget, performing an individualgraphical operation, or reading an event. Some kind of synchronization isnecessary.

It is possible for each application to implement its own synchronization schemethat prevents background processes from attempting to concurrently execute userinterface code. However, IBM Smalltalk provides standard mechanisms to supportthis kind of synchronization.

228 IBM Smalltalk: Programmer’s Reference

Page 243: IBM Smalltalk: Programmer's Reference

Background user-interface requestsA background user interface request is a block of code that must be run by theUIProcess at a point when no other user interface code is being run. The followingtwo methods are then implemented in class CwAppContext to take background userinterface requests.

Tip: A background (non-UI) process must never make widget or graphics requestsdirectly—it must use syncExecInUI: or asyncExecInUI: to ask the user interfaceto issue the request on its behalf.

Background user interface requests are run by atomically interleaving theirexecution with the event and callback processing of the user interface process.Once execution of the block has been started, no further user interface events canbe processed until execution of the block has been completed.

asyncExecInUI

The asyncExecInUI UIProcess executes a block during readAndDispatch processing, atthe next “clean” point, that is, at the next point where it is not already executinguser interface code. No result is returned.

Processes with higher priority than the UIProcess do not block when this method isrun. In this case, aBlock is run the next time the UI becomes active and reaches aclean point. Processes at the same or lower priority than the UIProcess normallyblock until aBlock has been run, but this is not guaranteed.

The process that runs this message is not provided any indication of when aBlockhas been run. In particular, it is not guaranteed that aBlock has been run when themethod returns.

If this message is sent by code that is executing in the UIProcess, then aBlock is runafter all previously queued background user interface requests have been run.

Tip: A background process can reawaken the UIProcess and cause a context switch(because the UIProcess is higher priority) by executing: CwAppContext defaultasyncExecInUI: []

syncExecInUI:

The syncExecInUI: UIProcess runs a block during readAndDispatch processing, at thenext “clean” point, that is, at the next point where it is not already executing userinterface code. The result of evaluating aBlock is returned.

Execution of the process that evaluates this method always suspends until aBlockhas been evaluated.

If this message is sent by code that is executing in the UIProcess, the block is runimmediately.

Both of these methods are implemented to add the code to be run, aBlock, to acollection of background user interface requests maintained by the CwAppContext.This collection is FIFO ordered so operations can use syncExecInUI: to ensure thatall previously sent asyncExecInUI: messages have been processed.

After adding the request, both of the above methods reactivate the UIProcess if itwas sleeping. As was described in the previous section, the CwAppContextprocesses the background user interface requests as part of the normal functioning

Chapter 7. Common Widgets 229

Page 244: IBM Smalltalk: Programmer's Reference

of the readAndDispatch method. Processing of pending background user interfacerequests is interleaved with user interface event dispatching.

Using the above methods, it is possible for programmers to construct applicationsthat are both responsive and contain long running operations. The long-runningoperations are run by background tasks that use asyncExecInUI: or syncExecInUI: toaccess the user interface. Obviously, the programmer is responsible for ensuringthat the individual blocks that are passed to the asyncExecInUI: methods do nottake an unusually long time to execute.

Tip: Because execution of background graphics requests can be deferred whileevents are processed, background user interface request blocks must beprepared for eventualities such as widgets being destroyed between therequest being posted and run.

Work procs and timer procsIn addition to background user interface requests, there are two other mechanismsthat can be used to defer execution or have a method repeatedly executed. Thefollowing two methods are in the class CwAppContext. Unlike the background userinterface request methods described above, work procs and timer procs can onlybe registered by the UI process itself. As with background user interface requests,work procs and timer procs are sent from the event loop during idle processing.

The processing of active work procs and timer procs prevents the user interfaceprocess from suspending, and background processes will not run until all workprocs and timer procs have been removed. However, the enableProcs: message inCwAppContext can be used to temporarily disable work proc and timer procprocessing in order to allow the UIProcess to suspend.

As with background user interface requests, work procs and timer procs are onlyprocessed by the UIProcess during readAndDispatch processing. If the UIProcess iscompute bound, no work procs or timer procs will be processed until the UIProcessreturns to the event loop.

Note: Keep the amount of work done in a work proc or timer proc to a minimum.If they are too long, they keep the UIProcess from returning to the eventloop, which can cause user interface responsiveness to degrade.Long-running operations should be coded in background tasks that useasyncExecInUI: or syncExecInUI: to access the user interface.

addWorkProc:receiver:selector:clientData:

This message adds a work proc for idle UI processing, and returns an object whichuniquely identifies the work proc. This object can later be used to remove the workproc using removeWorkProc:. The 1-parameter message defined by selector isrepeatedly sent to receiver (with clientData as the parameter) while the event loopis idle waiting for events. Multiple work procs may be added, and the last oneadded is called first. If the work proc message returns true, then it is automaticallyremoved and will not be called again.

addTimeOut:receiver:selector:clientData:

This message adds a timer proc which is sent after the specified number ofmilliseconds have elapsed, and returns an object which uniquely identifies thetimer proc. As with work procs, this object can be used later to remove the timerproc before it expires if it is no longer needed. Multiple timer procs can be added,

230 IBM Smalltalk: Programmer’s Reference

Page 245: IBM Smalltalk: Programmer's Reference

but unlike work procs, timer procs are always sent only once. When the intervalexpires, the 1-parameter message specified by selector is sent to receiver withclientData as parameter.

Note: Because timer procs are only sent when the UI is idle, they may not expireat the exact time specified. They are only guaranteed to expire after thegiven number of milliseconds have passed.

The UI idle processing mechanisms are as follows:

asyncExecInUI: syncExecInUI: addWorkProc:... addTimerProc:...

Can be registered byany process

Can be registered byany process

Can be registeredonly by UI process

Can be registeredonly by UI process

Next pending blockevaluated at next UIidle

Block evaluatedimmediately if calledfrom UIprocess—otherwisenext pending blockevaluated at next UIidle

Next pendingmessage sent at nextUI idle

Next expiredmessage sent at nextUI idle

No return value Returns result ofblock

Returns workProc ID Returns timerProc ID

Block evaluated onceonly

Block evaluated onceonly

Message sentrepeatedly until itreturns true

Message sent onceonly

Processed in FIFOorder

Processed in FIFOorder

Processed in LIFOorder

Processed in LIFOorder

Cannot be disabled Cannot be disabled Can be disabled Can be disabled

Examples of applications with long-running operationsThe following are some overviews of suggested implementation styles whenbuilding applications with long-running operations using IBM Smalltalk. Theseexamples are intended to show typical ways that applications can be written usingIBM Smalltalk. Of course, every application is different so developers can use anyor all of these techniques, or construct new idioms that are more appropriate totheir problem domain. The important point to remember is that, there are nosurprises. Every aspect of the polling model is accessible to the applicationdeveloper. Nothing is done “under the covers.”

Example 1: a simple text editorA simple text editing application is constructed using IBM Smalltalk. Theapplication is responsive in all situations except while reading or writing the filethat is being edited. To maintain responsiveness in this situation, file reading andwriting are moved to a background process. The operations are modified to use amodal “percentage complete” dialog that is updated by the background processusing asyncExecInUI:. When the file has been completely read or written, thebackground process uses a call to syncExecInUI: to close the dialog.

Example 2: a program development environmentA program development environment is constructed that uses a database to storesource code. Saving large segments of source code is found to cause a lack ofresponsiveness because several database accesses are required. To maintainresponsiveness, the saving operation is modified to:v Disable any menus or buttons that could affect the saving operation

Chapter 7. Common Widgets 231

Page 246: IBM Smalltalk: Programmer's Reference

v Change the cursor to indicate that an operation is “in progress”v Generate a background process that first saves the source to the database, and

then uses asyncExecInUI: to re-enable the menus and buttons and set the cursorback to normal.

Example 3: a complex drawing editorA drawing editor is constructed that allows large, complex drawings to be built.The system is responsive in all situations except while updating a display of alarge drawing. The update display (refresh) operation is modified as follows:v First, it checks the complexity of the drawing (for example, by detecting the total

number of primitive graphical objects that it contains) and if it is below aparticular threshold, it refreshes the drawing directly.

v If the drawing is too complex to refresh in the UIProcess, the operation changesthe cursor to indicate that a refresh operation is “in progress.”

v Then it generates a background process that draws the diagram, one componentat a time, using a background user interface request for each component. Afterthe diagram is redrawn, the application sets the cursor back to its standardshape using a synchronous background user interface request. The applicationretains a reference to the background process in order to terminate it if the userperforms some action that invalidates its usefulness (for example, resizing orclosing the window, or using a menu entry to request another refresh or switchto a different drawing).

Notice that in this example, the same code could be used to do the actualrefreshing of the drawing, regardless of whether it is being run by the UIProcess orby a background process, because the “ExecInUI” methods can always be called byboth background processes and the UIProcess.

232 IBM Smalltalk: Programmer’s Reference

Page 247: IBM Smalltalk: Programmer's Reference

Chapter 8. Extended Widgets

This chapter describes the Extended Widgets (EW) subsystem. The ExtendedWidgets classes and methods enable application developers to expand upon thegraphical user interfaces built using the Common Widgets (CW) subsystem.Common Widgets provides a framework for developing custom widgets. Thefamily of Extended Widgets discussed in this document was developed using thisframework. For a description of the CW subsystem API and the extended widgetframework, refer to “Chapter 7. Common Widgets” on page 135.

Extended Widgets class hierarchyThe following table describes the class hierarchy of extended widgets and classresponsibilities.

Table 38. Widgets hierarchyClass hierarchy ResponsibilityCwWidget Defines common behavior for all widgets

CwExtendedWidget Defines common behavior for all extended widgetsCwExtendedComposite Defines common behavior for all extended composites

EwNotebook Abstract superclass for notebook widgetsEwPMNotebook Displays a OS/2 look and feel notebookEwWINNotebook Displays a Windows look and feel notebook

EwPage Defines a composite that can be added to notebooksEwSplitWindow Splits a composite into panes and provides bars for

allowing the user to resize the panesEwToolbar Displays and lays out rows of tools

CwExtendedPrimitive Defines common behaviors for all extended primitivesEwScrollable Abstract superclass for scrollable widgets

EwList Abstract superclass for list widgetsEwIconArea Displays list of items in free-form styleEwLinearList Abstract superclass for linear lists of items

EwContainerList Abstract superclass for lists that are container-like viewsEwIconList Displays single-column list of items in icon and label

formatEwFlowedIconList Displays multi-column list of items in icon and label

formatEwIconTree Displays hierarchical single-column list of items

EwTableList Displays multi-column list of items in tabular formatEwTableTree Displays hierarchical list of items in tabular format

EwDrawnList Displays a list with application-drawn itemsEwSlider Displays an analog representation of a range of valuesEwSpinButton Displays an entry field with two arrow buttons for cycling

through a range of values.

EwConstants pool dictionaryThe Extended Widgets subsystem uses a pool dictionary called EwConstants toprovide pool variables for constant values that are used as arguments to ExtendedWidgets methods. These pool variable names should be used instead of directlyusing their constant values. Classes that require pool variable names must includethe EwConstants pool dictionary in their class definition.

© Copyright IBM Corp. 1994, 2000 233

Page 248: IBM Smalltalk: Programmer's Reference

Many constants are also defined in the CwConstants pool dictionary. TheCwConstants pool dictionary should also be included in the class definition ofclasses that require these pool variable names.

Creation convenience methodsExtended widgets are created using convenience functions implemented asinstance methods of CwWidget. Convenience messages are sent to the widget that isto be the new widget’s parent. Following is a list of extended widget creationconvenience methods:v createDrawnList:argBlock:v createFlowedIconList:argBlock:v createIconArea:argBlock:v createIconList:argBlock:v createIconTree:argBlock:v createPMNotebook:argBlock:v createProgressBar:argBlock:v createScrolledDrawnList:argBlock:v createScrolledFlowedIconList:argBlock:v createScrolledIconArea:argBlock:v createScrolledIconList:argBlock:v createScrolledIconTree:argBlock:v createScrolledTableList:argBlock:v createScrolledTableTree:argBlock:v createSlider:argBlock:v createSpinButton:argBlock:v createSplitWindow:argBlock:v createTableList:argBlock:v createTableTree:argBlock:v createToolBar:argBlock:v createWINNotebook:argBlock:

Extended list widgetsThe Common Widgets subsystem provides the CwList widget so that applicationscan display lists of strings that can be viewed, selected, and scrolled. Because it isoften more convenient to interact with and display collections of random objects,the Extended Widgets subsystem allows applications to create container widgetsthat can contain arbitrary objects and provide visual presentations other thansimple text. Some of these widgets have a hierarchical (tree) version that displayshierarchical lists of objects.

The extended container widgets use different techniques for drawing the itemsprovided by applications:v EwDrawnList uses callbacks to request customized drawing of items by an

application.v EwIconList, EwIconTree, EwFlowedIconList, and EwIconArea use callbacks to request

icons and labels that represent each item from an application.v EwTableList and EwTableTree use callbacks to request the objects to be displayed

in individual cells.

234 IBM Smalltalk: Programmer’s Reference

Page 249: IBM Smalltalk: Programmer's Reference

Common resourcesAll extended container widgets support the items resource. The items resourcerepresents the collection of objects to be displayed in a list. The widgets alsoprovide itemCount and selectionPolicy resources. These are similar to the resourcesof the same name in the common widgets’ CwList. All extended container widgetssupport using an OrderedCollection for the items resource. Some of the widgets aremore flexible in the value type for the items resource. Consult the definition of theitems resource in a particular widget to see what type of value is required.

Tip: Most of the extended list widgets (all except for EwlconArea) support orderedlists. The lists are protocol compatible with CwList. Items can be added,deleted, replaced, or selected in the items list using standard CwList protocol.

Scrolled listsEach of the container widgets can be created with scrolling capability, much likeCwList. All resources and callbacks associated with a particular list can be appliedto the scrolled version of that list. Scrolling is handled automatically. ThescrollHorizontal resource specifies whether the widget should provide a horizontalscroll bar.

Tip: The horizontal scroll bar will not be shown in the list widget unless it hasbeen created as a scrolled list, even if the scrollHorizontal resource is set totrue.

The scrollBarDisplayPolicy resource controls the automatic placement of the scrollbars. If the resource is set to XmASNEEDED, scroll bars are displayed if the listitems exceed the list work region in one or both dimensions. If the resource is setto XmSTATIC, scroll bars are displayed regardless of the relationship between thesize of the list items and the list work region.

In the following example, a scrolled EwIconList is created as a child of a form.Creating a scrolled list inserts a CwScrolledWindow parent between the list and thereceiver of the creation message, in this case, the form. It is important tounderstand this distinction when attaching a scrolled list to a form or attachingother form children to the list.| shell form iconList |shell := CwTopLevelShell

createApplicationShell: 'shell'argBlock: [:w | w title: 'Scrolling List Example'].

form := shellcreateForm: 'form'argBlock: nil.

form manageChild.iconList := form

createScrolledIconList: 'scrolled list'argBlock: [ :w | w

items: self itemList;scrollHorizontal: true].

iconList manageChild.

"Note: The icon list's parent is sent attachment messages."iconList parent

setValuesBlock: [:w | wtopAttachment: XmATTACHFORM;rightAttachment: XmATTACHFORM;leftAttachment: XmATTACHFORM;bottomAttachment: XmATTACHFORM].

shell realizeWidget.

Chapter 8. Extended Widgets 235

Page 250: IBM Smalltalk: Programmer's Reference

Tip: When a scrolled list is created, the creation message returns an instance of thelist (the child of a CwScrolledWindow). However, because the CwScrolledWindowis itself the child of the form, form attachment messages must be sent to thelist’s parent (that is, to the CwScrolledWindow). Any other form childrenattaching to the scrolled list should be attached to the list’s parent.

Drawn list widgetThe application-drawn list widget (EwDrawnList) allows an application to drawarbitrary graphics to represent each object in the list. It combines list behavior witha drawing area-based widget. Following is an example of a drawn list widget:

An application hooks the displayCallback to draw the items in the list. If the itemsin the list have different sizes, an application should hook the measureCallback tospecify the height of each individual item in the list. If all items have the sameheight, the itemHeight resource can be used to specify the height in pixels.

The applicationDrawnStates resource allows for the specification of visuals for any ofthe emphasis states in the list, such as selection emphasis or cursored emphasis.Applications can choose to allow the drawn list to provide these emphasis visuals.In the following code, a list of CgFontStructs is added to a drawn list, and eachfont name in the list is drawn with the font that it describes.Object subclass: #DrawnListExample

instanceVariableNames: 'fontStructs'classVariableNames: "poolDictionaries: 'CgConstants CwConstants EwConstants'

open| shell drawnList |shell := CwTopLevelShell

createApplicationShell: 'shell'argBlock: [:w | w title: 'Drawn List Example'].

fontStructs := ((CgDisplay default listFonts: '*' maxnames: 100)collect: [:fontName |

CgDisplay default loadQueryFont: fontName]) asOrderedCollection.

drawnList := shellcreateScrolledDrawnList: 'drawnList'argBlock: [ :w | w items: fontStructs].

drawnListaddCallback: XmNdisplayCallbackreceiver: selfselector: #display:clientData:callData:clientData: nil;

236 IBM Smalltalk: Programmer’s Reference

Page 251: IBM Smalltalk: Programmer's Reference

addCallback: XmNmeasureCallbackreceiver: selfselector: #measure:clientData:callData:clientData: nil;

addCallback: XmNdestroyCallbackreceiver: selfselector: #destroy:clientData:callData:clientData: nil.

drawnList manageChild.shell realizeWidget.

display: widget clientData: clientData callData: callData"Display the fontStruct by drawing its font name in theupper left-hand corner of the specified rectangle, usingthe fontStruct as the font."

| fontStruct |fontStruct := callData object.callData gc setFont: fontStruct font.callData drawable

drawString: callData gcx: callData xy: callData y + fontStruct ascentstring: fontStruct name

measure: widget clientData: clientData callData: callData"Measure the fontStruct by querying its height."| fontStruct |fontStruct := callData object.callData height: fontStruct height

destroy: widget clientData: clientData callData: callData"Destroy the fontStruct collection."

fontStructs do: [:fontStruct | fontStruct freeFont].

Icon list widgetsAn icon list widget (EwIconList) displays each of the items in its list as a labelledicon. Following is an example of an icon list widget:

The application hooks the visualInfoCallback to specify the label and icon for eachobject in the list. Typically, an application provides both an icon and a string in thiscallback. However, either value can be set to nil if only the icon or label is desired.

Tip: If your application requires a view with either an icon or label per item, butnot both, set the icon to nil, and the label to the desired visual object for eachitem in the visualInfoCallback callData. Set the labelOrientation resource of thewidget to XmRIGHT (default), and set the emphasisPolicy resource of thewidget to XmTOGETHER.

Chapter 8. Extended Widgets 237

Page 252: IBM Smalltalk: Programmer's Reference

In the following example, a list of classes is added to an icon list. The class name isused as the label of each item, and each item in the list displays the same icon.Object subclass: #IconListExample

instanceVariableNames: 'icon'classVariableNames: "poolDictionaries: 'CwConstants EwConstants'

open| iconList shell |shell := CwTopLevelShell

createApplicationShell: 'shell'argBlock: [:w | w title: 'Icon List Example'].

iconList := shellcreateScrolledIconList: 'iconList'argBlock: [ :w | w items: Object subclasses].

iconListaddCallback: XmNvisualInfoCallbackreceiver: selfselector: #visualInfo:clientData:callData:clientData: nil.

shelladdCallback: XmNdestroyCallbackreceiver: selfselector: #destroy:clientData:callData:clientData: nil.

icon := shell screengetIcon: 'default_xm_information' foregroundColor: CgRGBColor black.

iconList manageChild.shell realizeWidget.

visualInfo: widget clientData: clientData callData: callData"Provide the icon and label for the class contained in the callData."

callDatalabel: callData item name;icon: icon

destroy: shellWidget clientData: clientData callData: callData"Free the icon resource."

shellWidget screen destroyIcon: icon

RenderablesIn the Common Widgets subsystem, widgets require applications to provide astrongly typed visual object. For example, labels are required to be an instance ofString, and images must be instances of CgIcon or CgPixmap. In the ExtendedWidgets subsystem, the visual object types are less restrictive. Most extendedwidget label, icon, or image resources require only that the supplied visual objectconform to a specified rendering protocol. Any object that conforms to thisprotocol and can display (render) itself is called a renderable.

To be renderable, an object needs to implement the following messages to providesizing information and perform drawing operations: ewWidthUsing:,ewHeightUsing:, and ewDrawUsing:. The classes CgDeviceIndependentImage, CgIcon,CgPixmap, Character, Object, String, and UndefinedObject have been extended toprovide rendering protocol. Instances of these classes can be supplied for anyextended widget resource requiring a renderable.

You can add rendering protocol to other visual objects in your application. Forexample, a colored string renderable can be made by combining a String and aCgRGBColor into a ColoredString object.

238 IBM Smalltalk: Programmer’s Reference

Page 253: IBM Smalltalk: Programmer's Reference

Tip: When you are prototyping, the overhead of creating icons can be aninconvenience. Because any renderable can be used in the container widgets itis sometimes useful to use a String in place of a CgIcon.

Direct editing of labelsThe icon widgets (EwIconList, EwFlowedIconList, EwIconArea, and EwIconTree) can beconfigured to allow dynamic editing of an item’s label. The application mustdetermine what user action is to trigger the editing of a label. After this action isdetected, the application should request editing of a specific item.

When an edit action is requested, the widget fires the beginEditCallback todetermine the specific editing policy (see “Edit policies” on page 246). Whenediting is complete, the widget activates the endEditCallback to allow theapplication to save the edited value as appropriate.

The following example enables label editing in an icon list. ThedefaultActionCallback is used to trigger editing of the label.Object subclass: #IconListEditingExample

instanceVariableNames: 'icon'classVariableNames: "poolDictionaries: 'CwConstants EwConstants'

open| iconList shell |shell := CwTopLevelShell

createApplicationShell: 'shell'argBlock: [:w | w title: 'Icon List Example'].

iconList := shellcreateScrolledIconList: 'iconList'argBlock: [ :w | w

items: #('first item' 'second item' 'third item' 'fourth item')asOrderedCollection].

iconListaddCallback: XmNvisualInfoCallbackreceiver: selfselector: #visualInfo:clientData:callData:clientData: nil;

addCallback: XmNdefaultActionCallbackreceiver: selfselector: #defaultAction:clientData:callData:clientData: nil;

addCallback: XmNbeginEditCallbackreceiver: selfselector: #beginEdit:clientData:callData:clientData: nil;

addCallback: XmNendEditCallbackreceiver: selfselector: #endEdit:clientData:callData:clientData: nil.

icon := shell screengetIcon: 'default_xm_information' foregroundColor: CgRGBColor black.

shelladdCallback: XmNdestroyCallbackreceiver: selfselector: #destroy:clientData:callData:clientData: nil.

iconList manageChild.shell realizeWidget.

Chapter 8. Extended Widgets 239

Page 254: IBM Smalltalk: Programmer's Reference

defaultAction: widget clientData: clientData callData: callData"Request editing of the selected object."widget editItemAt: callData itemPosition

beginEdit: widget clientData: clientData callData: callData"Initiate the edit for the specified item."

callData doit: true

endEdit: widget clientData: clientData callData: callData"End the edit for the specified item. Replace the old textwith the new text."

widgetreplaceItems: (Array with: callData item)

newItems: (Array with: callData newValue)

visualInfo: widget clientData: clientData callData: callData"Provide the icon and label for the class contained in the callData."callData

icon: icon;label: callData item.

destroy: shellWidget clientData: clientData callData: callData"Free the icon resource."

shellWidget screen destroyIcon: icon

Flowed icon list widgetA flowed icon list widget (EwFlowedIconList) provides a vertical, multi-column listof items with an icon and a label for each item. Items are arranged in rows with asmany items per row as can fit in the available width. Each item’s width and heightare determined by the itemWidth and itemHeight resources. Thus, the dimensions ofthe rows and columns are fixed. Following is an example of a flowed icon listwidget:

The icons and labels an application supplies in the visualInfoCallback can be anyrenderable or nil (see “Renderables” on page 238). This is the same as EwIconList.

The following example shows the creation of a flowed icon list (thevisualInfoCallback is not shown).| flowedIconList shell |shell := CwTopLevelShell

createApplicationShell: 'shell'argBlock: [:w | w title: 'Flowed Icon List Example'].

flowedIconList := shellcreateScrolledFlowedIconList: 'flowedIconList'argBlock: [ :w | w

items: Object subclasses;itemWidth: 200;itemHeight: 36].

flowedIconList manageChild.shell realizeWidget.

240 IBM Smalltalk: Programmer’s Reference

Page 255: IBM Smalltalk: Programmer's Reference

Icon area widgetThe icon area widget (EwIconArea) provides a free-form display of objects in a list.The widget displays a text label and icon for each item in the list, using the sametechnique as with EwIconList to supply icons and labels. Following is an exampleof an icon area widget:

Each item in the list is associated with a location, which is a Point representingwhere the item is displayed in the icon area. Items can be added to the list at aspecific location using the addItem:location: or addedItem:location: protocol.

Items in an icon area can be rearranged so that no items overlap using thearrangeItems function. The icons and labels an application supplies in thevisualInfoCallback can be renderable (see “Renderables” on page 238). This is thesame as EwIconList. The following example creates an icon area and adds an itemat a specific point (the visualInfoCallback is not shown).| iconArea shell |shell := CwTopLevelShell

createApplicationShell: 'shell'argBlock: [:w | w title: 'Icon Area Example'].

iconArea := shellcreateScrolledIconArea: 'iconArea'argBlock: nil.

iconArea manageChild.

shell realizeWidget.iconArea addItem: 'Fred' location: 25@30.

Table list widgetThe table list widget (EwTableList) displays various attributes for each item in thelist. Each item is displayed in its own row of the table. An application can specifythe displayed attributes for each item by defining columns and adding them to thetable. The value of a specific item’s attribute is contained in a cell. A specific cellcan be described by specifying the row in which a particular item is displayed andthe column in which a particular attribute value is displayed. Following is an

Chapter 8. Extended Widgets 241

Page 256: IBM Smalltalk: Programmer's Reference

example of a table list widget:

Tip: The objects used for cell values and headings are typically Strings, Numbers,and CgIcons, but this is not a requirement. It is possible for an application touse any renderable object as the cell value or heading (see “Renderables” onpage 238).

Table list resourcesTo use all of a table list’s features, an application must set resources and callbacksfor the table list widget and for its individual columns.

The columns of the table list widget are defined by the columns resource thatshould be set to a collection of EwTableColumn instances. The resources that can beset for each column are described in “Table columns” on page 243.

The table list widget supports the standard selection policies, plus additionalpolicies for cell selection.

Standard selection policiesAdditional policies for cell selection

XmSINGLESELECTStandard selection policies apply to the rows in the table as a whole

XmEXTENDEDSELECTStandard selection policies apply to the rows in the table as a whole

XmMULTIPLESELECTStandard selection policies apply to the rows in the table as a whole

XmBROWSESELECTStandard selection policies apply to the rows in the table as a whole

XmCELLSINGLESELECTAllows individual cells to be selected

XmCELLBLOCKSELECTAllows contiguous blocks of rows to be selected

The table list selection policies involve a separate protocol. Messages such asselectPos:notify: and deselectAllItems are used with the standard policies. Messagessuch as selectCell:notify: and deselectCell: are used with the cell selection policies. Itis important to ensure that the protocol being used at any given time is

242 IBM Smalltalk: Programmer’s Reference

Page 257: IBM Smalltalk: Programmer's Reference

appropriate for the widget’s selection policy. Row selection methods should not beused with cell selection policies and vice versa.

Many resources affect the visual appearance of the table:

visualStyleSpecifies whether the rows or individual cells should have an etched, threedimensional appearance

headingSeparatorThicknessControls the appearance of the line between column headings and therows of cell values

headingVisualStyleSpecifies whether the column heading should have an etched, threedimensional appearance

rowSeparatorsSpecifies whether lines should be drawn between each row

separatorsToExtremesSpecifies whether row separators should stop at the last column orcontinue to the border of the widget

lockedColumnsSpecifies the number of columns that should be locked on the left-handside. When a column is locked, it does not scroll when the list is scrolledhorizontally. This allows certain anchor columns to always remain visible,such as an icon or name column.

editableSpecifies whether the cell values in the table can be edited. This can becontrolled for each individual column. Editing is discussed in “Directediting of cell values” on page 245 and “Edit policies” on page 246.

Table columnsThe EwTableColumn objects in a table list have their own set of resources andcallbacks. The cellValueCallbackmethod obtains the renderable object that representsthe value of a column in a particular row.

Additional resources control the appearance of the column and its heading. Theheading resource can be set to a renderable object that is to be displayed at the topof a particular column. The resizable resource controls whether users can resize thecolumn to a different width by dragging the right side of the column heading.Other resources control the size, alignment, and visual style of the column.

The following code creates a table list with the subclasses of the class Object as itsitems. The first column displays an icon, the second displays the name of the class,and the third displays the class’s comment.Object subclass: #TableListExample

instanceVariableNames: 'icon'classVariableNames: "poolDictionaries: 'CwConstants EwConstants '

open| shell tableList |shell := CwTopLevelShell

createApplicationShell: 'shell'argBlock: [:w | w title: 'Table List Example'].

Chapter 8. Extended Widgets 243

Page 258: IBM Smalltalk: Programmer's Reference

tableList := shellcreateScrolledTableList: 'scrolled list'argBlock: [:w | w

columns: self columns;items: Object subclasses;selectionPolicy: XmSINGLESELECT].

"Note: The destroyCallback is not shown."icon := shell screen

getIcon: 'default_xm_information' foregroundColor: CgRGBColor black.

tableList manageChild.shell realizeWidget

columns"Answer a collection of EwTableColumns."| OrderedCollection new

add: self iconColumn;add: self nameColumn;add: self commentColumn;yourself

iconColumn"Answer the column for the class' icon."| col |col := EwTableColumn new

editable: false;resizable: false;width: 36;horizontalAlignment: XmALIGNMENTCENTER;yourself.

coladdCallback: XmNcellValueCallbackreceiver: selfselector: #iconCellValue:clientData:callData:clientData: nil.

|colnameColumn

"Answer the column for the class' name."| col |col := EwTableColumn new

editable: false;heading: 'Class Name';resizable: true;width: (CgFontStruct default textWidth: 'Class Name');horizontalHeadingAlignment: XmALIGNMENTCENTER;yourself.

coladdCallback: XmNcellValueCallbackreceiver: selfselector: #textCellValue:clientData:callData:clientData: #name.

| col

commentColumn"Answer the column for the class' comment."| col |col := EwTableColumn new

editable: false;heading: 'Comment';resizable: true;width: 512;horizontalHeadingAlignment: XmALIGNMENTCENTER;yourself.

coladdCallback: XmNcellValueCallbackreceiver: selfselector: #textCellValue:clientData:callData:clientData: #comment.

| col

244 IBM Smalltalk: Programmer’s Reference

Page 259: IBM Smalltalk: Programmer's Reference

iconCellValue: widget clientData: clientData callData: callData"Set the cell's value to the an icon."

callData value: icon

textCellValue: widget clientData: clientData callData: callData"Set the cell's value to the string answered by the listitem when the clientData is sent to it as a message."

callData value: (callData item perform: clientData)

Direct editing of cell valuesThe application programming interface (API) for user editing of cell values issimilar to the interface provided by EwIconList. The main difference with a tablelist widget is that the beginEditCallback and endEditCallback resources are used toprovide editing facilities for individual cell values rather than for items in the list.Cell editing can take place automatically as individual cells are selected, or it canoccur under application control by using editing functions.

Cell editing can automatically begin when a user clicks on a cell. To enableautomatic cell editing the following resources must be set:v The editable resource of the table list widget must be set to true.v The editable resource of each column in which cells are to be edited must be set

to true.v The selectionPolicy resource of the table list must be set to

XmCELLSINGLESELECT or XmCELLBLOCKSELECT.

When cell editing is under application control, editing begins when the applicationsends editCellAt: or editSelectedCell to the table list widget. These functions can beused to trigger cell editing regardless of the value of the editable resource in thetable or in its columns.

In both automatic editing and application-controlled editing, an application mustspecify a callback handler for the beginEditCallback and endEditCallback resources foreach column that is to provide editing capability. When a cell is about to be edited,either because you clicked in it or because the application sent editCellAt: oreditSelectedCell, the column activates its beginEditCallback. The application musthook this callback for editing to occur. At a minimum, the application must set thecallData doit flag to true to allow editing to begin.

Editing ends when the widget loses focus or another item is selected. When thishappens, or when the value in the edit widget has been changed (the exact detailsof when a change has occurred depend on the edit policy; see “Edit policies” onpage 246), the column activates its endEditCallback. The callData includes the oldvalue and the new value. Your application should hook this callback and save thenew edited value in your application as appropriate. The cell is then automaticallyrefreshed after the callback is sent, so that the new value is obtained anddisplayed.

The following code builds on the previous example and shows how cell editingcan be provided. First, the table list must be created in a slightly different way:...tableList := shell

createScrolledTableList: 'scrolled list'argBlock: [:w | w

columns: self columns;items: Object subclasses;

Chapter 8. Extended Widgets 245

Page 260: IBM Smalltalk: Programmer's Reference

"Automatic editing is provided by setting the table list to beeditable and setting the selection policy to XmCELLSINGLESELECT."editable: true;selectionPolicy: XmCELLSINGLESELECT].

tableList manageChild....

Next, the comment columns beginEditCallback and the endEditCallback must behooked, and the editable resource must be set to true:commentColumn

"Answer the column for the class' comment."| col |col := EwTableColumn new

editable: true;heading: 'Comment';resizable: true;width: 512;horizontalHeadingAlignment: XmALIGNMENTCENTER;yourself.

coladdCallback: XmNcellValueCallbackreceiver: selfselector: #textCellValue:clientData:callData:clientData: #comment;

addCallback: XmNbeginEditCallbackreceiver: selfselector: #beginEditText:clientData:callData:clientData: nil;

addCallback: XmNendEditCallbackreceiver: selfselector: #endEditText:clientData:callData:clientData: nil.

| col

Finally, the handlers must be written for the beginEditCallback and theendEditCallback.beginEditText: widget clientData: clientData callData: callData"About to start editing a text field. Ensure the doit field is true."

callData doit: true

endEditText: widget clientData: clientData callData: callData"Editing of a cell has just completed. Accept the valueand place it into the appropriate place in the list item."

callData item comment: callData newValue

Edit policiesFor simple text editing of cell values, an application need only provide simplebeginEditCallback and endEditCallback handlers. In some advanced applications,simple text editing of a cell might not be sufficient. In these situations, theapplication can specify an edit policy in the callData of the beginEditCallback.

The edit policy defines the type of widget to be used for editing and some otheredit semantics. The default edit policy is EwTextEditPolicy set up to use asingle-line CwText as the edit widget. The application can substitute a moreappropriate edit policy. For example, if the cell contains a day of the week, theapplication might wish to use an EwComboBoxEditPolicy. Applications can define

246 IBM Smalltalk: Programmer’s Reference

Page 261: IBM Smalltalk: Programmer's Reference

custom edit policies by subclassing EwEditPolicy as required. The suppliedsubclasses of EwEditPolicy serve as good examples of this.

The following edit policies are provided in the Extended Widgets subsystem:

EwComboBoxEditPolicyA cell is edited using a combo box. An application can specify the list ofitems to choose from and the initial value. It can also specify whether userscan edit the value manually or just choose one of the items in the list.

EwTextEditPolicyA cell is edited using a text widget. An application can specify whether thewidget is to be single or multiple lines, what the initial text value shouldbe, what the initially selected text should be, and what the maximumlength should be.

EwToggleButtonEditPolicyA cell is edited using a toggle button. An application can specify the labelstring for the toggle button, the horizontal alignment of the label stringand whether or not the toggle should be initially selected.

Note: The EwTextEditPolicy and EwComboBoxEditPolicy cancel an edit operationwhen the ESC key is pressed. When an edit operation is cancelled, theendEditCallback is activated using the item’s old value as the edited value.

Tree widgetsTree widgets (EwIconTree and EwTableTree) provide a hierarchical view of the itemsin a list. Only the top-level items of a hierarchy (the roots) are set in the itemsresource of a tree widget. The childrenCallback must be hooked so an applicationcan provide a collection of children for any of the items in the list. ThevisualInfoCallback must be hooked so an application can set the hasChildren flag inthe callData to indicate whether the item to be displayed has any children. Thisallows the tree widget to provide any visuals necessary to indicate that the itemhas children.

Tip: The childrenCallback is activated only for items in the list that return true asthe value of the hasChildren flag of the visualInfoCallback callData.

Tree widgets provide protocol that allows applications to control that branches ofthe tree are displayed. By default, only the roots of a tree are shown initially.Methods, such as expandPos:notify:, collapsePos:notify:, and expandCollapsePos:notify:,allow an application to expand or collapse branches of the tree.

The visual appearance of the tree depends upon the value of the hierarchyPolicyresource. This resource allows applications to specify the amount of indentationthat should be used to distinguish levels of a hierarchy. It also allows thespecification of specialized hierarchy graphics, such as lines drawn to connect theitems, or the button to be provided next to items that have children. By default, thehierarchyPolicy of tree widgets is an instance of EwHierarchyPolicy, with the linesflag set to true (indicating that lines should be drawn to illustrate the hierarchywhen expanded).

Another hierarchyPolicy class is provided, named EwIconHierarchyPolicy. This policyshows an icon beside each item that acts as the expand and collapse button. Toallow for proper animation of pressing the button, an application can specify adifferent icon to be used in each phase of the expand and collapse action.

Chapter 8. Extended Widgets 247

Page 262: IBM Smalltalk: Programmer's Reference

Tip: If the application allows hierarchy navigation using double-click actions, thenit must hook the defaultActionCallback to trigger expansion or collapse of thehierarchy. The icon hierarchy policy automatically expands and collapseswhen the user clicks on the icon.

Following are icon tree widgets with the default hierarchy policy and an iconhierarchy policy:

Icon treesIn the following example, an icon tree is created that displays the Smalltalk classhierarchy. The defaultActionCallback is hooked to allow navigation through the tree.Object subclass: #IconTreeExample

instanceVariableNames: 'icon'classVariableNames: "poolDictionaries: 'CwConstants EwConstants'

open| shell iconTree |shell := CwTopLevelShell

createApplicationShell: 'shell'argBlock: [:w | w title: 'Icon Tree Example'].

iconTree := shellcreateScrolledIconTree: 'iconTree'argBlock: [ :w | w

items: (Array with: Object)].

iconTreeaddCallback: XmNvisualInfoCallbackreceiver: selfselector: #visualInfo:clientData:callData:clientData: nil;

addCallback: XmNchildrenCallbackreceiver: selfselector: #children:clientData:callData:clientData: nil;

addCallback: XmNdefaultActionCallbackreceiver: selfselector: #defaultAction:clientData:callData:clientData: nil.

"Note: The destroyCallback is not shown."icon := shell screen

getIcon: 'default_xm_information' foregroundColor: CgRGBColor black.iconTree manageChild.shell realizeWidget.

248 IBM Smalltalk: Programmer’s Reference

Page 263: IBM Smalltalk: Programmer's Reference

children: widget clientData: clientData callData: callData"Provide the children of the object contained in the callData."

callData children: callData item subclasses.

defaultAction: widget clientData: clientData callData: callData"Toggle the expand and collapse state of the item in the callData."

widgetexpandCollapsePos: callData itemPositionnotify: false

visualInfo: widget clientData: clientData callData: callData"Provide the icon and label for the class contained in the callData.Also check whether the item has children."

callDataicon: icon;label: callData item name;hasChildren: callData item subclasses notEmpty

Table treesThe table tree widget (EwTableTree) is a combination of the table list widget andicon tree widget. Like the table list widget, it displays attributes of items incolumnar format. Like the icon tree widget, it also provides a hierarchical view ofthe items. The columns and their callbacks are created and set up in the same wayas they are for the table list widget.

The following example creates a scrolled table tree widget. The column definitionsand column callbacks are the same as the EwTableList example. ThedefaultActionCallback and childrenCallback methods are hooked and handled thesame as in the EwIconTree example. The visualInfoCallback must be hooked for atable tree. Athough the icon and label information are not specified (they arespecified as cell values), the hasChildren flag must be set.

Tip: The first column of the table tree is used to show the hierarchy (typically, thiscolumn shows icons). Because child items are indented, this column should bedefined with a larger width than a similar column for a table list widget.Also, it is a good idea to define this column as resizable.

Object subclass: #TableTreeExampleinstanceVariableNames: "classVariableNames: "poolDictionaries: 'CwConstants EwConstants'

open| shell tableList |shell := CwTopLevelShell

createApplicationShell: 'shell'argBlock: [:w | w title: 'Table Tree Example'].

tableList := shellcreateScrolledTableTree: 'scrolled table tree'argBlock: [:w | w

columns: self columns;items: (Array with: Object);selectionPolicy: XmCELLSINGLESELECT].

..."Callbacks are hooked as in previous examples"...

visualInfo: widget clientData: clientData callData: callData"Specify whether the item has children. All other values areprovided using cell value callbacks."

callData hasChildren: callData item subclasses notEmpty

Chapter 8. Extended Widgets 249

Page 264: IBM Smalltalk: Programmer's Reference

Notebook widgetsThe two notebook widgets (EwPMNotebook and EwWINNotebook) provideuser-interface elements that resemble the OS/2 notebook or the Windows tabbeddialog control. Each page of a notebook is a composite widget and can contain anarbitrary collection of child widgets. Both of these controls emulate existingplatform-specific controls and are available on all platforms.

Creating pagesBy themselves, notebook widgets do not offer much of an interface to users. Topresent a useful interface to users, notebooks must contain pages (EwPage). Pagesare created by sending one of the following messages to either a PM or WINnotebook:

createPage:argBlock:Creates a new page within the receiver and adds it to the end of thereceiver’s collection of pages. The first argument is the widget name for thenew page, the second is its argument block.

createPage:argBlock:before:Creates a new page within the receiver before an existing page within thereceiver. The last argument is the page that the new page is to precede.

createPage:argBlock:sharingWith:Creates a new page that shares widgets with another page in the receiver.The last argument is the page that defines the widgets shared by itself andthe new page.

createPage:argBlock:before:sharingWith:Creates a new page within the receiver that shares widgets with anotherpage. The new page is inserted before a page already within the receiver.

The following expression adds a page with a tab labeled ″Top Page″ to a notebook:topPage := notebook

createPage: 'envinfo_page'argBlock: [:w |

"Note: The tab label can be any renderable."w tabLabel: 'Top Page'].

topPage manageChild.

Use createPage:argBlock:sharingWith: if many pages of a notebook are to displaydifferent information in the same way; that is, each page will contain the samewidgets but with different information (for example, an address book). This willsave both the number of widgets needed and the speed of opening a notebook.

Tip: Pages only appear in the notebook if they are managed. To temporarily hide apage in a notebook without destroying the page widget, use theunmanageChild message.

CallbacksThe notebook and page widgets provide three different callbacks(pageChangeCallback, pageEnterCallback, and pageLeaveCallback) when a new page isbrought to the top. The notebook’s pageChangeCallback and a page’spageLeaveCallback both allow, by setting a doit flag to false, an application to stop anew page from being topped. This is useful when some input is still required fromthe user on the old page. If the previous callbacks have been activated successfully,the page’s pageEnterCallback will fire. This notifies an application of the new pagebeing brought on top. By hooking this callback, an application can delay the

250 IBM Smalltalk: Programmer’s Reference

Page 265: IBM Smalltalk: Programmer's Reference

creation of the children of a page (its widgets) until that page is brought on top forthe first time. Delayed pages can be useful when a notebook has many pages orinitial open time is critical.

PM notebook widgetThe PM notebook widget (EwPMNotebook) is used to create notebooks with thelook and feel of the OS/2 notebook control. By manipulating the values of a fewresources, a PM notebook widget can be made to adopt the range of looksavailable from the native PM notebook control. Following is an example of a PMnotebook widget:

A notebook’s image can be oriented so that the pages appear to turn vertically, likea flip chart, or horizontally, like a book. If the value of the orientation resource is setto XmHORIZONTAL, the binding will be drawn along the left side. If it is set toXmVERTICAL, the binding will appear on the top or bottom depending on thevalue of the backPagePosition resource.

A PM notebook is displayed as a graphic representation of a stack of pages. Imagesof page edges can be drawn so that later pages are above and to the right, orbelow and to the right of previous pages. This behavior is controlled by the valueof the backPagePosition resource. It can be set to XmTOPRIGHT orXmBOTTOMRIGHT.

PM notebooks distinguish between different kinds of pages, called major andminor pages. When a page is created, its tabType resource specifies whether it is amajor page (XmMAJOR), minor page (XmMINOR), or neither (XmNONE). Thetabs for major pages are always displayed. A minor page is associated with themajor page that precedes it. It only appears when its major page is on the top ofthe notebook. Pages that are not major or minor pages do not have displayabletabs. They can only be reached by using page buttons to traverse all of the pages.

The combination of orientation and backPagePosition resources determines howmajor and minor tabs are positioned. Major tabs are always drawn opposite thebinding. Minor tabs, which only appear when the major tab they follow is broughtto the top, are drawn on the remaining page side.

The value of the bindingType resource determines what type of binding is drawnalong the ″bound″ edge of the notebook’s collection of pages. Options include nobinding (XmNONE), a spiral binding (XmSPIRAL), or a solid binding (XmSOLID).

Chapter 8. Extended Widgets 251

Page 266: IBM Smalltalk: Programmer's Reference

The following example creates a PM notebook with several pages, each of whichlists the messages understood by a class. A single base page is created that sharesits widgets with the remaining pages.Object subclass: #PMNotebookExample

instanceVariableNames: 'list 'classVariableNames: "poolDictionaries: 'CwConstants EwConstants '

open"Create the necessary widgets."| shell notebook |shell := CwTopLevelShell

createApplicationShell: 'shell'argBlock: [:w | w

title: 'Notebook Example';width: 512;height: 384].

notebook := shellcreatePMNotebook: 'notebook'argBlock: [:w | w

bindingType: XmSPIRAL;orientation: XmVERTICAL;backPagePosition: XmBOTTOMRIGHT;majorTabWidth: (CgFontStruct default textWidth: 'ClassDescription')].

notebook manageChild.self createPagesOn: notebook.shell realizeWidget

createPagesOn: aNotebook"Create some pages on the given notebook."| basePage |

"Create the page that will define the widgets used by all pages."basePage := aNotebook

createPage: 'basePage'argBlock: [:w | w tabLabel: 'Object'].

basePage manageChild.basePage

addCallback: XmNpageEnterCallbackreceiver: selfselector: #pageEnter:clientData:callData:clientData: 'Object'.

list := basePagecreateList: 'list'argBlock: [:w | w

topAttachment: XmATTACHFORM;rightAttachment: XmATTACHFORM;leftAttachment: XmATTACHFORM;bottomAttachment: XmATTACHFORM].

list manageChild.

"Create the rest of the pages."#('Behavior' 'ClassDescription' 'Class' 'Metaclass') do: [:name |

| aPage |aPage := aNotebook

createPage: nameargBlock: [:w | w tabLabel: name]sharingWith: basePage.

aPage

addCallback: XmNpageEnterCallbackreceiver: selfselector: #pageEnter:clientData:callData:clientData: name;

manageChild]

252 IBM Smalltalk: Programmer’s Reference

Page 267: IBM Smalltalk: Programmer's Reference

pageEnter: widget clientData: clientData callData: callData"A notebook page has just been brought to the front. Fill in its values."

list items:((Smalltalk at: clientData asGlobalKey) selectors collect: [

:s | s asString])

WIN notebook widgetThe Microsoft Windows equivalent of a notebook control is a tabbed dialog.Instances of the class EwWINNotebook are used to create widgets resemblingWindows tabbed dialogs. Construction of notebooks using EwWINNotebook issimpler than with EwPMNotebook because only few aspects of the widget’sbehavior are under application control. There are only two resources; the height ofthe tabs, tabHeight, and the number of tabs per row, tabsPerRow. Following is anexample of a WIN notebook widget:

Some resources of an EwPage have no effect in a Windows notebook. Because aWindows notebook only displays tabs across the top and has no status area, thetabStyle and pageLabel resources have no effect.

The previous example can be modified to use an EwWINNotebook by substitutingthe following notebook creation code:...notebook := shell

createWINNotebook: 'notebook'argBlock: [:w | w

tabsPerRow: 4;tabHeight: 35].

notebook manageChild....

Progress bar widgetProgress bar widgets (EwProgressBar) reflect the current status of an applicationtask. The status is displayed as a percentage of the task that is complete. Ahorizontal or vertical bar is periodically updated by the application to indicate theprogress of a particular task.

Progress is demonstrated visually by filling the progress bar with the widget’sforeground color or by displaying a specified ribbonImage. The application isresponsible for periodically updating the fractionComplete resource to indicate theextent to which the task has been completed.

Resources are provided which allow the application to control the visualappearance of the progress bar widget.

Chapter 8. Extended Widgets 253

Page 268: IBM Smalltalk: Programmer's Reference

The orientation of the progress bar is specified using the orientation resource. Thedirection resource is used to determine which way the bar is filled in. For example,a progress bar with a vertical orientation and forward direction will fill in from thetop to the bottom.

The shadowType and shadowWidth resources allow shadows around the bar to bespecified, while the size of the bar itself within the widget can be specified usingthe innerHeight and innerWidth resources. The application may also use theshowPercentage and fontList resources to specify a percentage complete label and itsassociated font.

The following method creates a progress bar with a thick shadow that fills in fromthe bottom to the top. The Motif information icon is used to fill in the bar. Thepercentage complete is shown in the bar using the default font. Add this methodto a class that uses the pool dictionaries CwConstants and EwConstants.progressBarExample

| progressBar shell |shell := CwTopLevelShell

createApplicationShell: 'shell'argBlock: [:w | w

title: 'Progress Bar Example';width: 210;height: 100].

progressBar := shellcreateProgressBar: 'progressBar'argBlock: [:w | w

orientation: XmVERTICAL;direction: XmREVERSE;ribbonImage: (CgScreen default

getIcon: 'default_xm_information'foregroundColor: CgRGBColor black);

shadowType: XmSHADOWIN;shadowWidth: 5;fractionComplete: 1/4;showPercentage: true].

progressBar manageChild.shell realizeWidget.

When you run the method by evaluating <class name> new progressBarExample,you get the following:

Slider widgetThe slider widget (EwSlider) displays an analog representation of a value within aspecified range of values. The range is represented by a horizontal or vertical shaft.The currentValue resource reflects the position of a slider arm that can be movedalong the length of the shaft to display the current value.

The orientation of the slider can be specified using the orientation resource. A valueof XmVERTICAL indicates that the slider will be drawn vertically, with theminimum value at the bottom and the maximum value at the top. Similarly,

254 IBM Smalltalk: Programmer’s Reference

Page 269: IBM Smalltalk: Programmer's Reference

XmHORIZONTAL indicates that the slider will be drawn horizontally, with theminimum value at the left and the maximum value at the right. Following arehorizontal (on the left) and vertical (on the right) slider widgets:

The slider widget can display one or two scales along the shaft, which can bedisplayed above and below a horizontal slider, or to the left and right of a verticalslider. Both scales provide a minimum value, a maximum value, and a resolution.The resolution represents the size of the increments between the minimum andmaximum values. For example, using a minimum of 0, a maximum of 100, and aresolution of 10 would result in valid values of 0, 10, 20...100. Minimum value,maximum value, and resolution for each scale are set using the topOrLeftScaleMin,topOrLeftScaleMax, topOrLeftScaleResolution, bottomOrRightScaleMin,bottomOrRightScaleMax, bottomOrRightScaleResolution resources.

The methods addDetentToScale:at:label: and addTickToScale:at:label: can be used to adddetents and tick marks to a scale. Detents are small images that represent aparticular location on the slider scale. They can be clicked to position the slidervalue to the detent’s location. A tick is a mark that can be used to label a particularlocation on the shaft.

Several resources control the visual appearance of the slider. The thickness of theslider shaft can be controlled using the thickness resource. The buttonStyle resourceprovides the option of increment and decrement buttons on the shaft. If requested,these buttons can be positioned together at either end of the shaft, or separately,one at each end of the shaft. Further refinements to the shaft position within theslider widget can be made using the verticalMargin and horizontalMargin resources.

The slider value is changed by moving the slider arm with the mouse, depressingthe increment or decrement buttons, using the arrow keys, or clicking on a detent.The slider arm moves in units specified by the resolution of the scale. If two scalesare displayed on a slider, the resolution depends on the setting of the activeScaleresource.

A slider can be used as a progress bar by setting the readOnly and ribbonStripresources to true and setting the currentValue resource to show the progress.

Slider widgets provide two callbacks to alert applications to changes in the valueof the slider. The dragCallback notifies applications of the movement of the sliderarm. The valueChangedCallback notifies applications when the value has beenchanged, that is, after a drag is complete, or if the buttons or detents are used tochange the value.

The following method creates a horizontal slider with tick marks along the topscale. Add this method to a class using the pool dictionaries CwConstants andEwConstants.sliderExample

| slider shell |shell := CwTopLevelShell

createApplicationShell: 'shell'argBlock: [:w | w

Chapter 8. Extended Widgets 255

Page 270: IBM Smalltalk: Programmer's Reference

title: 'Slider Example';width: 350;height: 100].

"Create a horizontal slider. The top scale ranges from -100 to 100.The scrolling buttons appears split (one button on each end of theslider)."

slider := shellcreateSlider: 'slider'argBlock: [:w | w

orientation: XmHORIZONTAL;activeScale: XmTOPORLEFT;topOrLeftScaleMin: -100;topOrLeftScaleMax: 100;topOrLeftScaleResolution: 5;ribbonStrip: true;buttonStyle: XmBUTTONSSPLIT].

"Add tick marks to the top scale".-100 to: 100 by: 10 do: [:value |

slideraddTickToScale: XmTOPORLEFT at: value size: 5

label: value printString].

slider manageChild.shell realizeWidget.

When you run the method by evaluating <class name> new sliderExample, youget the following:

Spin button widgetA spin button (EwSpinButton) provides an interface for selecting a single valuefrom a collection of strings or a range of numbers. The widget consists of an entryfield that displays the current value and two arrow buttons that you can use toscroll forward and backward through the values. You can also scroll through thevalues using the up and down arrow keys on the keyboard. The value in the textentry field can be edited directly if the editable resource is set to true. Following isan example of a spin button widget:

The itemType resource specifies whether the spin button is to display numeric dataor a collection of strings. Possible values for this resource are as follows:

XmSBNUMERICThe spin button holds numeric data

XmSBSTRINGThe spin button holds a collection of strings

The minimum, maximum, and increment resources can be used to define the rangevalues for a numeric spin button. These resources are ignored for spin buttons thathold collections of strings.

256 IBM Smalltalk: Programmer’s Reference

Page 271: IBM Smalltalk: Programmer's Reference

EwSpinButton also provides several callbacks for application interaction. Callbackprotocol is available for gaining and losing focus (focusCallback andlosingFocusCallback), incrementing and decrementing the current value(incrementCallback and decrementCallback), and activation of the default button(activateCallback). A less specific callback is provided for any change to the currentvalue (valueChangedCallback). An additional callback is provided to indicate that thevalue in the entry field has been edited by users (modifyVerifyCallback).

The following method creates a spin button that traverses the days of the week.Add this method to a class using the pool dictionaries CwConstants andEwConstants.spinButtonExample

| spinButton shell |shell := CwTopLevelShell

createApplicationShell: 'shell'argBlock: [:w | w

title: 'SpinButton Example';width: 110;height: 30].

spinButton:= shellcreateSpinButton: 'spinButton'argBlock: [:w | w

itemType: 2; "Or XmSBSTRING instead of 2"items: #('Monday' 'Tuesday' 'Wednesday' 'Thursday'

'Friday' 'Saturday' 'Sunday');wrap: true].

spinButton manageChild.shell realizeWidget

When you run the method by evaluating <class name> new spinButtonExample,you get the following:

Split window widgetA split window (EwSplitWindow) arranges widgets within a composite. Users canresize the visible potion of the child widgets in a split window by dragging splitbars. The orientation resource controls the layout of the widgets. A value ofXmHORIZONTAL causes the child widgets to be added from left to right, in theorder they are created; a value of XmVERTICAL causes the child widgets to beadded from top to bottom in the order they are created. Split bars areautomatically inserted between child widgets.

The childProportions resource can specify the initial size of the child widgets. ThechildProportions resource contains an array of integers indicating the relativepercentage of the window to be occupied by each child. If the resource is notspecified, the child widgets are sized equally within the window.

Users can reposition split bars by first pressing and holding mouse button onewhile the cursor is over a split bar and then moving the mouse to the desiredposition. Dragging one split bar towards another causes the visible portion of theenclosed widget to be reduced until it reaches a predefined minimum size asdefined by the childMinimumSizes resource.

Chapter 8. Extended Widgets 257

Page 272: IBM Smalltalk: Programmer's Reference

You can change the visual appearance of split bars using thesplitBarForegroundColor, splitBarBackgroundColor, and splitBarThickness resources.

The following method creates a split window with three child widgets. Childwidgets are given initial proportions and minimum sizes. Add this method to aclass using the pool dictionaries CwConstants and EwConstants.splitWindowExample

| shell splitWindow |

shell := CwTopLevelShellcreateApplicationShell: 'Split Window Example'argBlock: nil.

splitWindow := EwSplitWindowcreateManagedWidget: 'splitWindow'parent: shellargBlock: [:w | w

width: 400;height: 200;orientation: XmHORIZONTAL;childProportions: #(60 15 25) ;childMinimumSizes: #(30 15 15)].

CwListcreateManagedWidget: 'list1'parent: splitWindowargBlock: [:w | w

borderWidth: 0;items: (Collection withAllSubclasses collect: [:each | each name])].

CwListcreateManagedWidget: 'list2'parent: splitWindowargBlock: [:w | w

borderWidth: 0;items: (Collection class selectors collect: [:each | each printString])].

CwListcreateManagedWidget: 'list3'parent: splitWindowargBlock: [:w | w

borderWidth: 0;items: (Collection selectors collect: [:each | each printString])].

shell realizeWidget.

When you run the method by evaluating <class name> new splitWindowExample,you get the following:

258 IBM Smalltalk: Programmer’s Reference

Page 273: IBM Smalltalk: Programmer's Reference

Tool bar widgetA tool bar (EwToolbar) provides an interface for building a horizontal or vertical barcontaining user interface tools such as push buttons and labels. You can use toolbar widgets to implement the tool bars commonly found under the menu bar inGUI applications. You can use them to provide rows or columns of tools anywhereelse in a window. Further, you can use them to implement status bars that allowapplications to display various kinds of messages.

Several resources can control the way that a tool bar displays its tools. ThenumColumns resource can specify whether the tools should be arranged in columns.If the numColumns is 0, the tool bar lays out the tools in a row. Setting numColumnsto 1 produces a vertical tool bar. The spacing resource determines how much spaceto leave between each tool.

You can specify the colors of the tool bar using the standard foregroundColor andbackgroundColor resources. In addition, you can specify the default colors of toolsusing the toolForegroundColor and toolBackgroundColor resources.

Creating toolsThe tool bar usually does not have widgets as children. Instead, it has specializedchildren called tools (EwTool). Tools are user interface elements that look likewidgets but do not actually use all of the platform resources required by a widget.Tools collaborate with the parent tool bar to display themselves and handle userevents. You add widgets as children of a tool bar by associating a widget with awidget tool.

Tools are created by sending one of the following messages to a tool bar:

createGroup:argBlock:Creates a group tool inside the tool bar. The first argument is the name forthe new tool; the second is its argument block. A group is a tool thatcontains other tools.

createLabelTool:argBlock:Creates a label tool inside the tool bar.

createProgressBarTool:argBlock:Creates a progress bar tool inside the tool bar.

createPushButtonTool:argBlock:Creates a push button tool inside the tool bar.

createRadioButtonTool:argBlock:Creates a radio button tool inside the tool bar.

createSeparatorTool:argBlock:Creates a separator tool inside the tool bar.

createSimpleGroup:argBlock:Creates a simple group inside the tool bar. A simple group is a tool thatcontains only buttons. It provides protocol for specifying collections ofimages to be displayed in the group as buttons.

createToggleButtonTool:argBlock:Creates a toggle button tool inside the tool bar.

Chapter 8. Extended Widgets 259

Page 274: IBM Smalltalk: Programmer's Reference

createWidgetTool:name:argBlock:Creates a widget and adds it as a tool to the tool bar. The first argument isthe class of widget to be created; the second is its name; the third is itsargument block.

Tools are lighter weight than widgets and minimize platform resources. However,they do not always look like a platform widget. Using widgets and widget tools onthe tool bar ensures that the tools look exactly like their widget counterparts on aparticular platform. This platform look and feel, though, comes at the expense ofusing platform resources.

Using toolsTools on a tool bar can be used much like widgets. Resources such as width, height,borderWidth, foregroundColor, and backgroundColor can control the appearance of thetool. The variableWidth resource controls whether a tool shrinks or grows as the toolbar resizes.

The enterNotifyCallback and leaveNotifyCallback can determine when the mouseenters or leaves the location on the tool bar occupied by a tool. These callbacks areuseful for implementing features such as bubble help or tool tips or for updating astatus area.

Using primitive toolsThe most commonly used tools on a tool bar are primitive tools. These are toolsthat behave much like simple widgets such as buttons and labels. Primitive toolshave an image which determines the text or graphics that they display. The imagecan be any renderable object (see “Renderables” on page 238).

Label tools (EwLabelTool) display an image and provide a shadowed inset asspecified in the shadowType resource. They provide resources for setting marginssimilar to the CwLabel widget. Progress bar tools (EwProgressBarTool) look andbehave much like EwProgressBar. The button tools (EwPushButtonTool andEwToggleButtonTool) also behave much like their CwWidget counterparts. Aseparator tool (EwSeparatorTool) can separate tools or clusters of tools. TheseparatorType resource determines the exact appearance of a separator tool.

The following method creates a tool bar with four primitive tools. Add thismethod to a class using the pool dictionaries CwConstants and EwConstants.toolBarExample

| shell toolBar |shell := CwTopLevelShell

createApplicationShell: 'Tool Bar Example'argBlock: nil.

toolBar := EwToolBarcreateManagedWidget: 'toolBar'parent: shellargBlock: [:w | w numColumns: 0; spacing: 3].

toolBarcreateLabelTool: 'label'argBlock: [:w | w image: 'Text Label'].

toolBarcreateSeparatorTool: 'label'argBlock: [:w | w

orientation: XmVERTICAL;autoSize: true;separatorType: XmSHADOWETCHEDIN].

260 IBM Smalltalk: Programmer’s Reference

Page 275: IBM Smalltalk: Programmer's Reference

toolBarcreateProgressBarTool: 'progressBar'argBlock: [:w | w fractionComplete: 1/2].

toolBarcreatePushButtonTool: 'pushButton'argBlock: [:w | w image: 'Push Me'; width: 80].

shell realizeWidget.

When you run the method by evaluating <class name> new toolBarExample, youget the following:

Using widget toolsWidgets can be added to a tool bar by creating a widget tool. A widget tool can becreated by sending the createWidgetTool:name:argBlock: message to the toolbar. Whenadding a widget tool, the application specifies the class of widget to be created.

The argument for a widget tool argBlock is the tool itself, not the widget. To setresources for the tool’s associated widget, use the widget resource to access thewidget from the tool.

The following example creates a widget tool using a combo box. It uses theargument block to set both widget and tool resources....toolBar createWidgetTool: CwComboBox name: 'combo' argBlock: [:tool |

toolborderWidth: 1;height: 36.tool widgetitems: #('Red' 'Green' 'Blue');editable: true].

...

Using groupsGroups (EwGroupTool) are useful for grouping multiple tools in order to assigncommon properties or provide specialized behavior for the group. The shadowTyperesource determines what kind of border is drawn around the tools within a groupwhen the borderWidth is not 0. The spacing resource determines what spacing thegroup uses for its tools. If the group contains toggle button tools, the radioBehaviorresource can enforce radio button style behavior within a group.

A group is created like any other tool—by sending either createGroup:argBlock: orcreateSimpleGroup:argBlock: to the toolbar. Tools are added to the group by sendingtool creation messages to the group instead of the tool bar.

The following method below creates a tool bar that contains two groups separatedby a separator tool.toolGroupExample

| shell toolBar group1 group2 |shell := CwTopLevelShell

createApplicationShell: 'Tool Group Example'argBlock: nil.

toolBar := EwToolBar

Chapter 8. Extended Widgets 261

Page 276: IBM Smalltalk: Programmer's Reference

createManagedWidget: 'toolBar'parent: shellargBlock: [:w | w numColumns: 0; spacing: 3].

group1 := toolBarcreateGroup: 'group1'argBlock: [:w | w borderWidth: 1; shadowType: XmSHADOWIN].

group1createLabelTool: 'label'argBlock: [:w | w image: 'Text Label'].

group1createProgressBarTool: 'progressBar'argBlock: [:w | w fractionComplete: 1/2].

toolBarcreateSeparatorTool: 'label'argBlock: [:w | w

orientation: XmVERTICAL;autoSize: true;separatorType: XmSHADOWETCHEDIN].

group2 := toolBarcreateGroup: 'group2'argBlock: [:w | w

borderWidth: 1;shadowType: XmSHADOWOUT;radioBehavior: true].

group2createToggleButtonTool: 'toggle1'argBlock: [:w | w image: 'Yes'; radioBehavior: true].

group2createToggleButtonTool: 'toggle2'argBlock: [:w | w image: 'No'; radioBehavior: true; set: true].

shell realizeWidget.

Evaluating <class name> new toolGroupExample displays the following:

Simple groups (EwSimpleGroupTool) provide convenience methods for creatinggroups of buttons by simply specifying a collection of images from which buttontools will be created. The buttonBorderWidth, radioBehavior, and toggleBehaviorresources specify the appearance and behavior of the buttons.

The example below creates a group like the radio group in the previous example,but it uses a simple group to create the toggle buttons....group2 := toolBar createSimpleGroup: 'group2' argBlock: [:w | w

borderWidth: 1;shadowType: XmSHADOWOUT;radioBehavior: true;toggleBehavior: true;images: #('Yes' 'No')].

...

262 IBM Smalltalk: Programmer’s Reference

Page 277: IBM Smalltalk: Programmer's Reference

Chapter 9. Drag and Drop

Pluggable drag and drop support is provided for the widgets in both CommonWidgets and Extended Widgets subsystems without requiring modifications to thewidgets. The Drag and Drop subsystem uses the portable CG and CW subsystems.No platform-specific drag and drop API is used. “Platform-integrated drag anddrop” on page 215 covers drag and drop among applications. This chapter coversdrag and drop within a Smalltalk application. Currently, drag and drop is limitedto widgets in a single Smalltalk image.

An application might wish to support drag and drop for a variety of reasons. It isnot the purpose of Drag and Drop subsystem support to prescribe the semantics ofdrag and drop; this is left to the application. Instead, generalized objects calledadapters are provided to map low-level mouse and keyboard operations to dragand drop callbacks. The primary role of the application in drag and drop is tocreate the widgets and adapters required, hook the drag and drop callbacks on theadapters, and then make the changes to the underlying objects as drag and dropoccurs.

Because the adaptors hook low-level mouse and keyboard events, any widget thatprovides these events can be adapted to drop and drag. This includes thosewidgets in the Common Widgets subsystem that fully support mouse andkeyboard events.

Drag and drop adaptersThe hierarchy of drag and drop adapter classes is the following:

Class hierarchy Responsibility

EwDragAndDropAdapter Defines common behavior for all adapters

EwSourceAdapter Defines common behavior for all drag and dropsources

EwBlockSourceAdapter Defines a drag and drop source that uses anapplication-defined block to determine the dragsource items

EwContainerListSourceAdapter Defines a source adapter for EW container- stylewidgets

EwIconAreaSourceAdapter Defines a source adapter for EwIconArea widgets

EwDrawnListSourceAdapter Defines a source adapter for EwDrawnList widgets

EwTargetAdapter Defines common behavior for all drag and droptargets

EwContainerListTargetAdapter Defines a target adapter for EW container-stylewidgets

EwIconAreaTargetAdapter Defines a target adapter for EwIconArea widgets

The Drag and Drop subsystem provides two kinds of adapters for use in drag anddrop: source adapters and target adapters. The adapters serve as a wrapper aroundwidgets, providing drag and drop callbacks that the widgets themselves do notprovide.

© Copyright IBM Corp. 1994, 2000 263

Page 278: IBM Smalltalk: Programmer's Reference

An application should create a source adapter for each widget that an applicationdesignates as a drag and drop source.

An application creates one source adapter for each source widget as follows:aSourceAdapter := EwSourceAdapter on: aWidget.

The source adapter provides the following callbacks for drag and drop sourceoperations:

dragStartCallbackA drag has been started from the source widget.

dragChangeCallbackThe target or semantics of the drag have changed.

dragCompleteCallbackThe drag and drop operation has completed.

dragCancelCallbackThe drag and drop operation was canceled or did not complete.

The application also should create a target adapter for each widget that is to be atarget for drag and drop. The target adapter is created as follows:aTargetAdapter := EwTargetAdapter on: aWidget

The target adapter provides the following callbacks for drag and drop targetoperations:

dragOverCallbackThe mouse pointer is moving over the drag target widget.

dragLeaveCallbackThe mouse pointer has left the drag target widget.

dropCallbackThe drop operation was indicated over the drag target widget.

dragCancelCallbackThe drag and drop operation was canceled or did not complete.

Sequence of eventsAn application prepares for drag and drop by creating a source adapter on thewidgets that acts as the drag source. It then hooks each source adapter’sdragStartCallback and dragCompleteCallback and, optionally, the dragChangeCallbackand dragCancelCallback.

An application also creates a target adapter on each widget that can act as a droptarget, including any source widgets that can also act as targets. An applicationthen hooks each target adapter’s dragOverCallback and dropCallback and, optionally,the dragLeaveCallback and dragCancelCallback.

In the following example, a window is created with a single EwIconList on it. Thislist is configured to do drag and drop to and from another such window. Thisportion of the example creates the widgets and adapters, hooks the necessarycallbacks, and realizes the window. The visualInfoCallback handler is also shown forcompleteness. The application containing the class should have EwDragAndDrop fora prerequisite.

264 IBM Smalltalk: Programmer’s Reference

Page 279: IBM Smalltalk: Programmer's Reference

Object subclass: #DragAndDropExampleinstanceVariableNames: 'icon'classVariableNames: "poolDictionaries: 'CwConstants EwConstants '

openOn: aCollectionOfObjects"Open the example, showing a list of objects."| shell iconList sourceAdapter targetAdapter |shell := CwTopLevelShell

createApplicationShell: 'shell'argBlock: [:w | w

title: 'Drag and Drop Example';width: 250;height: 300].

iconList := shellcreateScrolledIconList: 'iconList'argBlock: [:w | w

selectionPolicy: XmEXTENDEDSELECT;items: aCollectionOfObjects asOrderedCollection].

iconList manageChild.iconList

addCallback: XmNvisualInfoCallbackreceiver: selfselector: #visualInfo:clientData:callData:clientData: nil.

sourceAdapter := EwSourceAdapter on: iconList.sourceAdapter

addCallback: XmNdragStartCallbackreceiver: selfselector: #dragStart:clientData:callData:clientData: nil;

addCallback: XmNdragCompleteCallbackreceiver: selfselector: #dragComplete:clientData:callData:clientData: nil.

targetAdapter := EwTargetAdapter on: iconList.targetAdapter

addCallback: XmNdragOverCallbackreceiver: selfselector: #dragOver:clientData:callData:clientData: nil;

addCallback: XmNdropCallbackreceiver: selfselector: #drop:clientData:callData:clientData: nil.

"Note: The destroyCallback is not shown."icon := shell screen

getIcon: 'default_xm_information' foregroundColor: CgRGBColor black.shell realizeWidget.

visualInfo: widget clientData: clientData callData: callData"Provide the icon and label for the object contained in callData."callData

icon: icon;label: callData item.

The user initiates a drag by pressing the drag mouse button (ButtonDrag) over adrag source widget and moving the mouse a certain nominal distance. (TheButtonDrag is button 1 on Windows and UNIX platfoms, and button 2 on OS/2.Note that these buttons are settable.) The source adapter, having hooked the mouseevents on the source widget, detects that a drag is starting and activates thedragStartCallback to the application. The callData for the dragStartCallback includesthe mouse event that triggered the drag start, the items in the source widget thatare being dragged, and each item’s offset from the mouse location. It also contains

Chapter 9. Drag and Drop 265

Page 280: IBM Smalltalk: Programmer's Reference

a default image for each item to be used to represent the item during the drag. Theimages and offsets can be modified by the application to cause alternate imagesand offsets to be used. For example, an application might wish to use a multi-fileicon to represent all items being dragged rather than a single icon for each item.

The images and offsets that the adapter provides as defaults depend on the API ofthe source widget. For example, because CwList provides no API to allow thesource adapter to determine which item in the list is under the cursor when thedrag starts, the adapter simply provides the selected items as the drag items.Similarly, because the source adapter cannot determine the offsets of the selecteditems, it provides offsets that cause the drag items to be beveled up and to theright from the mouse.

The dragStartCallback callData also contains a doit flag that is set to true by default.The application can change this flag to false if it determines that dragging is notallowed for some reason. The callData also includes a default vote (see “Votingand cursors” on page 267), which is an array of operations that the source allowsfor these items. The application can change this vote to an array of operations thatit will allow, for the source items being dragged.

Finally, the dragStartCallback callData contains a slot for the source model. Theapplication can place any value in this slot, but typically it is used to hold theunderlying object that contains the items being dragged. This value will be passedalong to the drag target in the callData of the target-related callbacks.

This portion of the example shows a sample dragStartCallback handler:dragStart: sourceAdapter clientData: clientData callData: callData

"The items in the callData are being dragged. Allow onlymove operations, not copy or link."callData

doit: true;vote: (Array with: XmMOVE)

Each time the mouse moves, the system determines which widget is currentlyunder the mouse. The system keeps a registry of all target adapters and theirwidgets. This enables it to map the widget under the mouse (if any) to itscorresponding target adapter (if any).

If a widget is not under the mouse or if a target adapter does not exist for awidget, the cursor which indicates that the operation is not allowed (that is, the“No Parking” cursor) is automatically shown.

If a target adapter is found, the dragOverCallback is sent to its application. ThedragOverCallback callData contains the items being dragged, the source widget, andthe mouse event. The target adapter also determines which item in the targetwidget is under the mouse and supplies this item in the callData. This is onlypossible on widgets that provide the necessary API to determine this information.Because CW widgets provide no API to support this, the item under the cursor isalways nil for target adapters on base widgets.

If there is an API to determine which item is under the cursor (as is the case insome extended widgets), the application must determine whether the item underthe cursor is itself capable of accepting a drop. For example, a trash can or aprinter typically would be able to accept a drop.

The callData also contains an emphasis flag that an application can set to specifywhich kind of emphasis should be shown on the target widget. Again, this is not

266 IBM Smalltalk: Programmer’s Reference

Page 281: IBM Smalltalk: Programmer's Reference

possible on any of the CW widgets; only EwIconList, EwIconTree, EwFlowedIconList,EwTableList and EwTableTree use the emphasis flag. If an application has determinedthat the item under the cursor is capable of receiving the drop, it sets the emphasisflag to XmTARGETEMPHASIS. If it determines that the item is not capable ofreceiving the drop, then it can set the emphasis flag to eitherXmINSERTIONEMPHASIS or XmNOEMPHASIS (default).XmINSERTIONEMPHASIS indicates that if the drag items are dropped, they willbe inserted into the target widget at the index determined by the mouse position.

The dragOverCallback callData also contains the source model and a field for thetarget model. The source model is whatever value was last placed in thesourceModel slot by the source in either the dragStartCallback or dragChangeCallbackcallData. The application can set the target model to be any object, but this istypically the object that would contain the drag items if they were to be droppedon the target.

The dragOverCallback callData also contains a vote. The application can set this tobe an array of operations that it will allow given the current target widget, targetitem (if any), and the items being dragged.

Finally, the dragOverCallback callData contains a repeat flag. This Boolean variabledetermines whether another dragOverCallback should be activated even if the itemunder the cursor does not change. By default, this value is false for performancereasons. If the application needs the dragOverCallback to be triggered continuously,then the repeat field must be set to true each time the callback is triggered. Forexample, if an application uses a drawing area to present an image, the applicationmight need the dragOverCallback to be triggered repeatedly so that it can detectwhen the items are being dragged over the various parts of the image.

This portion of the example shows a sample dragOverCallback handler:dragOver: targetAdapter clientData: clientData callData: calldata

"The items in the calldata are being dragged over the receiver.These items might be from another source. Allow only moveoperations between different lists, not copy or link, and notwithin the same list."

calldata sourceWidget == targetAdapter widgetifTrue: [calldata vote: #()]ifFalse: [

calldatavote: (Array with: XmMOVE);emphasis: XmINSERTIONEMPHASIS]

Tip: In some cases, an application might need to draw while a drag is in progress(for example, to change the icon of an item under the cursor). To avoidleaving visual “debris” on the screen, the application must do any drawingby sending the message drawDuringDrag: to the adapter. This message takes aBlock as its argument. All drawing that takes place in the block will not leavedebris on the screen.

Voting and cursorsAs items are being dragged, users can affect the drag operation by pressing theshift key, the control key, or both keys. Each time a dragOverCallback is activated, oreach time the keyboard status changes, the source, target, and keyboard votes arerecalculated, and a net operation is determined. This operation, in turn, determineswhat the cursor should be.

Chapter 9. Drag and Drop 267

Page 282: IBM Smalltalk: Programmer's Reference

Because dragging images causes the cursor to blink, an alternative to cursors,called cursor images, is provided. Like cursors, each cursor image corresponds toan operation. The difference is that if a cursor image is defined for an operation, itis drawn over all the drag images and will not blink as the mouse is moved. Bydefault, the system turns off the cursor during drag and drop and uses a uniquecursor image for each operation.

The cursor images and keyboard mappings for each operation are configurable ona global basis (see “System configuration” on page 269).

Source vote and image changesSome applications might require that the source be able to change its vote, its dragimages, or its drag offsets based on the target, the operation, or both. For example,the source might want to allow certain operations only if the item is being draggedover the source. In this case, the source would need an opportunity to change itsvote whenever the target changed.

To support this requirement, the dragChangeCallback on the source adapter isactivated whenever the target or the operation changes. The callData includes theitems being dragged, the target widget, target item, target model, and the currentoperation. It also includes the drag images and offsets and the most recent sourcevote and source model. The application can change these values to implementbehaviors like those outlined in the example above.

Leaving a targetIn some cases, an application might need to be notified when items are draggedaway from a target. For example, if an application had hooked the dragOverCallbackto show target emphasis, it would need to be notified when the drag had left thattarget widget so that it could erase the emphasis.

To support this, the dragLeaveCallback on the target adapter is activated wheneverthe items are dragged away from the target of the last dragOverCallback. ThecallData includes only the source widget, the source model, and the source items.None of these fields can be changed; this callback is for notification only.

DroppingWhen a user releases the mouse button, a drop occurs on the target widget. Boththe target and the source are notified. The target adapter first activates thedropCallback. The callData includes the source widget, the source model, the sourceitems, the operation, and the mouse event. It also includes an offset for each sourceitem relative to the mouse location. If, in response to the last dragOverCallback, theapplication set the emphasis to XmTARGETEMPHASIS, the callData for thedropCallback also contains the target item. If the emphasis was set toXmINSERTIONEMPHASIS, the callData contains the insertion index. Finally, thecallData contains a doit flag, which an application can set to false if it is unable toperform the drop. In this case, the source adapter will activate itsdragCancelCallback. Otherwise, it is the application’s responsibility to perform theappropriate operation on the target widget and the underlying objects.

This portion of the example shows a sample dropCallback handler:drop: targetAdapter clientData: clientData callData: calldata

"The items in the callData are being dropped onto thereceiver. These items must be from another source."| toAdd |

268 IBM Smalltalk: Programmer’s Reference

Page 283: IBM Smalltalk: Programmer's Reference

toAdd := calldata sourceItems reject: [:anObject |targetAdapter widget items includes: anObject].

targetAdapter widget addItems: toAdd position: calldata insertionIndex

After the target has triggered the dropCallback, the source adapter activates itsdragCompleteCallback. The callData includes the source items, the target widget, thetarget model, the target item (if any), and the operation. It is the application’sresponsibility to perform the appropriate operation on the source widget and theunderlying objects. For example, if the operation was XmMOVE, the applicationshould remove the items from the source widget.

This portion of the example shows a sample dragCompleteCallback handler:dragComplete: sourceAdapter clientData: clientData callData: calldata

"The items in the calldata have been dropped somewhere else."calldata vote == XmMOVE ifTrue: [

sourceAdapter widget deleteItems: calldata sourceItems]

Canceling a dragThe user can cancel a drag at any time by pressing the key represented byXkCancel. In this case, the source adapter and the target adapter (if any) activatetheir dragCancelCallback. The callData for this callback depends on whether theadapter is a source or a target adapter. For source adapters, the callData includesthe same information as the callData for the dragCompleteCallback. For targetadapters, the callData includes the same information as the callData for thedropCallback.

The source adapter also activates the dragCancelCallback when items are droppedoutside any target widgets. The dragCancelCallback is also triggered when the itemsare dropped onto a target that is unwilling to accept them; that is, when no validoperation is in effect or when the target widget’s application sets the doit flag tofalse in the dropCallback’s callData.

System configurationA central drag and drop manager (EwDragAndDropManager) stores system-widedrag and drop parameters. It provides API to set and query: the list of possibleoperations, the cursors that correspond to each operation, and the mappings fromkeyboard combinations to operations.

The mouse button that should be used to initiate a drag operation is specified inthe button resource. An application can specify a particular button using Button1,Button2, or Button3, or it can use the value ButtonDrag to indicate that the defaultdrag button for a particular platform should be used.

The set of operations and their relative priorities are configurable. By default, theoperations are XmMOVE, XmCOPY, and XmLINK (a “Link” is a reference to thesame object). When the source, target, and keyboard votes are tallied, the highestpriority operation of the intersection of the three votes is used as the operation.The priority of the votes is determined by the order the source answers itsallowable operations in the dragStartCallback. The highest priority vote is the firstvote the source gives. If the intersection is empty, then the cursor which indicatesthat an operation is not allowed is shown.

The mapping of the shift and control key combinations to drag operations can becustomized, too. The default mappings are:

None All operations are allowable.

Chapter 9. Drag and Drop 269

Page 284: IBM Smalltalk: Programmer's Reference

Shift XmMOVE

ControlXmCOPY

Shift + ControlXmLINK

The cursor images to be shown for an operation are also configurable. The defaultmappings are:

Note: The button can be set to start drag.

Simple drag and dropFor most applications, the default settings are acceptable. This section describes theminimum requirements for an application to enable drag and drop.

At a minimum, the application must create the source and target adapters on theappropriate widgets. On the source adapter it does not need to hook thedragStartCallback unless it intends to change the vote, images, or offsets to valuesother than the defaults or unless it wants to deny drag and drop in certain casesby setting the doit flag to false. An application must hook the dragCompleteCallbackto perform the operation. The dragChangeCallback does not need to be hooked, nordoes the dragCancelCallback.

On the target adapters, the application only needs to hook the dragOverCallback if itneeds to check the kind of items being dragged to ensure that the target widgetcan receive them or if it does not want the default target vote. It should hook thedropCallback to perform the operation. It does not need to hook thedragLeaveCallback or dragCancelCallback.

Tip: Most of the extended widgets are useful without drag and drop, but forEwIconArea widgets, drag and drop is needed just to move the items aroundwithin the widget. The EwIconArea widget provides an API to supportinternal-only drag and drop without having to create a source and targetadapter, and without having to hook any callbacks. The methodconfigureForDefaultDragAndDrop automatically does this. It limits drag anddrop to only allow the user to move items within the container. If theapplication requires any additional capabilities, it should not use this simpleAPI, but should create its own adapters and hook the callback accordingly.

Widget limitationsTechnically, any widget is capable of drag and drop, although some types ofwidgets are better suited than others. Drag and drop works best on container styleextended widgets such as EwIconArea, EwIconList, EwFlowedIconList, EwIconTree,EwTableList, and EwTableTree. On these widgets, the sourceItems, targetItem, and

270 IBM Smalltalk: Programmer’s Reference

Page 285: IBM Smalltalk: Programmer's Reference

itemUnderCursor fields in the various callData always contain actual items from thesource and target container. Furthermore, these container widgets assume that ifdragging starts on one of the selected items, then all of the selected items aredragged. They also assume that if dragging starts on a non-selected item, then onlythat item is dragged.

Drag and drop for the other list-oriented widgets such as CwList and CwComboBoxcarries some limitations. First, the sourceItems, targetItem, and itemUnderCursor fieldsin the various callData only ever contain strings when the callbacks are triggered.However, the application can override these values in the callback handlers. Also,because these widgets do not provide any way to determine which items are underthe cursor, they always assume that, regardless of where a drag actually starts, allselected items are dragged. Drag and drop on these widgets is further limited bythe fact that they cannot show insertion or target emphasis. This implies that it isnot possible to inform users where items will be inserted if they are dropped onone of these widgets.

Drag and drop to and from non-list-oriented widgets is more severely limited.Because there are no commonly accepted semantics for drag and drop on labels,buttons, forms, or other non-list-oriented widgets, the application must definewhat is meant, for example, by dragging from a CwLabel to a CwToggleButton. Also,the sourceItems, targetItem, and itemUnderCursor fields in the various callData arealways left nil.

Chapter 9. Drag and Drop 271

Page 286: IBM Smalltalk: Programmer's Reference

272 IBM Smalltalk: Programmer’s Reference

Page 287: IBM Smalltalk: Programmer's Reference

Chapter 10. Common Printing

The Common Printing (CP) subsystem provides an event-driven printing modelwith support for job and page control, job setup, and printer font selection. Textand graphics, including bitmapped images, can be printed using the CommonGraphics API.

Common Printing classesThis section describes printing-related terminology and the classes defined byCommon Printing.

A print device, referred to in this text as a printer, is any device capable ofproducing printed output. An instance of the CgPrinterScreen class represents asingle printer.

A print job is a document stored within the computer that contains zero or morepages of output. Print jobs have platform- and device-specific attributes associatedwith them such as print resolution, form selection, special printer effects such asorientation and duplex printing, and so on. Common Printing encapsulates theseattributes in the CgPrintJobAttributes class.

A CwPrinterShell provides job and page control methods, and processes printingevents. The window associated with a CwPrinterShell represents the printable areaon the physical page. Applications use Common Graphics operations to draw onthis window.

Users can choose from available printers using a CwPrinterPrompter. Printerprompters also allow users to configure print job attributes.

A print server is an object that manages one or more printers and commonresources such as printer fonts. In IBM Smalltalk, a connection to a print server isrepresented by a CgDisplay. Each CgDisplay contains at least one CgPrinterScreenobject and zero or more CgScreen objects.

The following diagram shows how the classes are related from the application’spoint of view.

© Copyright IBM Corp. 1994, 2000 273

Page 288: IBM Smalltalk: Programmer's Reference

Printing process overviewThis overview describes printer selection, print job attribute configuration, andprint job configuration.

Selecting a printerThere are several different approaches to selecting a printer. The recommendedapproach is to allow the user to choose a printer display using a printer prompter.For more information on CwPrinterPrompter, see “Using the printer prompter” onpage 275.

If a user selection is not required, the application can choose to use the defaultprinter. The default printer can be obtained by sending default to CgPrinterScreenclass. It can be changed via printer configuration tools provided by the operatingsystem, for example, the Print Manager in Windows or a Printer object in OS/2. Ifthere is no default printer, default answers nil.

A printer can also be selected by enumerating the printer screens available on agiven display using the printerScreens method. For instance, printer screens on thedefault printer display can be obtained using CgDisplay defaultPrinterDisplayprinterScreens. Printers on other displays can be listed by first opening a connectionto the desired display, using CwAppContext openDisplay:, and then sending

274 IBM Smalltalk: Programmer’s Reference

Page 289: IBM Smalltalk: Programmer's Reference

printerScreens to this printer display. Printer displays opened in this manner shouldalways be closed when they are no longer needed by issuing close. The defaultprinter display should not be closed.

Display names used for opening a printer display with openDisplay: can beobtained from CgDisplay allPrinterDisplayNames. Do not cache the results ofallPrinterDisplayNames because printers can be added or removed from theoperating system at any time. To obtain a human-readable name of a printer, useCgPrinterScreen name, rather than CgDisplay displayString

Configuring print job attributesPrint job attributes, such as print resolution, form selection, and special printereffects, are both printer- and platform-specific. A CwPrinterPrompter allows users toconfigure these attributes. The CwPrinterPrompter contains a CgPrintJobAttributesobject that describes the printer-specific setup of the printer that the user selected.For more information on CgPrintJobAttributes, see “Print job attributes” on page276.

Creating a print jobTo produce documents, the application creates a CwPrinterShell on the desiredprinter screen and display. The shell provides methods to start and end print jobsand to identify page boundaries. Text and graphics are drawn on the windowassociated with the printer shell.

The CwPrinterShell notifies the application of printing events using the widgetcallback mechanism. The callback model for printing is described in “Addingcallbacks” on page 277. See the ″Common Widgets″ chapter for more informationon callbacks.

Using the printer prompterThe CwPrinterPrompter allows users to select a printer. The user can configure jobattributes for a printer by using a platform- and printer-specific setup dialog. Printjob attributes for the selected printer can be retrieved by sending jobAttributes tothe CwPrinterPrompter after a printer has been selected. A CwPrinterPrompter fromthe OS/2 platform is shown in the following diagram.

A printer prompter returns the display name of the selected printer, or nil if noprinter is selected. The prompter also returns nil if no printers are available.

The display name returned by the prompter is used to open a connection to thedesired printer display by sending openDisplay:; to CwAppContext default. A printershell can then be created by sending appCreateShell:applicationClass:display:argBlock:;to the CwPrinterShell class.

Chapter 10. Common Printing 275

Page 290: IBM Smalltalk: Programmer's Reference

When a printer prompter returns successfully (the value is not nil), its jobAttributesmethod answers that with a CgPrintJobAttributes compatible with the selectedprinter. The job attributes should be used when creating a printer shell byspecifying the jobAttributes: resource message in the create argBlock for the shell.

The following sample code shows typical printer prompter use, including openingthe selected display, retrieving selected job attributes, and creating a printer shell.| prompter displayName display jobAttributes printerShell |prompter := CwPrinterPrompter new.

(displayName := prompter prompt) isNilifTrue: [|System message: 'A printer was not selected.'].

(display := CwAppContext default openDisplay: displayName) isNilifTrue: [|self error: 'Cannot connect to selected printer.'].

jobAttributes := prompter jobAttributes.

printerShell := CwPrinterShellappCreateShell: 'print job'applicationClass: nildisplay: displayargBlock: [ :w | w jobAttributes: jobAttributes].

Print job attributesMost printers allow configuration of features such as print resolution, formselection, simplex or duplex printing, and so on. Common Printing encapsulatesthese printing attributes in the CgPrintJobAttributes class.

Print job attributes can be configured by the user in two ways: default attributesvia printer configuration tools provided by the operating system, and job-specificattributes via the platform- and printer-specific setup dialog of a printer prompter.The application can obtain print job attributes by sending defaultJobAttributes to aCgPrinterScreen or by sending jobAttributes to a CwPrinterPrompter after the user hasselected a printer. Attributes can also be saved between sessions.CgPrintJobAttributes can be passed to a CwPrinterShell in the create argBlock for theshell using the jobAttributes:; resource setting method.

Print job attributes are platform- and printer-specific, so a CgPrintJobAttributesobject that works on one printer will not necessarily work on another printer, andwill not work on a different platform. CgPrintJobAttributes objects know theirplatformName, deviceName, and driverVersion, and they can be asked whether theyare compatible with a certain printer screen using isCompatibleWith:.

Using a printer shellAs mentioned above, a CwPrinterShell is used to create print jobs. The windowassociated with a CwPrinterShell corresponds to the physical page on the printer,and can be drawn on using standard Common Graphics commands. The shellitself handles job and page control.

CwPrinterShell has the same application program interface (API) as aCwTopLevelShell widget, with the following exceptions:v Child widgets are not supported. Graphics can be drawn on the window

associated with the printer shell, but child widgets cannot be added to the shell.v Video-specific features such as shell iconification are not supported.

276 IBM Smalltalk: Programmer’s Reference

Page 291: IBM Smalltalk: Programmer's Reference

v Additional printer-specific methods such as resolution are included in theCwPrinterShell API.

Creating a shellThere are two different methods of creating a printer shell.v CwPrinterShell>>createApplicationShell:argBlock: creates a printer shell on the

default printer display. Resource-setting messages can optionally be sent to theshell in the create:argBlock:.

v CwPrinterShell>>appCreateShell:applicationClass:display:argBlock: allows anapplication to specify the printer display (the print server) the shell is to beassociated with. This method is typically used when a printer display has beenselected using a printer prompter.

The screen: method can be used in the shell’s create:argBlock: to specify theCgPrinterScreen (the print device) the shell is to be associated with. The screenmust be one of the printer screens of the shell’s display. If a screen is not specified,the shell simply uses the default printer screen of the display. Because there israrely more than one CgPrinterScreen associated with a printer display, the defaultprinter screen is typically used.

Print job attributes for the shell can also be specified in the create:argBlock: via thejobAttributes: method. All print jobs produced by the shell take on the given jobattributes. If job attributes are not specified at shell creation time, the shell obtainsdefault job attributes from its printer screen. Job attributes are not checked forcompatibility with the selected printer, but the application can useisCompatibleWith:; to test compatibility if desired.

Both printer shell creation methods answer the newly created shell widget, or nil ifthe widget cannot be created. An error message is displayed if a printer display orprinter screen is requested that is not valid.

Adding callbacksCommon Printing uses the callback mechanism to inform applications of eventsrelated to the printing process. Callbacks are added to a shell using theaddCallback:receiver:selector:clientData: method.

CwPrinterShell uses the following callbacks:

mapCallbackThe shell has been mapped and is ready for print job production.

exposeCallbackThe shell is ready to receive data for the current printer page.

resizeCallbackThe shell’s dimensions have been modified.

destroyCallbackThe shell is about to be destroyed.

Chapter 10. Common Printing 277

Page 292: IBM Smalltalk: Programmer's Reference

The following diagram shows the proper sequencing of printer shell job commandsand callbacks.

Starting a jobAfter creation, a printer shell widget must be realized by invoking realizeWidget.The shell responds with a map callback to indicate readiness for job controlmessages. At this point the shell can be used to start print jobs.

Because printing is implemented as a set of user-interface operations on a printerdisplay, the application must run the user-interface event loop to allow callbacks tobe sent to the printer shell. The application can either fall back to the event loopafter realizing the shell, or it can run a new event loop in place until printing iscomplete. Printing operations cannot be performed by processes other than theuser-interface process. For more information see “The user interface processmodel” on page 225.

After reception of a map callback the application sends startJob to the shell, whichbegins a new document with the title specified by the shell’s title resource. Thetitle is used to identify the document within the operating system, and typicallyincludes the name of the application producing the document. Title changes onlytake effect prior to the beginning of a new print job.

Producing a pageThe actual contents of a print job consist of graphics and text created with theCommon Graphics API. See “Printing with Common Graphics” on page 279 formore information on printing graphics.

An application uses the following steps to produce pages of graphics and text:1. Send a startPage message.2. Upon reception of an expose callback, draw graphics on the window associated

with the shell (window). The number of the page currently being drawn isspecified in the callback data of the expose callback.

3. Send an endPage message.

278 IBM Smalltalk: Programmer’s Reference

Page 293: IBM Smalltalk: Programmer's Reference

4. Repeat steps 1 to 3 as necessary.

Ending a jobThe endJob method ends a print job and submits the job for printing. A job can alsobe canceled at any point by calling cancelJob. In this case, an attempt is made toerase the entire contents of the print job and cancel printing of the job. It is notnecessary to issue endJob after canceling a print job.

Once a print job is complete or has been canceled, an application can beginanother document by issuing startJob and beginning the printing process again.When all print jobs are complete, destroyWidget should be used to destroy theprinter shell and release its associated resources. Finally, the printer display shouldbe closed if it is no longer needed.

CwPrinterShell resources and convenience methodsThe following CwPrinterShell resource methods provide useful information relatedto printing:

screen The printer screen on which the printer shell resides

height The read-only height of the printable area of a page, in pixels

width The read-only width of the printable area of a page, in pixels

x The read-only x-coordinate of the upper-left corner of the widget, inrelation to the printable area of a page

y The read-only y-coordinate of the upper-left corner of the widget, inrelation to the printable area of a page

title The document title, used by startJob to identify the current job

jobAttributesThe job attributes for the current print job

resolutionThe read-only horizontal @ vertical resolution of the shell, in dots per inch(DPI)

pageNumberThe current logical page number

The following CwPrinterShell convenience methods are also useful:

displayThe CgDisplay on which the printer shell created.

windowThe CgWindow associated with the printer shell.

Tip: If necessary, device-specific data can be sent directly to a printer, one byte at atime using the CwPrinterShell method sendRawPrinterData:.

Printing with Common GraphicsThe drawing process for printing is basically the same as that for drawing on avideo display: Obtain a graphics context, and draw graphics and text on adrawable using Common Graphics methods. In the case of a printer shell, thedrawable is the printer shell’s window.

Chapter 10. Common Printing 279

Page 294: IBM Smalltalk: Programmer's Reference

The major distinction between printed graphics and screen graphics is deviceresolution. Printers generally have much higher print resolution than videodisplays, so a pixel on a 300 DPI laser printer is much smaller than a pixel on a 72DPI video display. Correspondingly, an image drawn on a video display appearsmuch smaller when printed. Because Common Graphics methods are pixel-based,applications that require printing capability must adjust to the resolution of theprinting device. Scaling can be done by querying the printer shell resolution andmultiplying drawing coordinates by an appropriate factor.

An application requires a graphics context to draw graphics on a printer. Agraphics context created for a printer is similar to one created for a video display,with the limitation that a printer graphics context cannot generally be used for adifferent printer, or even a different print job on the same printer. This is becauseprinter graphics contexts are printer- and print job-specific. For the same reason, aprinter graphics context cannot be used for video display play graphics. Also,printer display graphics contexts are reset at the start of each page by theoperating system. For this reason, the application must reset any desired graphicscontext fields in the expose callback before drawing.

Applications should send createGC:values: to a CwPrinterShell window to obtain agraphics context for a printer. It is possible to create more than one graphicscontext for a print job. default does not return a graphics context suitable for use ona printer.

The font model for printing is the same as that for screen graphics. However,printer fonts generally work only on printers and not on video displays. Inaddition, video display fonts do not necessarily work on printers, although inpractice many do. The application can determine which fonts are supported byboth the video and printer displays by comparing the font information returned bylistFonts:maxnames: for each display.

Common Printing does not support cursors, because cursors are screen-specificobjects. Printed image support (including that for CgIcon) is provided viaCgDeviceIndependentImage. Common Printing does not support CgPixmap, becausepixmaps are device-specific. Applications must take printer resolution into accountwhen scaling images for the printer.

A complete exampleThe following example prints two pages of text, diagonal lines, and filled circles.The printer where the pages are being sent is prompted for, and if there are noprinters available or if no printer is chosen, no printing is done.Object subclass: PrintingExample

instanceVariableNames: 'done gc fontStruct'classVariableNames: ''poolDictionaries: 'CwConstants CgConstants'

print"Print two similar pages of text and graphics.

NOTE: This call must run in the UI process because itruns its own event loop until printing is completed."

"To test, execute the following:PrintingExample new print"| prompter displayName display jobAttributes printerShell |

done := false.

280 IBM Smalltalk: Programmer’s Reference

Page 295: IBM Smalltalk: Programmer's Reference

CgDisplay allPrinterDisplayNames isEmptyifTrue: [|System errorMessage: 'There are no available printers.'].

prompter := CwPrinterPrompter new.(displayName := prompter prompt) isNil

ifTrue: [|nil].

jobAttributes := prompter jobAttributes.display := CwAppContext default

openDisplay: displayName.display isNil

ifTrue: [|nil].

printerShell := CwPrinterShellappCreateShell: self class nameapplicationClass: nildisplay: displayargBlock: [:w | w jobAttributes: jobAttributes].

printerShelladdCallback: XmNmapCallbackreceiver: selfselector: #printerShellMap:clientData:callData:clientData: nil;

addCallback: XmNexposeCallbackreceiver: selfselector: #printerShellExpose:clientData:callData:clientData: nil;

addCallback: XmNdestroyCallbackreceiver: selfselector: #printerShellDestroy:clientData:callData:clientData: nil.

printerShell realizeWidget.

"Printing starts on return to the event loop - so force event loop here."[done] whileFalse: [CwAppContext default readAndDispatch].

printerShellMap: printerShell clientData: clientData callData: callData"Create a graphics context, load a font, begin the print job,and start the first page."

| fontNames display |gc isNil

ifTrue: ["Create a graphics context."gc := printerShell windowcreateGC: Nonevalues: nil.

"Load a font (the first courier font) for use in drawing strings."display := printerShell display.fontNames := display

listFonts: '*courier*'maxnames: 1.

fontStruct := fontNames isEmptyifTrue: [display defaultFontStruct]ifFalse: [display loadQueryFont: fontNames first].

].printerShell

startJob;startPage.

printerShellDestroy: printerShell clientData: aStream callData: callData"Free resources allocated for printing."

done := true.gc freeGC.fontStruct = printerShell display defaultFontStruct

ifFalse: [fontStruct freeFont].printerShell display close.

Chapter 10. Common Printing 281

Page 296: IBM Smalltalk: Programmer's Reference

printerShellExpose: printerShell clientData: clientData callData: callData"Process the current page. If all pages are processed, end the print joband destroy the printer shell."

| pageNum |gc setFont: fontStruct fid.pageNum := callData pageNumber.self printPage: pageNum on: printerShell.printerShell endPage.

"This example only prints two pages."pageNum < 2

ifTrue: [printerShell startPage.

]ifFalse: [

printerShellendJob;destroyWidget.

].

printPage: pageNum on: printerShell"Print some text and graphics on a printerShell."

| halfWidth halfHeight fontHeight lineNumber |

halfWidth := printerShell extent x // 2.halfHeight := printerShell extent y // 2.lineNumber := 1.fontHeight := fontStruct height.

0 to: halfHeight by: 100 do: [:y |printerShell window

drawLine: gcx1: 0y1: 0x2: halfWidthy2: y

].printerShell y + fontHeight to: halfHeight + fontHeight

by: fontHeight do: [:y |printerShell window

drawString: gcx: 40y: ystring: 'Line: ', lineNumber printString, ', page: ' ,

pageNum printString.lineNumber := lineNumber + 1.

].

printerShell windowfillArc: gcx: halfWidthy: halfHeightwidth: halfWidth // 2height: halfHeight // 2angle1: 0 * 64angle2: 360 * 64.

Setting up printers and queues on UNIX platformsTo direct the output of the Common Printing subsystem to a printer, you must firstconfigure the system to recognize any available printers and queues. Printerdefinitions are installed through the CwPrinterPrompter. Install printer definitions asfollows:1. Open the printer prompter by executing the following code in a workspace:

CwPrinterPrompter new prompt

282 IBM Smalltalk: Programmer’s Reference

Page 297: IBM Smalltalk: Programmer's Reference

2. When the prompter opens, select Install. A Printer Installation dialog willappear, listing any configured printers. Tihs list should contain one installedprinter, which may be used as an example. After installing any additionalprinters, this printer can be deleted.

3. To install a new printer, select Add Printer. A dialog appears, listing theavailable printer types and currently configured ports. A connection to a printeris specified by a combination of a PostScript printer definition (PPD) and a portdefinition.

4. Select Define New Port to create a new port definition. A dialog appears,allowing you to edit port definitions. Type the port definition in the Edit Portinput area. Port definitions have the following format:port=print_command

The port is any string which users will recognize as referring to a particularprinter. The print_command is the command used for sending output to theprinter port (for example, lp -d or lpr -P. For example, suppose you have twoprinters, ADMIN and LAB. Your definitions might look like the following:ADMIN=rsh bandit "lp -d ps"LAB=lpr -Pgonzo

In this example, ADMIN refers to a printer connected to the system BANDIT,so the print command is a remote shell command executed on BANDIT.ADMIN is a PostScript printer attached to a queue named PS, so the commandlp -d ps is executed on BANDIT to print to ADMIN. LAB, however, prints to aprinter on the local system, so the print command executed locally to print toLAB is lpr -Pgonzo, where GONZO specifies the defined PostScript printerqueue name.

Note: Some systems use lp -dqueuename to send output to the printer; othersuse lpr -Pqueuename. You should specify whatever command isappropriate to generate printed output on your system.

5. Select Add/Replace to add the new port in the list of current port definitions.6. Repeat for each printer you want to send output to.

Note: To modify an existing port using the Printer Setup dialog, select the portyou want to modify and edit the port information in the Edit Port inputarea, then select Add/Replace.

7. In the Printer Devices field, select the description that matches the printer youare installing. If no description matches your printer, contact your printervendor for a PPD file.

8. Select the desired port in the Current Port Definitions list box and select AddSelected. The new printer is now included in the list of currently installedprinters.

To close any dialog without accepting the changes, select Cancel. To close a dialogand accept the changes, select Dismiss.

Configuring printer setup optionsThe Xprinter Printer Setup widget does the following:v Reads default configuration information from file $HOME/.Xpdefaults, which is

your local setup information file. If this file is absent, it reads defaultconfiguration information from Xpdefaults in the directory you specify as theprintPath in the abt.ini file.

v Presents this information to you and allows you to modify these defaults.

Chapter 10. Common Printing 283

Page 298: IBM Smalltalk: Programmer's Reference

The orientation, scale, and number of copies to be printed can be specified directlyusing this widget. Additionally, the action area of the Printer Setup Widgetcontains the following six buttons:

Button Description

Apply Provides changed configuration information to the application withoutupdating the default printer

Save Saves the current configuration information as your default printer

Reset Reloads the default configuration from $HOME/.Xpdefaults

Cancel Closes the dialog and aborts all configuration changes

Options Displays the options dialog box that allows you to select a differentprinter setup

Install Displays the installation dialog box that allows you to add or removeprinter devices and printer ports

Selecting the Install button opens a dialog allowing you to add and remove printerdefinitions.

To select a different printer or to change printer-specific properties, select Options.If the Options button is disabled, ensure that ’Printer Specific’ is selected in theoutputTo: field.

Printer name, resolution, page size, and paper tray can be changed using thisdialog. Selecting the arrow button t the right of the field displays a list of validvalues from which you can choose. The values presented differ based upon theparticular printer selected. To save the configuration as the default, after you havechanged the printer option, select Save. Select Apply when finished to close theprinter prompter.

Printer configuration informationBy default, printer configuration information is stored in the file Xpdefaults, in theprinter subdirectory (that is, opt/IBMvast/printing). The information in this file isused by the printer prompter to allow selection and modification of currentlydefined printers. This file can be treated as common and shared by multiple users;it is important, however, to note the following:

The Xpdefaults file is read-only. When a user modifies the printer information inthis file using the printer prompter, the resulting information is stored in the user’shome directory in the file .Xpdefaults. If a user’s home directory contains an.Xpdefaults file, this file will always be used in preference to the commonXpdefaults file. Each user, therefore, can have a different printer configuration. Asa result, it is necessary to rename the $HOME/.Xpdefaults file to Xpdefaults andmove the file to the printing directory for all users to have access to the newlyinstalled printers.

284 IBM Smalltalk: Programmer’s Reference

Page 299: IBM Smalltalk: Programmer's Reference

Chapter 11. IBM Smalltalk Virtual Machine API

The IBM Smalltalk Virtual Machine Application Program Interface (API) is a Clanguage interface that binds to the IBM Smalltalk virtual machine and enablesyou to write C code that interfaces with Smalltalk code.

This chapter describes the IBM Smalltalk Virtual Machine API and includes thefollowing:v Calling functions in other languages from IBM Smalltalkv Calling IBM Smalltalk from other languagesv Writing user primitives

Who should read this chapterThis chapter is for developers needing to interface to other languages or writecustom primitive operations.

Some reasons to interface to other languages are:v Low-level operating system interface requirementsv Performance-critical code or enhancementsv Preserving existing business-critical code

You can use either of two mechanisms for interfacing to C code:v PlatformFunctionv User primitives

If you need to interface to existing code written in C or other languages (operatingsystem code, for example), you would use PlatformFunction, because it does notrequire you to write any C code. You can interface to C code usingPlatformFunction completely from Smalltalk. PlatformFunction enables you to callarbitrary code that knows nothing about objects.

User primitives enable you to write performance-critical code that isSmalltalk-specific. This code is aware of Smalltalk objects. For this reason, theseprimitives can be very fast, and you can use them to improve performance.

This chapter assumes a familiarity with the C programming language and with theC compiler for the IBM Smalltalk platform.

ConventionsThe conventions used in this chapter are as follows:v All publicly available IBM Smalltalk functions and macros are prefixed with Es.

This prevents name conflicts with user-developed code that is linked with anIBM Smalltalk virtual machine.

v The terms byte, word, and long refer to 8-, 16-, and 32-bit quantities,respectively.

v C language code in text is in the example font, while Smalltalk code is in italics.v All function descriptions are in C and have the following form:

returnType functionName(type arg1, type arg2, ...)

© Copyright IBM Corp. 1994, 2000 285

Page 300: IBM Smalltalk: Programmer's Reference

The text that follows the function description is an explanation of thefunction, its parameters, and return values. Following the explanation appearparagraphs like this:Error cases: This paragraph describes error conditions, if any, and anyassumptions made about parameters.Smalltalk equivalent: This shows the equivalent operation in Smalltalk, ifany.Side effects: This describes any side effects the function might have.

This format is used to describe everything, even though some of the functions areactually implemented as macros. You can see examples of this presentation formatin “Functions available in user primitives” on page 320.

IBM Smalltalk C programming modelThe file esuser.h must be included by any C file that interfaces to IBM Smalltalk.This file resides in the include directory provided with the release. The includedirectory should be included in the C compiler search path by using the -I option.

Defined typesesuser.h defines the following C data types:U_8, U_16, U_32

Unsigned 8-, 16-, and 32-bit integersI_8, I_16, I_32

Signed 8-, 16-, and 32-bit integersBOOLEAN

Either TRUE or FALSE (also defined)EsObject

Pointer to an IBM Smalltalk objectEsVMContext

Pointer to a low-level process information blockEsBehavior

Pointer to a kind of Behavior (for example, Class or Metaclass)EsGlobalInfo

Information global to all processesEsPrimitiveTable

An IBM Smalltalk user primitive table

Object typesThe five types of IBM Smalltalk objects include:v Immediate objectsv Pointer objectsv Byte objectsv Word objectsv Long objects

In addition, all of these object types except “immediate” can be marked as one ofthe following:v Read-onlyv Fixed

286 IBM Smalltalk: Programmer’s Reference

Page 301: IBM Smalltalk: Programmer's Reference

Immediate objectsAn immediate object’s value is represented directly in the object pointer, with nodata associated. In IBM Smalltalk, true, false, nil, Character, and SmallInteger areimmediate. In C, true, false, and nil can be referenced as EsTrue, EsFalse, andEsNil, respectively.

IBM Smalltalk SmallIntegers range from -1073741824 to +1073741823.

Character values range from 0 to 65535.

Pointer objectsA pointer object’s instance variables or indexed slots contain references to otherobjects. An example of this type of object is Array.

Byte, word, and long objectsByte, word, and long objects have no named instance variables. The indexed slotscontain bytes, word, or longs, respectively.

Read-only objectsPointer, byte, word, and long objects can be marked read-only. A read-only objectcannot be stored into by Smalltalk.

The following methods relate to read-only objects:

markReadOnly: aBooleanIf aBoolean is true, marks the receiver as read-only. If aBoolean is false, marksthe receiver as read-write. Answers true if the receiver is now read-only,false if the receiver is now read-write.

isReadOnlyAnswers true if the receiver is read-only, false if not.

Note: For immediate objects in ROM, this method will always answer truebecause these objects are always read-only.

attemptedROMStore: storedObject intoSlot: anIntegerSends this message to a read-only object when an attempt is made to storeinto it. anInteger is the instance variable index of the slot in the receiverwhere the store was attempted (this is the same index used byinstVarAt:put:). storedObject is the object being stored.

If this method answers true, the store operation is retried. If the receiverhas been marked read-write, the store will take place. If not, this messagewill be sent again. If this method answers false, the store operation isignored.

Note: storedObject and anInteger are suitable for instVarAt:Put: not at:put:. Ifthe receiver is a String or DBString, storedObject will be an Integer,not a Character.

Fixed objectsPointer, byte, word, and long objects can be made fixed. A fixed object cannot bemoved by the Smalltalk garbage collector. Fixed objects can be used to provide Ccode with memory that can be used to store results (for example, a buffer for acommunications interrupt handler). Once an object has been made fixed, itsaddress does not change.

The following methods relate to fixed objects:

Chapter 11. IBM Smalltalk Virtual Machine API 287

Page 302: IBM Smalltalk: Programmer's Reference

makeFixedMoves the receiver into fixed space. Answers the receiver. If there is notenough fixed space memory for the receiver, a walkback occurs.

isInFixedSpaceAnswers true if the receiver is fixed, false if not.

Note: Fixed objects that become garbage are not garbage collected until the nexttime the image is started. At that time, IBM Smalltalk can be sure that thereare no C code references to the object and the object can safely be collected.

Macros versus functionsAll operations in this chapter are described as being functions. However, somemight be implemented as macros. In future releases of IBM Smalltalk, someoperations might change from macros to functions or vice-versa. To ensure futurecompatibility, do not pass expressions with side-effects to functions described here.Also, do not attempt to take the address of any of the API functions.

External language interfaceIBM Smalltalk interfaces with other languages through the PlatformFunctionmechanism. A PlatformFunction is an object that prototypes a function in anotherlanguage (C for example). The PlatformFunction contains the shared library wherethe function can be found, the function’s name or number, and the types of thearguments and return value, if any.

For example, to create a PlatformFunction for the DosBeep function in OS/2, do thefollowing:dosBeep :=

PlatformFunctioncallingConvention: 'c'function: 286library: 'DOSCALL1'parameterTypes: #(uint32 uint32)returnType: #uint32.

See “Platform requirements” on page 333 for details about platform-specific callingconventions. The function: parameter can be a positive Integer or a String. Thelibrary: parameter is the name of the shared library where the function is stored. Itcan be a String or nil. The parameterTypes: argument is an array of type names (seebelow). The returnType: argument is a single type name.

If the library is given as nil, the function must be a String. The function is found inthe user primitive table instead of in a shared library. The string is the name of theuser primitive. The function that is called is not a user primitive; it is a normal Cfunction. See “User primitive tables” on page 319 for details on how to addfunctions to the table.

Parameter typesThe supported parameter types for the C language are:

none, voidThis is not a valid parameter type. If used as the return type, the value nilis returned.

objectNo conversion is performed. The parameter value is passed directly to the

288 IBM Smalltalk: Programmer’s Reference

Page 303: IBM Smalltalk: Programmer's Reference

called function. Returned values are passed directly back to Smalltalk. ThePlatformFunction author must ensure that only valid IBM Smalltalk objectsare returned.

struct Can be used only as a parameter type; for parameters, this is valid only forbyte, word, or long objects and nil. For byte, word, and long objects, thepassed parameter is a pointer to the first instance variable of the object. Fornil, 0 (NULL) is passed.

char, char8If used as a parameter type, the parameter must be a Character whosenumeric value is between 0 and 255. The parameter is converted to a Cchar. If used as a return value, the low 8 bits of the return value areconverted to a Character before returning to Smalltalk.

char16 All instances of Character are converted. This means that the passed-invalues will be between 0 and 65535 and the low 16 bits of the return valueare converted to a Character on return.

float, double, extendedIf used as a parameter type, the parameter must be a Float. The parameteris converted to the specified size of float. If used as a return value, theresult is converted to an instance of Float.

bool, booleanFor outgoing parameters, only true or false can be converted. The passedparameter is TRUE for true, FALSE for false. As a return type, 0 isconverted to false, and all other values are converted to true. The passedvalue for true is platform-dependent. The value of !0 in C is passed.

int8, int16, 1nt32, uint8, uint16, uint32If used as a parameter type, the parameter must be an Integer that can berepresented in 32 bits, Character, Boolean, or nil (see “Passed parameters” onpage 290). Instances of OSObject with reftype immediate (namely true, false,nil, Characters, and SmallIntegers) can also be used (see “OSObjects” onpage 308). If used as a return type, the low n (8, 16, 32) bits of the returnvalue are sign- or zero-extended (signed or unsigned, respectively) andthen converted to a Smalltalk Integer. The return value in Smalltalk isguaranteed to be within these given ranges:int8 -128...127int16 -32768...32767int32 -2147483648...2147483647uint8 0...255uint16

0...65535uint32

0...4294967295

pointerAs a parameter type, this is an amalgamation of the struct, char, bool, andint type conversions. If the parameter is a byte, word, or long object or nil,the struct conversion is performed. If the parameter is true or false, the boolconversion is performed. If the parameter is a Character, the char16conversion is performed. If the parameter is an Integer, the uint32conversion is performed.

Instances of OSObject can also be supplied as the parameter. If theOSObject reftype is handle, the handle is dereferenced and the offset isadded. All other objects cause the conversion to fail. If used as a returntype, the uint32 conversion is performed.

Chapter 11. IBM Smalltalk Virtual Machine API 289

Page 304: IBM Smalltalk: Programmer's Reference

safePointerAs a parameter type, the parameter may be a byte, word or long object.Instances of OSObject can also be supplied as the parameter provided theydo not have reftype immediate. If used as a return type, the uint32conversion is performed.

Passed parametersAll values passed to C functions are extended to a 32-bit quantity before beingpassed. Signed integers are sign extended; unsigned integers are zero extended.Because the C compiler does the same thing, it will be transparent to you.

All of the int types perform the same conversion for when converting from IBMSmalltalk objects to external language values. For example, it is legal to pass -1 as auint32 or a uint8. Both result in 0xFFFFFFFF being passed.

Calling a PlatformFunctionOnce a PlatformFunction has been created, it can be called using call, callWith:,callWith:with:, and so on. The number of arguments in the call must match thenumber of arguments in the PlatformFunction.

For example, to call the DosBeep function described above, you might use thefollowing statement:rc := dosBeep callWith: 100 with: 200

Error casesThe call to a PlatformFunction can fail and cause a walkback for the followingreasons:

Invalid argument countThe number of parameters in the PlatformFunction is not the same as thenumber of parameters in the call.

Invalid classThe parameter could not be converted because its class is invalid (forexample, trying to pass a Float in an int32 parameter). All such typeconversions must be done explicitly (for example, pass the Float truncatedas the parameter).

Value out of rangeThe Character or Integer value is not in the range allowed for the type (seeabove for the ranges).

Not enough memoryThere is insufficient memory to allocate a LargeInteger for the return valueof the function.

Operating system errorAn operating-system-specific error occurred; for example, it could not findthe shared library or the function in the library.

Note: Calling a PlatformFunction with invalid arguments may result in a systemcrash. You need to ensure the validity of the arguments.

Inline external function callsAn external language function can be called directly from a method using thefollowing syntax:

290 IBM Smalltalk: Programmer’s Reference

Page 305: IBM Smalltalk: Programmer's Reference

messagePattern<callingConvention: returnType 'library':function parameterTypes>...fail code...

For example:send: msg to: id

<c: int32 'message':sendTo int32 int32>|self primitiveFailed

External language functions have the same syntax as those in PlatformFunction,with one exception. If the function called is in the user primitive tabe and not in ashared library, omit the references to the library. Thus, change the previousexample as follows:send: msg to: id

<c: int32 sendTo int32 int32>|self primitiveFailed

The receiver of the method is not used in the function call. The number ofarguments to the method must be the same as the number of parameters specifiedin the external function call. If callingConvention: specifies a returnType of voidor none, the Smalltalk method returns the nil.

If the call to the external function fails (for the reasons described in “Error cases”on page 290), the fail code (the rest of the code in the method) is run. If no fail

code is provided, self is returned on failure. The suggested default fail code is |selfprimitiveFailed. It generates a walkback describing the reason for the failure anddisplaying the operating system error.

PlatformFunction protocolsThe address of a PlatformFunction is not looked up until required (for example,when calling it). Looking up the address is referred to as binding. APlatformFunction can also be unbound by the system, meaning that it must bebound again before being called.

Instance methods: accessingThe get methods are listed below. For every get method, there is a correspondingset method.

address Answers the address (a positive Integer) of the receiver. If the receiver isnot already bound, bind it. If the binding fails, a walkback occurs.

callingConventionAnswers the calling convention (a Symbol) of the receiver.

functionNumberIf the receiver is a numbered function, answers the number (a positiveInteger). Otherwise, answers nil.

libraryIf the receiver resides in a shared library, answers the appropriatePlatformLibrary object. Otherwise, answers nil.

name If the receiver is a named function, answers the function name (a String).Otherwise, answers nil.

parameterTypesAnswers an array of the receiver’s parameter types (Symbols).

returnTypeAnswers the Symbol describing the return type of the receiver.

Chapter 11. IBM Smalltalk Virtual Machine API 291

Page 306: IBM Smalltalk: Programmer's Reference

Instance methods: callingcall Calls the receiver and answers the result of the call. If the return type is

void, answers the receiver. If the receiver cannot be bound or a parametercannot be converted, a walkback occurs.

callWith:Calls the receiver with the given arguments. Answers the result of the call.If the return type is void, answers the receiver. If the receiver cannot bebound or a parameter cannot be converted, a walkback occurs.

callWith:with:Calls the receiver with the given arguments. Answers the result of the call.If the return type is void, answers the receiver. If the receiver cannot bebound or a parameter cannot be converted, a walkback occurs.

callWith:with:...with:Calls the receiver with the given arguments. The maximum number ofarguments is 32. Answers the result of the call. If the return type is void,answers the receiver. If the receiver cannot be bound or a parameter cannotbe converted, a walkback occurs.

Class methods: instance creationcallingConvention:function:library:parameterTypes:returnType:

Answers a new PlatformFunction with the given parameters. ThecallingConvention: must be a string or symbol. The function: can be apositive Integer or a String. The library: is the name of the shared librarywhere the function is stored. It can be a String or nil. parameterTypes: is anarray of type names (Strings or Symbols). The returnType: is a single typename (a String or Symbol).

Note: If the library is given as nil, the function must be a String. Thefunction is looked up in the user primitive table instead of in ashared library. The String is the name of the user primitive. Thefunction that is called is not a user primitive; it is a normal Cfunction.

callingConvention:address:parameterTypes:returnType:Answers a new PlatformFunction with the given parameters. ThecallingConvention:, parameterTypes:, and returnType: are the same as above.The address: is a positive Integer. Use this method to create aPlatformFunction for a function that is not in a shared library but whoseaddress is available by some other means (for example, returned by anoperating system call). A PlatformFunction created in this manner has itsaddress set to zero when the image starts.

CallingConvention

OS/2 Windows 95/98 Windows NT UNIX

’c’ __stdcall __stdcall __stdcall (none)

’pascal16’ _Far16 _Pascal __far __pascal

’pascal’ _Pascal

’cdecl16’ _Far16 _Cdecl __far __cdecl

v ’abtSystem’ and ’abtC32’ are obsolete synonyms for ’c’.v ’c16’ and ’abtsystem16’ are obsolete synonyms for ’pascal16’.v ’abtpascal32’ is an obsolete synonym for ’pascal’.v ’abtc16’ is an obsolete synonym for ’cdecl16’.

292 IBM Smalltalk: Programmer’s Reference

Page 307: IBM Smalltalk: Programmer's Reference

PlatformLibrary protocolsInstances of PlatformLibrary are used to look up function or data addresses inoperating system shared libraries. PlatformLibrary is used implicitly by instances ofPlatformFunction.

Each instance has a logical name and a physical name. The logical name is thename used to refer to the library in Smalltalk (for example, the library name usedin a PlatformFunction). The physical name (which can be the same as the logicalname) is the name that is passed to the operating system. The PlatformLibrary classkeeps a list of all instances that it creates. This way, multiple instances with thesame logical name are never created.

Instance methods: accessinglogicalName

Answers the logical name of the receiver (a String).

physicalNameAnswers the physical name of the receiver (a String or nil).

Instance methods: library operationsgetAddress:

Answers the address (a positive Integer) of the library object in the receiver.The library object must be a String or an Integer. If the library object cannotbe found, a walkback occurs.

close Closes the receiver. All PlatformFunctions that reside in the receiver areunbound.

Class methods: mapping logical names to physical namesmapLogicalName:toPhysicalName:

Sets the mapping for the platform library’s logical name to the specifiedphysical name. If a PlatformLibrary with the specified logical name exists,closes it and sets its physical name as indicated. If a new instance ofPlatformLibrary with the logical name is created at some later time, itsphysical name is set as indicated. The logical name and the physical namemust be a String. The physical name must be either a String or nil. If thephysical name is nil, all functions in the library are looked up in the userprimitive table instead of an operating system shared library.

removeMappingForLogicalName:Removes the mapping for the logical name, if any. If a PlatformLibrary withthe logical name exists, closes it, and sets its physical name to the logicalname. If a new instance of PlatformLibrary with the logical name is createdat some later time, its physical name is set to the logical name. The logicalname must be a String.

Class methods: instance creationlogicalName:

If a PlatformLibrary with the logical name already exists, answers it.Otherwise, answers a new instance whose logical name is as indicated andwhose physical name is set according to the mappings. The logical namemust be a String.

Chapter 11. IBM Smalltalk Virtual Machine API 293

Page 308: IBM Smalltalk: Programmer's Reference

Class methods: miscellaneousremoveUnreferencedLibraries

Closes all instances of PlatformLibrary. Discards any instances that are notreferenced from at least one PlatformFunction. This method does notremove any mappings.

Entry pointsIBM Smalltalk allows other languages to call Smalltalk through the EsEntryPointmechanism. An EsEntryPoint is an object that prototypes a function in anotherlanguage such as C. An EsEntryPoint contains the Smalltalk receiver and selector aswell as the types of the parameters and any return value.

For example, to create an EsEntryPoint for the WindowProc function in Windows,you can use the following code in the class OSEventManager:initializeWindowClass

"Private - Get the standard window procedure and register thewindow class in the OS."| windowProc address |"Get the address of the window proc and install the receiver and selector.This message is sent from the window proc for every OS message."windowProc :=

EsEntryPointreceiver: selfselector: #windowProc:msg:with:with:callingConvention: 'c'arrayBased: falseparameterTypes: #(uint32 uint32 uint32 uint32)returnType: #int32.

windowProc failAddress: DefWindowProc address.address := windowProc address."Register the Smalltalk window procedure."WindowClass := 'WINDOWPROC'.Hab

winRegisterClass: WindowClasspfnWndProc: addressflStyle: CsSizeredrawcbWindowData: 4.

To use an EsEntryPoint, create it and send it the message address. The result is aninteger that can be passed out to a PlatformFunction that requires a function pointeras a parameter. When the external language calls the function pointer, IBMSmalltalk converts the parameters into Smalltalk objects and sends the messagedesignated by the receiver and selector of the EsEntryPoint. The receiver parametercan be any Smalltalk object. The selector parameter must be a Symbol.parameterTypes is an array of type names and returnType is a single type name. ThecallingConvention parameter must be a string that is one of the valid IBM Smalltalkcalling conventions. For details about platform-specific calling conventions, see“Platform requirements” on page 333.

There are two kinds of EsEntryPoints, depending on the value of arrayBasedparameter when an EsEntryPoint is created. If arrayBased is false, the selector musttake the same number of parameters as the number of parameters in theparameterTypes array; that is, one per external language parameter. If arrayBased istrue, the selector must take one parameter, which is an array of all the parameters.

Note: When using an EsEntryPoint, you do not need to make any of the objects(the receiver, selector, or the EsEntryPoint itself) fixed.

294 IBM Smalltalk: Programmer’s Reference

Page 309: IBM Smalltalk: Programmer's Reference

Parameter types and return typesThe supported parameter types and return types are:

none, voidThis is not a valid parameter type. If it is used as the return type, thereturn value of the Smalltalk message is ignored and no value is returnedto the caller of the EsEntryPoint.

char, char8If it is used as a parameter type, the low eight bits of the parameter areconverted to a Character whose numeric value is between 0 and 255. If it isused as a return type, the return value from the Smalltalk message must bea Character whose numeric value is between 0 and 255.

char16 If it is used as a parameter type, the low 16 bits of the parameter areconverted to a Character. If it is used as a return type, the return valuefrom the Smalltalk message must be a Character.

bool, booleanIf it is used as a parameter type, the low eight bits of the parameter aretested for 0. If they are 0, false is passed to the Smalltalk message. If theyare not 0, true is passed. If it is used as a return type, only true or false canbe converted. The return value is TRUE for true, and FALSE for false.

The return value for true is platform-dependent. In C it is the value of !0.

int8, int16, int32, uint8, uint16, uint32If it is used as a parameter type, the low 8, 16 or 32 bits of the parameterare converted to an Integer that is in the specified range. If it is used as areturn type, the return value must be an Integer (see “Returnedparameters” on page 296). The integer ranges are as follows:int8 -128...127int16 -32768...32767int32 -2147483648...2147483647uint8 0...255uint16 0...65535uint32 0...4294967295

struct If it is used as a parameter type, the parameter is converted using uint32conversion. If it is used as a return type, the return value must be a byte,word, or long object or a non-immediate OSObject. nil is returned as 0.

pointerIf used as a parameter type, the parameter is converted using uint32conversion. If it is used as a return type, this is an amalgamation of struct,char, bool, and int type conversions. For a given parameter type, theconversion performed is as follows:byte object, word object, long object, nil

structtrue, false

boolCharacter

char16Integer uint32OSObject

struct

All other objects cause the conversion to fail.

Chapter 11. IBM Smalltalk Virtual Machine API 295

Page 310: IBM Smalltalk: Programmer's Reference

safePointerIf it is used as a parameter type, this is the same as pointer conversion. If itis used as a return type, the parameter can be a fixed byte, word, or longobject. Instances of OSObject can also be supplied as the parameterprovided they are non-immediate.

If an OSObject whose reference is a byte, word, or long object is returned,the reference must be in fixed space. This is also true for byte, word, orlong objects that are returned directly.

Returned parametersAll values returned to external language functions are extended to a 32-bit quantitybefore being returned. Signed integers are sign-extended; unsigned integers arezero-extended. All the int types perform the same conversion when convertingfrom IBM Smalltalk objects to external language values. For example, -1 can bereturned as a uint32 or a uint8. Both result in 0xFFFFFFFF being returned.

Calling an EsEntryPointOnce an EsEntryPoint is created, send it the message address to bind it. Theaddress can be passed to an external language function that requires a functionpointer. For example, to get the address of the WindowProc callback describedabove:address := windowProc address.

External functions calling Smalltalk using EsEntryPoint must run in the samethread as Smalltalk.

Error casesThe call to address can fail and cause a walkback for the following reasons:

No more entry pointsAll available EsEntryPoint addresses are in use.

Invalid calling conventionThe EsEntryPoint is using an unsupported calling convention.

Not enough memoryThere is insufficient memory to allocate a LargeInteger for the return valueof the function or to allocate internal support structures.

EsEntryPoint failureWhen the address of an EsEntryPoint is called by the external language, there isalways the possibility of failure. It may not be possible to allocate the necessaryobjects required for the conversion to Smalltalk objects. The return value fromSmalltalk may be invalid and unconvertable.

EsEntryPoint instances contain a fail address that defaults to 0. When the callbackfails for any reason, this address is checked. If it is 0, 0 is returned from thecallback. If it is not 0, it must be the address of a function that has exactly thesame prototype as the EsEntryPoint. Upon failure, this function is called.

For example, in Windows, the following code can be used to catch a WindowProcfailure:windowProc failAddress: (PlatformFunctions at: 'DefWindowProc') address

This code causes DefWindowProc to be called when the Smalltalk WindowProcfails. When an EsEntryPoint unbinds, the fail address is reset to 0.

296 IBM Smalltalk: Programmer’s Reference

Page 311: IBM Smalltalk: Programmer's Reference

EsEntryPoint protocolsEsEntryPoint has the following methods:

Instance methods: accessingaddress Answers the address (a positive integer) of the receiver. If the receiver is

not already bound, binds it. If the binding fails, a walkback occurs.

failAddressAnswers the fail address (a positive integer) of the receiver. Answers 0 ifno fail address has been specified.

failAddress:Sets the fail address (a positive integer) of the receiver to anInteger. IfanInteger is not valid, a walkback occurs.

receiverAnswers the receiver of the callback message selector. Answers the selectorof the callback message.

isArrayBasedAnswers true if the received accepts arguments as an array; false if thereceiver accepts each argument individually.

callingConventionAnswers the calling convention (a Symbol) of the receiver.

parameterCountAnswers the number of arguments expected by the receiver.

parameterTypesAnswers an array of the receiver’s argument types (instances of Symbol).

returnTypeAnswers the Symbol describing the return type of the receiver.

Instance methods: miscellaneousunbind Unbinds the receiver. This returns the receiver’s address to the pool of

available addresses. The receiver must not be in use when it is unbound orthe system may crash the next time the address is called. This also resetsthe fail address of the receiver to zero. All instances of EsEntryPoint and itssubclasses are unbound when the image starts.

Class methods: instance creationreceiver:selector:callingConvention:arrayBased:parameterTypes:returnType:

Answers a new EsEntryPoint with the given parameters. ThecallingConvention must be a String or Symbol. The receiver parameter maybe any Smalltalk object. The selector parameter must be a Symbol.parameterTypes is an array of type names and returnType is a single typename.

There are two kinds of EsEntryPoints, depending on the value of arrayBasedparameter when the EsEntryPoint was created. If arrayBased is false, theselector must take the same number of parameters as the number ofparameters in the parameterTypes array; that is, one per external languageparameter. If arrayBased is true, the selector must take one parameter, whichis an array of all the parameters.

Chapter 11. IBM Smalltalk Virtual Machine API 297

Page 312: IBM Smalltalk: Programmer's Reference

Asynchronous calloutsWhen a platform function call is made in Smalltalk, all Smalltalk processes blockuntil that call completes. Asynchronous callout is an extension to the standardplatform function call protocol that allows developers to make a platform functioncall in a separate thread. By making the call in a separate thread, it ensures thatonly those processes waiting on the result of the platform function call block.

For example, if a socket receive call that blocks is made in Smalltalk, no Smalltalkprocesses run until the receive call completes. By using asynchronous callout, onlythose processes waiting on the return value of the receive operation block.

These are the ways a Smalltalk process makes asynchronous calls:

Standard asynchronous callThe Smalltalk process blocks until the call completes. This type of call isused when the process needs the return value and cannot proceed until ithas been calculated.

Resource future callThe Smalltalk process receives a future and continues to run, polling thefuture for the result of the platform function call. This type of call is usedwhen the process does not immediately need the return value and cancontinue executing. Additionally, more than one process may wait on thereturn value.

Static future callThe Smalltalk process receives a future and continues to run, polling thefuture for the result of the platform function call. A static future call differsfrom a resource future call in that the same thread can be used by morethan one call. Some calls, such as those that get the last error, requireseveral platform function calls to be made in the same thread.

The syntax for using asynchronous calls is similar to normal platform functioncalls. The system sets up the OS resources required to make the call, executes thecall, and recovers the resources automatically.

With resource futures calls, the system manages the OS resources. The system setsup the OS resources required to make the call, executes the call, and recovers theresources automatically. Resource future calls can be used for single asynchronouscalls only.

Static futures calls require the developers to manage resources themselves. Theadvantage of a static future call is that it can be used to make more than oneplatform function call in the same thread. The developer must explicitly allocatethe resources for the future and return them when the future is no longer required.

Calling a Platform Function asynchronouslyAfter a PlatformFunction has been created, it can be called using one of theseasynchronous protocols:

Standard asynchronous callasyncCall, asyncCallWith:, asyncCallWith:with:, and so on

Resource future callfutureCall, futureCallWith:, futureCallWith:with:, and so on

298 IBM Smalltalk: Programmer’s Reference

Page 313: IBM Smalltalk: Programmer's Reference

Static future callstaticFutureCall:, staticFutureCall:with:, staticFutureCall:with:with:, and so on

The number of arguments in the call must match the number of arguments in thePlatformFunction. The following sections describe how to make asynchronous callsusing each of the protocols.

Standard asynchronous callsStandard asynchronous calls are created using the asyncCall... API. Use standardasynchronous calls when the value is required by a single process, and the processmust wait until the call has completed. Standard asynchronous calls cause thecurrent Smalltalk process to be suspended until the value is returned. OtherSmalltalk processes continue to execute.

When an asynchronous call is made, an operating system thread is acquired, thecurrent Smalltalk process suspends, and the platform function is executed in thatthread. When the call completes, the result is posted back to Smalltalk, and theprocess that was waiting for the result resumes.

For example, to call a platform function asynchronously:param1 := 100.param2 := 200.rc := dosBeep asyncCallWith: param1 with: param2

param1 and param2 are the arguments to the call. dosBeep is a previously declaredplatform function. The rc is the return value of the platform function, or anAcoError if an error occurred during the execution of the call. For a discussion oferrors, see “ACO errors and error cases” on page 301.

When a standard asynchronous call is made during a system callback (that is whenthe operating system has called back into Smalltalk), the call is performedsynchronously. Standard asynchronous calls are the fastest form of asynchronouscall.

Resource future callsResource future calls should be used if more than one process needs to wait on thereturn value or if the current process must continue executing until the returnvalue is needed.

When a resource future call is made, a future is returned. This future can bequeried for the state of the call while the platform function executes in a separatethread. If a process asks for the value of the future before the value is ready, theprocess is suspended. More than one process can wait on the return value of thefuture. When the call completes, the result is posted back to Smalltalk and theprocesses that are waiting on the result are resumed.

For example, to call a platform function using a resource future call:param1 := 100.param2 := 200.aFuture := dosBeep futureCallWith: param1 with: param2.12 fibonnacci. "May or may not execute before the call completes."rc := aFuture value.12 fibonnacci. "Will not execute until the call completes."

param1 and param2 are the arguments to the call. The rc is the return value of theplatform function, or an AcoError if an error occurred. The aFuture is a future thatcontains the result of the platform function. You must explicitly ask the future for

Chapter 11. IBM Smalltalk Virtual Machine API 299

Page 314: IBM Smalltalk: Programmer's Reference

its value. If the platform function has not yet completed, the process asking for thevalue of the platform function call blocks until the value is ready.

To check the status of a blocking call, the messages checkForValue or isReady can besent to the future. The message checkForValue answers the return value if it is readyor an AcoError if it is not yet ready. The message isReady answers true if the returnvalue is ready; otherwise, it answers false. When a future is asked for its valueduring a system callback (that is when the operating system has called back intoSmalltalk), if the return value has not been calculated, then an AcoError isanswered. Resource future calls are slower than standard asynchronous calls.

Static future callsLike resource future calls, static future calls allow the current Smalltalk process tocontinue running until the return value is needed.

In addition, static future calls allow you to use the same operating system threadin more than one asynchronous call. The static future call does this by reserving athread. This is useful when data is stored in the local memory for a thread. As aresult, you must manage the resources by explicitly creating and destroying staticfutures and their resources. “Allocating resources for static futures” on page 301discusses the allocation and deallocation of resources.

To begin a static future call, the developer creates a static future and makes thecall. When the call completes, the result is posted back to Smalltalk and processeswaiting on the result are resumed. At this point, the developer may either reusethe static future or return its resources to the AcoResourceManager.

For example, to call a platform function using a static future call:aFuture := AcoResourceManager default createStaticFuture.param1 := 100.param2 := 200.rc := dosBeep staticFutureCall: aFuture with: param1 with: param2.rc := aFuture value."A second call can be made using the same thread."rc := dosBeep staticFutureCall: aFuture with: param1 with: param2.rc := aFuture value.AcoResourceManager default returnStaticFuture: aFuture.

param1 and param2 are the parameters to the call. The rc is the return value of theplatform function. The aFuture is a static future that contains the result of theplatform function. You must explicitly ask the future explicitly for its value. If theplatform function has not completed, the process asking for the value of a futureblocks until the value is ready.

The static future can be reused for other platform function calls. These calls will bemade in the same operating system thread. Once the developer no longer requiresthe static future, it must be returned to the AcoResourceManager.

To check the status of a blocking call, the messages checkForValue or isReady can besent to the future. The message checkForValue answers the return value if it is readyor an AcoError if it is not ready. The message isReady answers true if the returnvalue is ready; otherwise, it answers false.

Before a static future can be used in a subsequent call, the previous call must havecompleted. There are two protocols for determining this. Sending value to thefuture guarantees that the previous call has completed before the next starts

300 IBM Smalltalk: Programmer’s Reference

Page 315: IBM Smalltalk: Programmer's Reference

because value waits until the call completes. When a static future is sent isAvailable,it answers true if the future is not involved in another asynchronous call and falseif it is.

When a future is asked for its value during a system callback (that is when theoperating system has called back into Smalltalk), if the return value has not beencalculated, then an AcoError is answered.

Static future calls are slower than standard asynchronous calls, but faster thanresource future calls.

Allocating resources for static futures: The AcoResourceManager allocates anddeallocates resources for a static future. Resources include the thread used to makethe call and some fixed-space memory. To get the default resource manager, themessage default is sent to the AcoResourceManager class. The default resourcemanager can then be sent the following messages to allocate and deallocateresources:

createStaticFutureAllocates a static future and the required resources. Answers the staticfuture created.

returnStaticFuture:Returns to the resource manager the resources used by the static future.

reinitializeStaticFuture:Reacquires resources for the static future that were previously lost whenthe image was saved.

createStaticFutureWithStackSize:Creates a static future with a thread having a stack size equal to anInteger.Answers the static future created.

Locking resources for an asynchronous callOccasionally, several calls must be made in the same thread. For example, inWindows to get the last error code from a function call, developers must make theGetLastError call in the same thread as the original call was made.

By using the lockThreadIn: aBlock protocol in the AcoResourceManager the developerspecifies a series of standard asynchronous calls (for example, asyncCall) to bemade in the same operating system thread. The protocol reserves a single threadfor all the calls made in the scope of the block.

The following is an example of standard asynchronous calls (dosBeep andgetLastError) that are guaranteed to occur in the same thread:AcoResourceManager default lockThreadIn: [

rc := dosBeep asyncCallWith: param1 with: param2.rc2 := getLastError asyncCall]

ACO errors and error casesAn asynchronous call can generate these types of errors:

Errors that generate walkbacksThese errors are caused by an incompatibility between the arguments andthe platform function call.

Errors that generate AcoErrors for the return valueThese errors are often recoverable because they are often caused by

Chapter 11. IBM Smalltalk Virtual Machine API 301

Page 316: IBM Smalltalk: Programmer's Reference

resource problems associated with making the call. By returning an errorobject rather than a walkback, the developer can recover from the failurewithout using exceptions.

WalkbacksThe asynchronous call to a PlatformFunction can fail and cause a walkback forseveral reasons. The reasons are identical to the error cases for callWith:, which aredescribed in “Error cases” on page 290.

ACO errorsThe return value from an asynchronous call is either the return value of theplatform function or an AcoError; the AcoError identifies the problem that occurredwhile making the asynchronous call.

To test for an error, isAcoError can be used. For example, to determine whether anerror occurred, the following code can be used.

For standard asynchronous calls:rc := dosBeep asyncCallWith: parm1 with: parm2.rc isAcoError ifTrue: [self error: rc printString]

For resource future calls:future := dosBeep futureCallWith: parm1 with: parm2.rc := future value.rc isAcoError ifTrue: [self error: rc printString].

For static future calls:staticFuture := AcoResourceManager default createStaticFuture.staticFuture isAcoError ifTrue: [self error: staticFuture printString].dosBeep staticFutureCall: staticFuture with: parm1 with: parm2.rc := future value.rc isAcoError ifTrue: [

AcoResourceManager default returnStaticFuture: staticFuture.self error: rc printString].

AcoResourceManager default returnStaticFuture: staticFuture.

ACO errors include:

Resources invalidThe operating system resources (for example, the thread) are no longervalid. This may occur after an image is shut down and restarted.

Invalid static futureThe future being passed into a static future call is either not a type ofStaticFuture or is a static future that has invalid operating system resources.Resources may become invalid after an image is shut down and restarted.

The resource is not availableThere are no available resources.

The static future is not availableThe static future being used to make the call is currently executing aprevious call.

Resources lostAn asynchronous call was in progress when an image was saved. Whenthe image restarted, the asynchronous call cannot continue because theoperating system resources (for example, the thread) are no longer valid.

302 IBM Smalltalk: Programmer’s Reference

Page 317: IBM Smalltalk: Programmer's Reference

The value is not availableThe future has not completed the call and the return value is not ready.

Asynchronous callout not supportedThe platform does not support asynchronous callout.

Primitive failed due to general protection faultThe platform function that was called caused a general protection fault.

Invalid stack size requestedA stack size was requested when a thread was locked using thelockThreadIn: method of AcoResourceManager.

Requested future value in a system callbackYou cannot request the value of a future during a callback into Smalltalkfrom the operating system.

Parameter types and return typesAll parameters and return types used in standard platform function calls arepermitted except:

object You cannot pass or return object parameters in functions that are calledasynchronously, including objects in fixed space.

Parameters passed with asynchronous callsObjects located in movable memory that are passed into an asynchronous call arecopied into a location in non-movable memory for the duration of theasynchronous call. When the asynchronous call completes, the arguments arecopied back to the original objects. If the object is not copied, the garbage collectormay move the object during the call, resulting in unpredictable behavior.

Objects that are not movable and not copied include:v OSObjects that reside in operating system memory, such as those allocated using

callocv Objects that reside in fixed space

Objects are otherwise passed in the same way as platform function calls using thecallWith:... protocol.

Because objects are copied during an asynchronous call, the parameters passed tothe function should not be used while the asynchronous call is in progress. Thecontents of the parameters may be changed at any time by the asynchronous call.

Managing resourcesAsynchronous calls are made in a separate operating system thread. When the callis blocked waiting for a resource, only that thread blocks and not the thread thatIBM Smalltalk is running in.

To support asynchronous callout, IBM Smalltalk manages both the thread andsome additional resources in fixed space. The additional resources allow IBMSmalltalk and the asynchronous thread to interact.

Minimum required resourcesTo make asynchronous calls, the platform must support threads at the operatingsystem level. On platforms that do not support threads at such a level,asynchronous calls are converted into synchronous calls.

Chapter 11. IBM Smalltalk Virtual Machine API 303

Page 318: IBM Smalltalk: Programmer's Reference

To determine whether a platform supports asynchronous callout, the classEsAsynchronousCallout can be sent the message supported, which returns true if theplatform supports asynchronous callout and false if it does not.

Additionally, the image must have adequate fixed space allocated to allowasynchronous calls to be made.

ACO resource managerThe resources (that is, the thread and fixed-space memory) are managed by theACO resource manager (AcoResourceManager). The manager improves performanceby caching resources that are expensive to create (the thread) or are not collectableby garbage collection (the fixed-space memory).

When using standard asynchronous protocols (asyncCall...) or resource futureprotocols (futureCall...), the resources are managed automatically through theresource manager. Static future protocols (staticFutureCall:...) permit the resources tobe managed manually, but still require the resource manager.

The resource manager allows developers to control how operating system threadsand fixed-space resources are managed. The resource manager allows you tocontrol the resources using the following selectors:

cacheSize:, cacheSizeThe number of resources to cache. The default is 10 threads.

maximumNumberOfResources:, maximumNumberOfResourcesA maximum limit on the number of resources created. On some systems,all the processes compete for a limited set of threads. This value is used tolimit the number of threads that Smalltalk acquires for itself. The default isno limit.

limitOfReclaimedFutures:, limitOfReclaimedFuturesThe number of futures that are recovered from fixed space when the imagestarts up. The default is 10.

defaultStackSize:, defaultStackSizeThe stack size that threads are created with. The default is 8192 bytes.

defaultPriority:, defaultPriorityThe priority that operating system threads run at. This is a value between1 (lowest priority ) and 7 (highest priority).

Resource limitationsAn asynchronous call can have problems with resources by either:v Losing a resource, for example, when a thread is killedv Failing to acquire a resource

If resources are lost during a call, an AcoError is returned from the asynchronouscall indicating that the resources associated with the asynchronous call were lost.

Note: If you save an image, all the calls proceed normally in the running image.However, when you load the saved image, the threads for the asynchronouscalls have been terminated, and the asynchronous calls indicate that theyhave lost their resources.

The three different types of asynchronous calls can fail to acquire resources if oneof these conditions is true:v The AcoResourceManager has reached the limit set by

maximumNumberOfResources:.

304 IBM Smalltalk: Programmer’s Reference

Page 319: IBM Smalltalk: Programmer's Reference

v The operating system cannot create additional threads.v There is no more fixed space available.

Depending on the type of asynchronous call, there are different responses to thefailure to acquire resources. Calls using asyncCall or futureCall are automaticallyqueued, on a first-come, first-serve basis, until the resources become available. As aresult, standard asynchronous calls and resource future calls are delayed if thereare not enough resources. Calls using the staticFutureCall: method answer anAcoError indicating that the resources cannot be allocated.

Maintaining a threadThe AcoResourceManager and AcoStaticFutures let the developer maintain the threadan asynchronous call is made in. This is important for allowing more than one callto be made in the same thread. For example, getting the last error is thread-specificand must be guaranteed to occur in the same thread as the call that generated theerror.

AcoResourceManager lets you specify a set of calls to be made in the same thread,using the lockThreadIn: aBlock protocol. All the calls using asyncCall performed inaBlock are made in the same thread. The resources are reserved exclusively for callsmade in this block until the block finishes executing.

An AcoStaticFuture explicitly acquires and releases its threads. Between the timethat an AcoStaticFuture acquires a thread and releases it, its thread is reserved forexclusive use by that future.

Instances of both AcoResourceFuture and AcoStaticFuture are unaffected bylockThreadIn: aBlock. The resources they acquire and release are independent of theresources held by the lock.

Extensions to platform function protocolsThere are different calling conventions for making asynchronous calls, dependingon whether they are standard asynchronous calls, resource future calls, or staticfuture calls.

Instance methods: standard asynchronousasyncCall, asyncCallWith:, asyncCallWith:with:, asyncCallWith:with:...with:

Call the receiver with the given parameters. The maximum number ofparameters is 32. Block the current process until the call is completed.Answer the result of the call. If the return type is void, answer the receiver.If the receiver cannot be bound or an argument cannot be converted, awalkback occurs.

asyncCallWithArguments: anArray, asyncCallWithArguments: anArray stackSize:aStackSize

Call the receiver with the given parameters. The maximum number ofparameters is 32. If aStackSize is requested, use a thread with the specifiednumber of bytes. Block the current process until the call is completed.Answer the result of the call. If the return type is void, answer the receiver.If the receiver cannot be bound or a parameter cannot be converted, awalkback occurs.

Instance methods: resource futurefutureCall, futureCallWith:, futureCallWith:with:, futureCallWith:...with:...with:

Call the receiver with the given parameters. The maximum number ofparameters is 32. Answer an AcoResourceFuture. The current process

Chapter 11. IBM Smalltalk Virtual Machine API 305

Page 320: IBM Smalltalk: Programmer's Reference

continues to run. To obtain the return value, ask the AcoResourceFuture forits value. If the receiver cannot be bound or a parameter cannot beconverted, a walkback occurs.

futureCallWithArguments: anArray futureCallWithArguments: anArray stackSize:anIntegerStackSize

Call the receiver with the given parameters. If aStackSize is requested, use athread with the specified number of bytes. The maximum number ofparameters is 32. Answer an AcoResourceFuture. The current processcontinues to run. To obtain the return value, ask the AcoResourceFuture forits value. If the receiver cannot be bound or a parameter cannot beconverted, a walkback occurs.

Instance methods: static futurestaticFutureCall: anAcoStaticFuture staticFutureCall: anAcoStaticFuture with: parm1staticFutureCall: anAcoStaticFuture with: parm1 with: parm2 staticFutureCall:aAcoStaticFuture with: parm1...with: parmN...with: parm16 staticFutureCall: futurewithArguments: anArray

Call the receiver with the given parameters. the maximum number ofparameters is 32. Answer the parameter anAcoStaticFuture. The currentprocess continues to run. To obtain the return value ask anAcoStaticFuturethe for its value. If anAcoStaticFuture is not a type of AcoStaticFuture or haslost its resources, answer an AcoError. If the receiver cannot be bound or aparameter cannot be converted, a walkback occurs.

ACO resource manager protocols

Class methods: resource control protocolscacheSize

Answer the maximum number of resources that can be cached.

cacheSize:Set the maximum number of resources that can be cached.

default Answer the default resource manager for the system.

defaultStackSizeAnswer the default stack size of the thread.

defaultStackSize:Set the default stack size (in bytes) of the thread.

defaultThreadPriorityAnswer the default thread priority.

defaultThreadPriority:Set the default thread priority.

limitOfReclaimedFuturesAnswer the number of futures to be reclaimed when the image next startsup. A reclaimed future is added back into the AcoResourceManager. If thisvalue is nil, all possible futures are added. Futures that are not reclaimedremain in fixed memory until they are collected during garbage collectionthe next time the image starts up.

limitOfReclaimedFutures:Set the number of futures to be reclaimed when the image next starts up.A reclaimed future is added back into the AcoResourceManager. If this value

306 IBM Smalltalk: Programmer’s Reference

Page 321: IBM Smalltalk: Programmer's Reference

is nil, all possible futures are added. Futures that are not reclaimed remainin fixed memory until they are collected during garbage collection the nexttime the image starts up.

maximumNumberOfResourcesAnswer the maximum number of resources that can be created. If thisvalue is nil, the resources are limited by the fixed-space size and number ofthreads available from the operating system.

maximumNumberOfResources:Set the maximum number of resources that can be created. If this value isnil, the resources are limited by the fixed-space size and number of threadsavailable from the operating system.

Instance methods: static resource management protocolscreateStaticFuture

Answer a static future that maintains its resources during each call.Answer nil if failed to create a complete future because of lack ofresources.

createStaticFutureWithStackSize:Answer a static future with the specified stack size that maintains itsresources during each call. Answer nil if failed to create a complete futurebecause of lack of resources.

reinitializeStaticFuture:Answer the static future if resources can be acquired, nil otherwise. Discardthe resources that the static future is currently using and reinitialize it withnew resources. Use this method to reinitialize only static futures that areneeded after an image is exited and restarted because Smalltalk discardsthe current resource.

returnStaticFuture: aFutureUsed to return a static future to the resource pool. Answer an AcoError ifthe static resources cannot be returned to the pool; answer self otherwise.

lockThreadIn: aBlockEvaluate all the asynchronous calls in the block aBlock using the samethread. Answer the result of the block.

Resource future protocols

Instance methodscheckForValue

Answer true if the value is available and an AcoError otherwise.

isAcoFutureAnswer true if the object is a type of AcoFuture.

isReadyAnswers true if the value is available; false otherwise.

isStatic Answer false. This is not a static future.

value Answer the value of the future. If the value has not been calculated,suspend the current process until the value is ready.

Chapter 11. IBM Smalltalk Virtual Machine API 307

Page 322: IBM Smalltalk: Programmer's Reference

Static future protocols

Instance methodscheckForValue

Answer true if the value is available and an AcoError otherwise.

isAcoFutureAnswer true if the object is a type of AcoFuture.

isReadyAnswers true if the value is available; false otherwise.

isStatic Answer true. This is a static future.

value Answer the value of the future. If the value has not been calculated,suspend the current process until the value is ready.

ACO error protocols

Instance methodsgpInfo Answer the gpinfo string and nil if there was no general protection fault.

identifierAnswer a string describing the error identifier.

isAcoErrorAnswer true.

errorCodeAnswer the error number.

messageAnswer a string describing the error reported by the receiver.

printOn: aStreamPrint a text representation of the receiver on aStream. The format is<identifier>(<errno>: <message>.

OSObjectsTraditionally, Smalltalk has been ill-suited for modeling the complex memorystructures used by low-level languages like C, and by most modern operatingsystems. Often programmers were required to build facilities for accessing thesestructures using variable-byte classes and complex glue code. IBM Smalltalk, inaddition to having byte, word, and long classes for accessing simple array-likememory structures efficiently, provides a mechanism for describing and accessingarbitrary memory structures.

OSObject subclassesSubclasses of class OSObject are used to model particular kinds of memoryreferences. OSObject closely models C-style addressing and structure sharing.

Every OSObject has an indirection level that describes how many times a pointermust be followed to reach the actual data (a sequence of bytes in memory). Theoperation of dereferencing a pointer results in another pointer or immediate dataand reduces the indirection level of the new pointer by one.

308 IBM Smalltalk: Programmer’s Reference

Page 323: IBM Smalltalk: Programmer's Reference

OSImmediateYou can use subclasses of OSImmediate to represent C-style typedefs to unsigned 8-,16-, 32- or 64-bit values. Instances of OSImmediate cannot be dereferenced. Allsubclasses of OSImmediate have indirection level zero. To model HWND (the Ctypedef #typedef HWND unsigned long), add a new subclass of OSImmediate.OSImmediate provides the inherited class instance variable fixedSize that must beassigned before the class can be used. In this example, fixedSize is 4 (the size ofunsigned long).

OSBaseTypeYou use subclasses of OSBaseType to represent pointers to C base types.Dereferencing an OSBaseType answers a Smalltalk immediate type. All subclasses ofOSBaseType have indirection level one. To model int * (a pointer to a C array ofint), use the class OSInt32. Dereferencing an instance of OSInt32 results in a signedSmalltalk integer. IBM Smalltalk provides the following standard OSBaseTypesubclasses:v OSBool8, OSBool16, OSBool32v OSChar8, OSChar16v OSFloat32, OSFloat64v OSInt8, OSInt16, OSInt32v OSUInt8, OSUInt16, OSUInt32v OSVoid

OSStructureYou use subclasses of OSStructure to represent arrays of structs and unions. Allsubclasses of OSStructure have indirection level one. To model struct POINT * (apointer to a C structure struct {int x, y} POINT;), a new subclass of OSStructureis required. OSStructure provides the inherited class instance variables fixedSize thatmust be assigned before the class can be used. In this example, fixedSize is 8 (thesize of int x, y;).

OSVariableStructureYou use subclasses of OSVariableStructure represent variable-sized structures.Dereferencing is disallowed because the size of each element is not known. Tomodel struct DATA * (a pointer to struct {int cbSize; char data[1]} DATA;), anew subclass of OSVariableStructure is required. OSStructure provides the inheritedclass instance variables fixedSize and variableSize that you must assign before theclass can be used. In this example, fixedSize is 4 (the size of int cbSize;) andvariableSize is 1 (the size of one data element in the variable-sized portion of thestructure, or char data [1];).

OSObjectPointerOSObjectPointer is used to represent pointers to other instances of OSObject.Dereferencing an OSObjectPointer answers a new instance of OSObjectPointer or anOSObject subclass.

To model struct POINT ** (a pointer to a pointer to a C structure struct {int x,y;} POINT;), a new instance of OSObjectPointer is created. The following exampleuses an OSObjectPointer to model a pointer to an OSPoint:| ptr |ptr := OSObjectPointer calloc: 1 itemType: OSPoint.ptr at: 0 put: (point := OSPoint calloc x: 12; y:13)

OSObjectPointer can point to any OSObject. You can also use subclasses ofOSObjectPointer to model pointers to a single type of OSObject. The class of thisOSObject is specified by assigning the defaultItemType class instance variable in the

Chapter 11. IBM Smalltalk Virtual Machine API 309

Page 324: IBM Smalltalk: Programmer's Reference

new OSObjectPointer subclass. For example, by defining OSPointPointer (a subclassof OSObjectPointer) and assigning defaultItemType to OSPoint, the above codefragment could be rewritten as:| ptr |ptr := OSPointPointer calloc: 1.ptr at: 0 put: (point := OSPoint calloc x: 12; y:13)

OSObject protocolsThis section describes the protocols supported by OSObject.

Instance methodscastTo: Answer a new instance of anOSObjectClass, which is initialized to refer to

the same data as the receiver using the appropriate indirection level.

isOSObjectAnswer true if the receiver is an OSObject or one of its subclasses.

isUndefinedAnswer true if the receiver has no value.

makeUndefinedMake the receiver undefined. OSObject and PlatformFunction primitives failwhen used with an undefined OSObject.

Class methods: initializationfixedSize

Answer an integer that is the size in bytes of one data element of thereceiver.

fixedSize: anIntegerSet an integer that is the size in bytes of one data element of the receiver.This value must be set before using an instance of the receiver.

Class methods: instance creationundefined

Answer an undefined instance of the receiver.

OSImmediate protocolsThis section describes the protocols supported by OSImmediate.

Instance methods= Answer a Boolean indicating whether the receiver and anOSObject are

equal. Two immediates are equal if they have the same class and equalvalues.

asIntegerAttempt to coerce the receiver’s value to an integer.

indirectionLevelAnswer the receiver’s indirection level.

isImmediateAnswer true if the receiver represents an immediate data element.

isNull Answer true if the receiver is a NULL value.

notNullAnswer true if the receiver is not a NULL value.

310 IBM Smalltalk: Programmer’s Reference

Page 325: IBM Smalltalk: Programmer's Reference

value Answer the receiver’s immediate data coerced into the most appropriateSmalltalk class, as defined by the particular OSObject subclass. Forimmediates, this is always an unsigned integer.

Class methodsimmediate:

Answer a new instance of the receiver with indirection level 0, referencinga data element with the same value as the parameter.

new Answer a new instance of the receiver with indirection level 0, referencing0.

value: Same as immediate:.

OSBaseType, OSObjectPointer, and OSStructure protocolsThis section describes the protocols supported by OSBaseType, OSObjectPointer, andOSStructure.

Instance methods: pointer arithmetic+ Answer a new instance of the receiver, with the same indirection level,

pointing to the data element at index anInteger from the data elementreferenced by the receiver.

- Answer a new instance of the receiver, with the same indirection level,pointing to the data element at index anInteger before the data elementreferenced by the receiver.

decrementDecrease the pointer by one to point to the previous data element.

decrementBy:Decrease the pointer by anInteger to point to the previous data element.

incrementIncrease the pointer by one to point to the next data element.

incrementBy:Increase the pointer by anInteger to point to the next data element.

Instance methods: low-level storage accessThese methods enable you to access the contents of an OSBaseType, OSStructure, orOSObjectPointer. All offsets are zero-relative. Accessing non-aligned addresses isvalid but might be slower on processors that do not directly support this style ofaccess.

address Answer the operating system memory address of the start of the dataelement referenced by the receiver. This message is invalid for objectswhose data element is stored in Smalltalk memory.

bool16At: anIntegerAnswer the 16-bit Boolean at byte offset anInteger from the start of thestorage area referenced by the receiver.

bool16At: anInteger put: aValueSet the 16-bit Boolean at byte offset anInteger from the start of the storagearea referenced by the receiver to the integer value of aValue. aValue maybe nil, true, false, an Integer, a Character, or an OSObject. aValue is convertedusing the same rules as the pointer call-out conversion. There is oneexception—instances are not allowed of OSObject that point to Smalltalkmemory that is not fixed.

Chapter 11. IBM Smalltalk Virtual Machine API 311

Page 326: IBM Smalltalk: Programmer's Reference

bool32At: anIntegerAnswer the 32-bit Boolean at byte offset anInteger from the start of thestorage area referenced by the receiver.

bool32At: anInteger put: aValueSet the 32-bit Boolean at byte offset anInteger from the start of the storagearea referenced by the receiver to the integer value of aValue. aValue maybe nil, true, false, an Integer, a Character, or an OSObject. aValue is convertedusing the same rules as the pointer call-out conversion. There is oneexception—instances are not allowed of OSObject that point to Smalltalkmemory that is not fixed.

bool8At: anIntegerAnswer the 8-bit Boolean at byte offset anInteger from the start of thestorage area referenced by the receiver.

bool8At: anInteger put: aValueSet the 8-bit Boolean at byte offset anInteger from the start of the storagearea referenced by the receiver to the integer value of aValue. aValue mightbe nil, true, false, an Integer, a Character, or an OSObject. aValue is convertedusing the same rules as the pointer call-out conversion. There is oneexception—instances are not allowed of OSObject that point to Smalltalkmemory that is not fixed.

char16At: anIntegerSimilar to bool16At:.

char16At anInteger put: aValueSimilar to bool16At:put:.

char8At: anIntegerSimilar to bool8At:.

char8At anInteger put: aValueSimilar to bool8At:put:.

float32At: anIntegerAnswer an instance of Float representing the 32-bit floating-point value atbyte offset anInteger from the start of the storage area referenced by thereceiver.

float32At: anInteger put: aValueSet the 32-bit floating-point value at byte offset anInteger from the start ofthe storage area referenced by the receiver to aValue. aValue must be aninstance of Float.

float64At: anIntegerAnswer an instance of Float representing the 64-bit floating-point value atbyte offset anInteger from the start of the storage area referenced by thereceiver.

float64At: anInteger put: aValueSet the 64-bit floating-point value at byte offset anInteger from the start ofthe storage area referenced by the receiver to aValue. aValue must be aninstance of Float.

int16At: anIntegerSimilar to bool16At:.

int16At anInteger put: aValueSimilar to bool16At:put:.

312 IBM Smalltalk: Programmer’s Reference

Page 327: IBM Smalltalk: Programmer's Reference

int32At: anIntegerSimilar to bool32At:.

int32At anInteger put: aValueSimilar to bool32At:put:.

int64At: anIntegerAnswer the 64-bit Integer at byte offset anInteger from the start of thestorage area referenced by the receiver.

int64At anInteger put: aValueSet the 64-bit Integer at byte offset anInteger from the start of the storagearea referenced by the receiver to the integer value of aValue. aValue maybe nil, true, false, an Integer, a Character, or an OSObject. aValue is convertedusing the same rules as the pointer call-out conversion. There is oneexception—instances are not allowed of OSObject that point to Smalltalkmemory that is not fixed.

int8At: anIntegerSimilar to bool8At:.

int8At anInteger put: aValueSimilar to bool8At:put:.

pointerAt: anInteger type: anOSObjectSubclassCreate and answer a new struct instance of anOSObjectSubclass that pointsto the storage of the receiver starting at anInteger. An error is signaled ifanInteger is less than anOSObjectSubclass fixedSize bytes from the end of thereceiver’s storage.

referenceAnswer the Smalltalk memory referenced by the receiver. This message isinvalid for objects whose data element is stored in operating systemmemory.

structAt: anInteger type: anOSObjectSubclassCreate and answer a new struct instance of anOSObjectSubclass and copiesenough bytes to fill it from the receiver starting at anInteger. An error issignaled if anInteger is less than anOSObjectSubclass fixedSize bytes from theend of the receiver’s storage.

structAt: anInteger put: anOSObjectCopy the storage referenced by anOSObject over the storage for the receiverstarting at anInteger. An error is signaled if anInteger is less than anOSObjectclass fixedSize bytes from the end of the receiver’s storage.

memcpyFrom: start to: stopAnswer a ByteArray containing a copy of the bytes pointed to by thereceiver from byte offset start up to and including byte offset stop.

memcpyStringFrom: start to: stopAnswer a String containing a copy of the bytes pointed to by the receiverfrom byte offset start up to and including byte offset stop.

memcpyFrom: start to: stop into: anOSOrBitObject startingAt: repStartCopy bytes from byte offset start in the receiver up to and including byteoffset stop into anOSOrBitObject starting at byte index repStart. AnsweranOSOrBitObject. anOSOrBitObject might be a byte, word, or long object, oran OSObject.

uint16At: anIntegerSimilar to bool16At:.

Chapter 11. IBM Smalltalk Virtual Machine API 313

Page 328: IBM Smalltalk: Programmer's Reference

uint16At anInteger put: aValueSimilar to bool16At:put:.

uint32At: anIntegerSimilar to bool32At:.

uint32At anInteger put: aValueSimilar to bool32At:put:.

uint64At: anIntegerSimilar to int64At:.

uint64At anInteger put: aValueSimilar to int64At:put:.

int8At: anIntegerSimilar to bool8At:.

int8At anInteger put: aValueSimilar to bool8At:put:.

Instance methods: freeingfree Free the storage for the receiver. If the receiver does not represent a pointer

to operating system memory, do nothing.

Instance methods: testing= Answer a Boolean indicating whether the receiver and anOSObject are

equal. Two instances of OSObject are considered to be equal if theyrepresent the identical storage in operating system or Smalltalk memory.

memcmpFrom: start to: stop with: anOSOrBitObject startingAt: repStartCompare the bytes in the receiver from offset start to stop with the bytes inaCollection starting at repStart. If the bytes are all equal, answer 0. If thebytes are not all equal, the result is based on the first bytes that are notequal. If the byte from the receiver is less than the byte from aCollection,answer -1. If the byte from the receiver is greater than the byte fromaCollection, answer 1. anOSOrBitObject might be a byte, word, or longobject, or an OSObject.

isImmediateAnswer true if the receiver is an immediate.

isAddressAnswer true if the receiver represents a pointer to operating systemmemory.

isNull Answer true if the receiver is a NULL value; that is, if the receiver is apointer to location 0 in memory.

isAddressAnswer true if the receiver represents a pointer to Smalltalk memory.

notNullAnswer true if the receiver is not a NULL value.

Class methods: instance creationaddress: anInteger

Answer a new instance of the receiver referring to operating systemmemory at address anInteger.

calloc Answer a new instance of the receiver referring to storage in operatingsystem memory large enough to hold the fixedSize of the receiver in bytes.

314 IBM Smalltalk: Programmer’s Reference

Page 329: IBM Smalltalk: Programmer's Reference

alloc: anIntegerAnswer a new instance of the receiver referring to storage in operatingsystem memory large enough to hold anInteger times the fixedSize of thereceiver in bytes.

new Answer a new instance of the receiver referring to Smalltalk storage largeenough to hold the fixedSize of the receiver in bytes.

reference: aByteArrayAnswer a new instance of the receiver referring to the start of aByteArray.

OSStructure protocolsThis section describes the protocols supported by OSStructure.

Instance methods: testingequals: anOSObject

Answers a Boolean indicating whether the data element referenced by thereceiver and the data element referenced by anOSObject are equal. Thereceiver and anObject must be of the same class, have the same indirectionlevel, and the data elements they reference must contain the same data, inthe same sequence by byte comparison.

indirectionLevelAnswer the receiver’s indirection level.

OSVariableStructure protocols

Class methods: initializationvariableSize

Answer an Integer that is the size in bytes of one data element of thevariable portion of the receiver.

variableSize: anIntegerSet an Integer that is the size in bytes of one data element of the variableportion of the receiver. This value must be set before using an instance ofthe receiver.

Class methods: instance creationcallocVariable: anInteger

Answer a new instance of the receiver referring to storage in operatingsystem memory large enough to hold the fixedSize of the receiver plusanInteger times the variableSize of the receiver in bytes.

newVariable: anIntegerAnswer a new instance of the receiver referring to storage in Smalltalkmemory large enough to hold the fixedSize of the receiver plus anIntegertimes the variableSize of the receiver in bytes.

OSBaseType protocolsat: anInteger

Answer the data element at index anInteger from the data elementreferenced by the receiver. Indexing is done in terms of data elements, notbytes. Subclasses of OSBaseType override this method to return theappropriate Smalltalk base type (for example, OSBool16 returns a boolean).

at: anInteger put: anOSObjectSet the data element at index anInteger in the data element referenced by

Chapter 11. IBM Smalltalk Virtual Machine API 315

Page 330: IBM Smalltalk: Programmer's Reference

the receiver. Indexing is done in terms of data elements, not bytes.Subclasses of OSBaseType override this method to set the appropriateSmalltalk base type (for example, OSBool16 sets a 16-bit boolean).

indirectionLevelAnswer the receiver’s indirection level.

ObjectPointer protocols

Class methods: initializationdefaultItemType

Answer the default item type for new instances of the receiver. When notspecified, instances of the receiver point to items of this class.

defaultItemType: anOSObjectSubclassSet the default item type for new instances of the receiver. When notspecified, instances of the receiver point to items of this class.

Class methods: instance creationaddress: addressInteger itemType: anOSObjectSubclass

Answer a new instance of the receiver with indirection level 2, initializedto reference the operating system pointer to a data element described byanOSObjectSubclass, at an address equal to addressInteger.

address: addressInteger itemType: anOSObjectSubclass indirectionLevel: indirectionLevelAnswer a new instance of the receiver with the specified indirection level,initialized to reference the operating system pointer, at an address equal toaddressInteger.

calloc: anInteger itemType: anOSObjectSubclassAllocate operating system memory large enough to contain anIntegeroperating system pointers. Answer a new instance of the receiver withindirection level 2, initialized to reference the operating system pointer to adata element described by anOSObjectSubclass, in the allocated operatingsystem memory.

calloc: anInteger itemType: anOSObjectSubclass indirectionLevel: indirectionLevelAllocate operating system memory large enough to contain anIntegeroperating system pointers. Answer a new instance of the receiver with thespecified indirection level, initialized to reference the operating systempointer, in the allocated operating system memory.

itemType: anOSObjectSubclassAllocate Smalltalk memory large enough to contain one operating systempointer. Answer a new instance of the receiver with indirection level 2,initialized to reference the operating system pointer to a data elementdescribed by the default item type, in the allocated operating systemmemory.

itemType: anOSObjectSubclass indirectionLevel: indirectionLevelAllocate Smalltalk memory large enough to contain one operating systempointer. Answer a new instance of the receiver with the specifiedindirection level, initialized to reference the operating system pointer to adata element described by the default item type, in the allocated operatingsystem memory.

new: anInteger itemType: anOSObjectSubclassAllocate Smalltalk memory large enough to contain anInteger operatingsystem pointers. Answer a new instance of the receiver with indirection

316 IBM Smalltalk: Programmer’s Reference

Page 331: IBM Smalltalk: Programmer's Reference

level 2, initialized to reference the operating system pointer to a dataelement described by anOSObjectSubclass.

new: anInteger itemType: anOSObjectSubclass indirectionLevel: indirectionLevelAllocate operating system memory large enough to contain anIntegeroperating system pointers. Answer a new instance of the receiver with thespecified indirection level, initialized to reference the operating systempointer to a data element described by anOSObjectSubclass.

reference: aByteObject itemType: anOSObjectSubclassAnswer a new instance of the receiver with indirection level 2, initializedto reference aByteObject that contains operating system pointers to dataelements described by anOSObjectSubclass.

reference: addressInteger itemType: anOSObjectSubclass indirectionLevel: indirectionLevelAnswer a new instance of the receiver with the specified indirection level,initialized to reference aByteObject that contains operating system pointersto data elements described by anOSObjectSubclass.

Instance methods: accessingat: anInteger

Answer the data element at index anInteger from the data elementreferenced by the receiver. Indexing is done in terms of operating systempointers, not bytes. If the receiver’s indirection level is 2, the value must bean instance of the receiver’s itemType with indirection level 1. If thereceiver’s indirection level is greater than 2, the value must be an instanceof the receiver, with indirection one less than the receiver, and having thesame itemType.

at: anInteger put: anOSObjectSet the data element at index anInteger in the data element referenced bythe receiver. Indexing is done in terms of operating system pointers, notbytes. If the receiver’s indirection level is 2, the value must be an instanceof the receiver’s itemType with indirection level 1. If the receiver’sindirection level is greater than 2, the value must be an instance of thereceiver, with indirection one less than the receiver, and having the sameitemType.

indirectionLevelAnswer the receiver’s indirection level. The indirection level is defined asthe number of pointer dereferences required to reach the data elementdescribed by the receiver.

itemTypeAnswer an instance of the receiver with indirection level 2, initialized toreference aByteObject that contains operating system pointers to dataelements described by anOSObjectSubclass.

Methods available in other classesThe following instance methods are also available in ByteArray, String, andDBString. They function exactly like the OSObject methods. All use zero-basedindexing.

int8At:int8At:put:int16At:int16At:put:int32At:int32At:put:

Chapter 11. IBM Smalltalk Virtual Machine API 317

Page 332: IBM Smalltalk: Programmer's Reference

int64At:int64At:put:int8At:uint8At:put:uint16At:uint16At:put:uint32At:uint32At:put:uint64At:uint64At:put:memcpyFrom:to:memcpyStringFrom:to:memcpyfrom:to:into:startingAt:memcmpFrom:to:with:startingAt:

User primitivesIBM Smalltalk supports three syntaxes for user primitives:messagePattern

<primitive: primitiveName>...fail code...

messagePattern<primitive: 'sharedLibrary':functionName>...fail code...

messagePattern<primitive: 'sharedLibrary':functionNumber>...fail code...

The first syntax looks up the primitive in the user primitive table. primitiveName isan alphanumeric identifier. It is not surrounded by quotation marks. For example:add: a and: b

<primitive: add2Numbers>|self primitiveFailed

The other two syntaxes look up a user primitive function in a shared library, eitherby name or by number. The sharedLibrary, functionName, and functionNumber fieldshave the same syntax and function as those in a PlatformFunction. sharedLibrarymust be surrounded by quotes. functionName has no quotes. For example:myFunc: arg1

<primitive: 'MYLIB':myFunc>|self primitiveFailed

The user primitive acts the same way whether it is in the user primitive table or ina shared library. If the primitive succeeds, the object returned from the primitive isreturned from the method. If the primitive fails, the fail code (the rest of the codein the method) is run. If no fail code is provided, self is returned on primitivefailure. The suggested default fail code is |self primitiveFailed. It generates awalkback describing the reason for the failure.

In C, a user primitive function is defined as:EsUserPrimitive(functionName){

...your code...}

Within the primitive, the following are defined:

318 IBM Smalltalk: Programmer’s Reference

Page 333: IBM Smalltalk: Programmer's Reference

EsPrimVMContextWherever a vmContext parameter is required when calling a function, passthis value.

EsPrimReceiverThe receiver of the primitive method. It has type EsObject.

EsPrimArgumentCountThe number of arguments (not including the receiver) that were passed tothe primitive method.

EsPrimArgument(n)The nth argument (an EsObject) of the primitive method. The value of n isnot validated.

If the primitive fails, use EsPrimFail(errorCode, argumentNumber). errorCode. isone of the EsPrimErr values defined in Table 39 on page 336. argumentNumber is theindex of the argument in which the error occurred. If the error occurred in thereceiver, use EsPrimArgNumSelf. If the error occurred in no particular argument (forexample, an EsAllocateObject failed), use EsPrimArgNumNoArg. EsPrimFail returnsfrom the user primitive function.

If the primitive succeeds, use EsPrimSucceed(returnObject). returnObject must bean EsObject. EsPrimSucceed returns from the user primitive function.

User primitive tablesSome IBM Smalltalk platforms require user primitives to be statically linked withthe virtual machine. Others require that all user primitives be placed in an externalshared library. See “Platform requirements” on page 333 for details about yourplatform. In either case, user primitives are defined in the same way.

Platforms that require user primitives to be in an external shared library do nothave user primitive tables. All user primitive functions must be public (exported)from the shared library. The name of the user primitive function must exactlymatch the name used in the Smalltalk primitive declaration or PlatformFunctionfunction field.

For platforms that require static linking, all user primitives are accessed by thevirtual machine through the user primitive table, EsUserPrimitiveTable.

The file userprim.c contains an empty user primitive table. To add user primitives,modify the file to include new primitives. For example:EsDefinePrimitiveTable(EsUserPrimitiveTable)EsPrimitiveTableEntry("nameFromSmalltalk", function)

...EsEndPrimitiveTable

nameFromSmalltalk is the exact (case sensitive) name that the Smalltalk userprimitive used in the <primitive: > statement.

See the sections at the end of this chapter for platform-specific examples ofbuilding a new user primitive table.

To allow multifile user primitives, tables can be nested, as follows:/* userprim.c */extern EsPrimitiveTable file1Table; /* prims from file1.c */extern EsPrimitiveTable file2Table;EsDefineUserPrimitive(function)

Chapter 11. IBM Smalltalk Virtual Machine API 319

Page 334: IBM Smalltalk: Programmer's Reference

{...

}

EsDefinePrimitiveTable(EsUserPrimitiveTable)EsPrimitiveTableEntry("nameFromSmalltalk", function)EsSubTable(file1Table)EsSubTable(file2Table)...

EsEndPrimitiveTable

/* file1.c */

EsDefinePrimitiveTable(file1Table)EsPrimitiveTableEntry("nameFromSmalltalk", function)...

EsEndPrimitiveTable

Primitive tables have type EsPrimitiveTable.

Functions available in user primitivesThis section defines the functions available in user primitives:v Object allocationv Sending messagesv Testing objectsv Converting Smalltalk objects to C valuesv Converting C values to Smalltalk objectsv Accessing objectsv Protecting objects from garbage collectionv Miscellaneous

Object allocationThese functions enable users to allocate new objects from within a user primitive.

EsObject EsAllocateObject(EsVMContext vmContext, EsBehavior allocateClass,U_32 size, U_32 saves, EsObject ** saveList)

Returns a new, initialized object of class allocateClass with size indexableinstance variables. Pass 0 for saves and NULL for saveList. The instancevariables of pointer objects are initialized to nil. All other objects areinitialized to 0.

Error cases: If the object could not be allocated for any reason, returnsNULL.

Smalltalk equivalent: allocateClass new: size

Side effects: This operation can cause a garbage collection.

EsObject EsAllocateFixedObject(EsVMContext vmContext, EsBehaviorallocateClass, U_32 size, U_32 saves, EsObject ** saveList)

Same as EsAllocateObject, except the object is allocated in fixed space.This means that the object does not move during a garbage collect.

Error cases: If the object could not be allocated for any reason, returnsNULL.

Smalltalk equivalent: (allocateClass new: size) makeFixed

Sending messagesThis function enables users to send a message from within a user primitive andretrieve the result.

320 IBM Smalltalk: Programmer’s Reference

Page 335: IBM Smalltalk: Programmer's Reference

U_32 EsSendMessage(EsVMContext vmContext, EsObject * returnObject, EsObjectreceiver, EsObject selector, U_32 argumentCount, ...)

Calls back into the IBM Smalltalk interpreter by sending a message.returnObject is a pointer to an EsObject where the return value of themessage is placed. argumentCount can be from 0 to 255.

Error cases: Returns an EsPrimErr code.

Side effects: This operation can cause a garbage collection.

Testing objectsThese functions enable users to determine what the class and type (immediate,bytes, words, longs, or pointers) of an object are.

EsBehavior EsObjectClass(EsObject object)Returns the class of object. The generic return type of EsBehavior is usedbecause the class of object can be a Class or Metaclass.

Smalltalk equivalent: object class

BOOLEAN EsIsImmediate(EsObject object)Returns TRUE or FALSE, indicating whether or not object is immediate.

BOOLEAN EsIsSmallInteger(EsObject object)Returns TRUE or FALSE, indicating whether or not object is a smallInteger.

BOOLEAN EsIsCharacter(EsObject object)Returns TRUE or FALSE, indicating whether or not object is a character.

BOOLEAN EsIsNil(EsObject object)Returns TRUE or FALSE, indicating whether or not object is nil.

BOOLEAN EsIsTrue(EsObject object)Returns TRUE or FALSE, indicating whether or not object is true.

BOOLEAN EsIsFalse(EsObject object)Returns TRUE or FALSE, indicating whether or not object is false.

BOOLEAN EsIsBoolean(EsObject object)Returns TRUE or FALSE, indicating whether or not object is true or false.

BOOLEAN EsIsLargeInteger(EsObject object)Returns TRUE or FALSE, indicating whether or not object is a largeInteger.

BOOLEAN EsIsFloat(EsObject object)Returns TRUE or FALSE, indicating whether or not object is a Float.

BOOLEAN EsIsBytes(EsObject object)Returns TRUE or FALSE, indicating whether or not the instance variables ofobject contain bytes.

BOOLEAN EsIsWords(EsObject object)Returns TRUE or FALSE, indicating whether or not the instance variables ofobject contain words.

BOOLEAN EsIsLongs(EsObject object)Returns TRUE or FALSE, indicating whether or not the instance variables ofobject contain longs.

BOOLEAN EsIsPointers(EsObject object)Returns TRUE or FALSE, indicating whether or not the instance variables ofobject contain pointers.

Chapter 11. IBM Smalltalk Virtual Machine API 321

Page 336: IBM Smalltalk: Programmer's Reference

BOOLEAN EsIsIndexable(EsObject object)Returns TRUE or FALSE, indicating whether or not object has numberedinstance variables.

BOOLEAN EsIsReadOnly(EsObject object)Returns TRUE or FALSE, indicating whether or not object is read-only.

BOOLEAN EsIsCharacters(EsObject object)Returns TRUE or FALSE, indicating whether or not object contains instancesof Character. If this returns TRUE, object will be a byte or word object.

Converting Smalltalk objects to C valuesThese functions enable users to convert Smalltalk objects into C values forprocessing in a user primitive.

I_32 EsSmallIntegerToI32(EsObject smallInteger)Returns the signed 32-bit value of smallInteger.

Error cases: smallInteger is assumed to be a smallInteger.

char EsCharacterToChar(EsObject character)Returns the char value of character.

Error cases: character is assumed to be a character. Some IBM Smalltalkcharacters will not fit in a char. The return value in this case is unspecified.

U_16 EsCharacterToU16(EsObject character)Returns the U_16 value of character.

Error cases: character is assumed to be a character.

U_32 EsIntegerToI32(EsObject object, I_32 * value)Converts object to a C signed 32-bit Integer and stores the result in thelocation pointed to by value. Returns an EsPrimErr code. If the returnvalue is EsPrimErrNoError then *value is valid. Otherwise, *value isinvalid.

Error cases: An error occurs if object is not a smallInteger or largeInteger.An error occurs if the value of the number cannot fit in 32 bits signed.

U_32 EsIntegerToU32(EsObject object, U_32 * value)Converts object to a C unsigned 32-bit integer and stores the result in thelocation pointed to by value. Returns an EsPrimErr code. If the returnvalue is EsPrimErrNoError then *value is valid. Otherwise, *value isinvalid.

Error cases: An error occurs if object is not a smallInteger or largeInteger.An error occurs if the value of the number cannot fit in 32 bits unsigned.

U_32 EsFloatToCDouble(EsObject object, double * value)Converts object to a C double and stores the result in the location pointedto by value. Returns an EsPrimErr code. If the return value isEsPrimErrNoError then *value is valid. Otherwise, *value is invalid.

Error cases: An error occurs if object is not a Float.

Converting C values to Smalltalk objectsThese functions enable users to convert C values into their corresponding objectsfor returning to Smalltalk.

EsObject EsI32ToSmallInteger(I_32 value)Converts value (a signed number) to an IBM Smalltalk smallInteger andreturns it.

322 IBM Smalltalk: Programmer’s Reference

Page 337: IBM Smalltalk: Programmer's Reference

Error cases: Not all signed 32-bit values can fit in a smallInteger. No rangecheck is done on value. Use EsI32ToInteger or EsU32ToInteger if you arenot certain that value fits.

EsObject EsCharToCharacter(char character)Converts character to an IBM Smalltalk character and returns it.

EsObject EsU16ToCharacter(U_16 value)Converts value to the corresponding IBM Smalltalk character and returnsit.

U_32 EsI32ToInteger(I_32 value, EsObject * object)Converts value (a signed number) into an integer and stores the result inthe location pointed to by object. Returns an EsPrimErr code. If the returnvalue is EsPrimErrNoError then *object is valid. Otherwise, *object isinvalid.

Error cases: An error occurs if the new integer object cannot be allocated.

Side effects: This operation can cause a garbage collection.

U_32 EsU32ToInteger(U_32 value, EsObject * object)Converts value (an unsigned number) into an integer and stores the resultin the location pointed to by object. Returns an EsPrimErr code. If thereturn value is EsPrimErrNoError then *object is valid. Otherwise, *objectis invalid.

Error cases: An error occurs if the new integer object cannot be allocated.

Side effects: This operation can cause a garbage collection.

U_32 EsCDoubleToFloat(double value, EsObject * object)Converts value into a Float and stores the result in the location pointed toby object. Returns an EsPrimErr code. If the return value isEsPrimErrNoError then *object is valid. Otherwise, *object is invalid.

Error cases: An error occurs if the new Float object cannot be allocated.

Side effects: This operation can cause a garbage collection.

Accessing objectsThese functions enable users to access the instance variables of an object. For all ofthe following functions that use an instance variable index, the first instancevariable is numbered 1.

U_32 EsInstSize(EsObject object)Returns the number of named instance variables in object.

Smalltalk equivalent: object class instSize

U_32 EsBasicHash(EsObject object)Returns the basic hash of the object.

Smalltalk equivalent: object basicHash

U_32 EsBasicSize(EsObject object)Returns the number of indexed instance variables in object.

Smalltalk equivalent: object basicSize

U_32 * EsInstVarAddr(EsObject object)Answers the address of the first instance variable of object. The resultvalue is cast to U_32 * regardless of the type of object.

Error cases: Assumes that object consists of not immediate.

Chapter 11. IBM Smalltalk Virtual Machine API 323

Page 338: IBM Smalltalk: Programmer's Reference

EsObject EsInstVarAt(EsObject object, U_32 index)Returns instance variable index of object. Allows access of named andindexed instance variables; that is, index 1 is the first named instancevariable, if object has any.

Error cases: Assumes that object consists of pointers. index is notvalidated.

Smalltalk equivalent: object instVarAt: index

void EsInstVarAtPut(EsObject object, U_32 index, EsObject storedObject)Stores storedObject into instance variable index of object. Allows accessof named and indexed instance variables; that is, index 1 is the first namedinstance variable, if object has any.

Error cases: Assumes that object consists of pointers. index is notvalidated. Stores into read-only objects are not checked.

Smalltalk equivalent: object instVarAt: index put: storedObject

EsObject EsAt(EsObject object, U_32 index)Returns indexed instance variable index of object. Does not allow accessof named instance variables.

Error cases: Assumes that object consists of pointers and is indexable.index is not validated.

Smalltalk equivalent: object basicAt: index

void EsAtPut(EsObject object, U_32 index, EsObject storedObject)Stores storedObject into indexed instance variable index of object. Doesnot allow access of named instance variables.

Error cases: Assumes that object consists of pointers and is indexable.index is not validated. Stores into read-only objects are not checked.

Smalltalk equivalent: object basicAt: index put: storedObject

U_8 EsByteAt(EsObject object, U_32 index), U_8 EsU8At(EsObject object, U_32index) Returns the unsigned byte in indexed instance variable index of object.

Error cases: Assumes that object consists of bytes. index is not validated.

Smalltalk equivalent: object basicAt: index

void EsByteAtPut(EsObject object, U_32 index, U_8 value), voidEsU8AtPut(EsObject object, U_32 index, U_8 value)

Stores value into indexed instance variable index of object.

Error cases: Assumes that object consists of bytes. index is not validated.Stores into read-only objects are not checked.

Smalltalk equivalent: object basicAt: index put: value

U_16 EsWordAt(EsObject object, U_32 index), U_16 EsU16At(EsObject object,U_32 index)

Returns the unsigned word in indexed instance variable index of object.

Error cases: Assumes that object consists of words. index is not validated.

Smalltalk equivalent: object basicAt: index

void EsWordAtPut(EsObject object, U_32 index, U_16 value), voidEsU16AtPut(EsObject object, U_32 index, U_16 value)

Stores value into indexed instance variable index of object.

324 IBM Smalltalk: Programmer’s Reference

Page 339: IBM Smalltalk: Programmer's Reference

Error cases: Assumes that object consists of words. index is not validated.Stores into read-only objects are not checked.

Smalltalk equivalent: object basicAt: index put: value

U_32 EsLongAt(EsObject object, U_32 index), U_32 EsU32At(EsObject object,U_32 index)

Returns the unsigned long in indexed instance variable index of object.

Error cases: Assumes that object consists of longs. index is not validated.

Smalltalk equivalent: object basicAt: index

void EsLongAtPut(EsObject object, U_32 index, U_32 value), voidEsU32AtPut(EsObject object, U_32 index, U_32 value)

Stores value into indexed instance variable index of object.

Error cases: Assumes that object consists of longs. index is not validated.Stores into read-only objects are not checked.

Smalltalk equivalent: object basicAt: index put: value

I_8 EsSignedByteAt(EsObject object, U_32 index), I_8 EsI8At(EsObjectobject, U_32 index)

Returns the signed byte in indexed instance variable index of object.

Error cases: Assumes that object consists of bytes. index is not validated.

Smalltalk equivalent: object basicAt: index

void EsSignedByteAtPut(EsObject object, U_32 index, I_8 value), voidEsI8AtPut(EsObject object, U_32 index, I_8 value)

Stores value into indexed instance variable index of object.

Error cases: Assumes that object consists of bytes. index is not validated.Stores into read-only objects are not checked.

Smalltalk equivalent: object basicAt: index put: value

I_16 EsSignedWordAt(EsObject object, U_32 index), I_16 EsI16At(EsObjectobject, U_32 index)

Returns the signed word in indexed instance variable index of object.

Error cases: Assumes that object consists of words. index is not validated.

Smalltalk equivalent: object basicAt: index

void EsSignedWordAtPut(EsObject object, U_32 index, U_16 value), voidEsI16AtPut(EsObject object, U_32 index, U_16 value)

Stores value into indexed instance variable index of object.

Error cases: Assumes that object consists of words. index is not validated.Stores into read-only objects are not checked.

Smalltalk equivalent: object basicAt: index put: value

I_32 EsSignedLongAt(EsObject object, U_32 index), I_32 EsI32At(EsObjectobject, U_32 index)

Returns the signed long in indexed instance variable index of object.

Error cases: Assumes that object consists of longs. index is not validated.

Smalltalk equivalent: object basicAt: index

void EsSignedLongAtPut(EsObject object, U_32 index, I_32 value), voidEsI32AtPut(EsObject object, U_32 index, I_32 value)

Stores value into indexed instance variable index of object.

Chapter 11. IBM Smalltalk Virtual Machine API 325

Page 340: IBM Smalltalk: Programmer's Reference

Error cases: Assumes that object consists of longs. index is not validated.Stores into read-only objects are not checked.

Smalltalk equivalent: object basicAt: index put: value

Protecting objects from garbage collectionWhenever an object is allocated, a garbage collection might be required. If thishappens, all non-immediate object pointers stored in user primitive variables areinvalidated. If new objects are allocated in user primitives, they must be explicitlyprotected from garbage collection using the EsSaveObject / EsRestoreObjectprotocol.

Each object that is referenced only by the user primitive variables must be savedbefore any operation that could cause a garbage collection. After that operationcompletes, the objects must be restored in the reverse order from that in which theywere saved. All saved objects must be restored before the user primitive succeedsor fails.

void EsSaveObject(EsObject object)Pushes object onto the Smalltalk stack so that it is protected from agarbage collection.

EsObject EsRestoreObject(void)Pops the object on the top of the Smalltalk stack and returns it.

MiscellaneousThe virtual machine provides the following miscellaneous functions.

void EsRememberObjectStore(EsVMContext vmContext, EsObject targetObject,EsObject storedObject)

Must be called whenever an object is stored into an instance variable of apointer object.

For example,EsObject myObject;EsObject storedObject;EsObject * instVar;instVar = (EsObject *) EsInstVarAddr(myObject);*instVar = storedObject;EsRememberObjectStore(EsPrimVMContext, myObject, storedObject);

Note: EsAtPut and EsInstVarAtPut automatically call this function.

U_32 EsVMVersion(void)Returns the major and minor version numbers of the running virtualmachine. To extract the major and minor version numbers from the returnvalue:

U_32 versionNumber;U_16 versionMajor;U_16 versionMinor;

versionNumber = EsVMVersion();versionMajor = versionNumber >> 16;versionMinor = versionNumber & 0xFFFF;

The minor version number should be interpreted as a two-digit decimalnumber. For example, version 1.21 of the interpreter has minor version 21.Version 1.3 has minor version 30. Both have a major version of 1.

void EsScavenge(EsVMContext vmContext, U_32 bytesRequired)Causes the scavenger (a part of the garbage collector) to run once.

326 IBM Smalltalk: Programmer’s Reference

Page 341: IBM Smalltalk: Programmer's Reference

Smalltalk equivalent: System scavenge

void EsGGC(EsVMContext vmContext, U_32 bytesRequired)Causes the global garbage collector to run once.

Smalltalk equivalent: System globalGarbageCollect

Classes Available during User PrimitivesThe following classes (all of type EsBehavior) are available during a user primitive:v EsPrimClassSmallIntegerv EsPrimClassTruev EsPrimClassFalsev EsPrimClassUndefinedObjectv EsPrimClassCharacterv EsPrimClassStringv EsPrimClassArrayv EsPrimClassByteArrayv EsPrimClassFloatv EsPrimClassLargeIntegerv EsPrimClassDBString

Asynchronous messages (interrupts)Interrupt handlers cannot send messages (using EsSendMessage) to the IBMSmalltalk interpreter at arbitrary times. Interrupt-time messages must be queuedfor later processing when the virtual machine has regained control of the system.At certain checkpoints, the virtual machine polls the asynchronous message queueand sends any pending messages.

Because an interrupt handler could become active at any time (for example, whenthe virtual machine is garbage collecting), normal objects cannot be used inasynchronous messages. To support this, IBM Smalltalk allows objects to becomefixed, meaning that they do not move during a garbage collection.

When posting an asynchronous message, the receiver, selector, and any argumentsmust all be fixed objects. In Smalltalk, send makeFixed to all objects that will beused from interrupt handlers. After all of the objects are fixed, install the interrupthandler (for example, with a user primitive that takes the fixed receiver, selector,and arguments as parameters).

void EsPostNMI(EsVMContext vmContext)Causes nmi to be sent to the active process at the next checkpoint. Themessage is sent even if the process has asynchronous messages disabled.

BOOLEAN EsPostAsyncMessage(EsVMContext vmContext, EsObject receiver,EsObject selector, U_32 argumentCount, ...)

Queues a message for processing by the active process at the nextcheckpoint. The message is not sent if the process has asynchronousmessages disabled. All of the objects passed here must be fixed.

Error cases: If the message could not be queued for any reason, returnsFALSE. TRUE indicates successful queuing.

When running an interrupt handler, EsPrimVMContext is not defined. During theinterrupt handler installation user primitive, you must perform the following steps:ESGlobalInfo * gInfo; /* These are globals */EsObject receiver;EsObject selector;...

Chapter 11. IBM Smalltalk Virtual Machine API 327

Page 342: IBM Smalltalk: Programmer's Reference

EsUserPrimitive(installInterruptHandler){

...save receiver/selector/args...gInfo = EsPrimVMContext->globalInfo;...install handler...

}

In the interrupt handler, pass gInfo->currentVMContext as the vmContext parameterin EsPostAsyncMessage and EsPostNMI.

Do not save EsPrimVMContext in a global and use it in the handler. The savedvmContext might not remain valid for the duration of the interrupt handler. TheglobalInfo is always valid.

Using user primitive functions outside user primitivesMany of the functions described in this chapter can be used only from within auser primitive, where EsPrimVMContext is defined. In order to use these functionsfrom other places, you must set up a dummy user primitive environment in yourfunction.

You first need to store a globalInfo. (See “Asynchronous messages (interrupts)” onpage 327 for details.) Then, you can handle the following code anywhere in thelocal variable declaration section of your function:ESGlobalInfo * gInfo;myFunc(){

...Variable declarations...EsDefineUserPrimitiveEnvironment(gInfo);

...Now you can use any user primitive function...}

You cannot use EsPrimReceiver, EsPrimArgumentCount, or EsPrimArgument(n) fromwithin the dummy environment. EsPrimVMContext is defined.

This mechanism can be used only from a clean point in the virtual machine. Thevirtual machine is at a clean point when it calls a user primitive orPlatformFunction. This mechanism should not be used during an interrupt handler,because the virtual machine is not then at a clean point.

This mechanism is most useful for callbacks from the operating system. Forexample, if you were to call out (using a PlatformFunction) to the operating systemand bring a window to the front, the operating system might immediately callback asking the window to expose or paint. These messages can immediately besent to Smalltalk using EsSendMessage, because the virtual machine was at a cleanpoint when it called out to the operating system.

Sample user primitives for IBM SmalltalkUser primitives are stored in shared libraries. A shared library called sample existsin the samples\primitiv directory. (For example, for OS/2 and Microsoft Windows,the primitiv subdirectory contains sample.dll.) The name of the sample library mustbe specified in the Smalltalk primitive declarations.

sample.c contains (at least) the following:

328 IBM Smalltalk: Programmer’s Reference

Page 343: IBM Smalltalk: Programmer's Reference

#include "esuser.h"#include <string.h>

EsUserPrimitive(add2Numbers){

I_32 i1;I_32 i2;U_32 rc;EsObject retVal;

rc = EsIntegerToI32(EsPrimArgument(1), &i1);if (rc != EsPrimErrNoError)

EsPrimFail(rc, 1);rc = EsIntegerToI32(EsPrimArgument(2), &i2);if (rc != EsPrimErrNoError)

EsPrimFail(rc, 2);rc = EsI32ToInteger(i1 + i2, &retval);if (rc != EsPrimErrNoError)

EsPrimFail(rc, EsPrimArgNumNoArg);EsPrimSucceed(retVal);

}

EsObject sampleCStringToString(EsPrimVMContext, str)EsVMContext EsPrimVMContext;char * str;

{EsObject result;U_32 i, size;

size = strlen(str);result =

EsAllocateObject(EsPrimVMContext,EsPrimClassString,size,0, (EsObject **) NULL);

if (result != (EsObject) NULL)for (i = 0; i < size; ++i)

EsByteAtPut(result, i + 1, (U_8) str[i]);return result;

}

EsUserPrimitive(exampleMakeAString){

EsObject result;

result = sampleCStringToString(EsPrimVMContext,"This is a C string");

if (result == (EsObject) NULL)EsPrimFail(EsPrimErrNotEnoughMemory,

EsPrimArgNumNoArg);EsPrimSucceed(result);

}

#ifdef LINKED_USER_PRIMITIVES

EsDefinePrimitiveTable(samplePrimitiveTable)EsPrimitiveTableEntry("add2Numbers", add2Numbers)EsPrimitiveTableEntry("exampleMakeAString",

exampleMakeAString)EsEndPrimitiveTable

#endif

In Smalltalk, add the following methods to UndefinedObject:add: a and: b

<primitive: 'sample':add2Numbers>|self primitiveFailed

Chapter 11. IBM Smalltalk Virtual Machine API 329

Page 344: IBM Smalltalk: Programmer's Reference

makeAString<primitive: 'sample':exampleMakeAString>|self primitiveFailed

Now evaluate the following in a workspace (the expected result follows the --->):nil add: 54 and: 7 ---> 61nil add: 16r7FFFFFFF and: 1 ---> -2147483648 (overflow)nil add: -1 and: -2 ---> -3nil add: 1073741823 and: 1 ---> 1073741824 (LargeInteger)nil add: $a and: 2 ---> walkback "invalid class in argument 1"nil add: 0 and: 16r100000000 ---> walkback "value out of range in argument 2"nil makeAString ---> 'This is a C string'

Sample callback for OS/2 and Microsoft WindowsThe following example is the C code for the IBM Smalltalk window procedure forOS/2 and Microsoft Windows. This example demonstrates how to call back intoSmalltalk. Similar code will also work under UNIX platforms.

Note: IBM Smalltalk supports external language entry points that can be usedinstead of hand-written code. See “Entry points” on page 294.

Important points about the C code are:v The call-in is not performed from a user primitive, so the

EsDefineUserPrimitiveEnvironment macro must be used before any IBMSmalltalk API calls are made.

v The calls to EsSaveObject are necessary because the EsU32ToInteger call canresult in a garbage collection.

v The object result from EsSendMessage is a Smalltalk object, so it must beconverted back to C format before being returned.

Example callback code/* Contents: IBM Smalltalk Window Proc interface for call-in.

Comments:This file contains an implementation of the window procfor Windows and OS/2. The window proc calls into Smalltalk to processevery event received. The default window proc is calledif an error occurred during processing of the call-in.The most typical error is a walkback during call-in.

*/

#ifdef WIN32/*

Includes different header file and redefines some result valuesfor Windows.

*/

#include <windows.h>#ifndef MRESULT#define MRESULT LRESULT#endif#ifndef MPARAM#define MPARAM LPARAM#endif

#ifndef EXPENTRY#define EXPENTRY CALLBACK#endif#define WinDefWindowProc DefWindowProc#endif#ifdef OS2

330 IBM Smalltalk: Programmer’s Reference

Page 345: IBM Smalltalk: Programmer's Reference

/*Includes different header file and redefines some result valuesfor OS/2.

*/#define INCL_WININPUT#include <os2.h>#endif#include "esuser.h"

typedef struct {EsObject class;U_32 flags;U_32 size;EsObject selector;EsObject arguments;EsObject receiver;

} ESDirectedMessage;

static BOOL RecursiveError = FALSE;static BOOL PrimitiveError = FALSE;static ESGlobalInfo *GlobalInfo = 0;static ESDirectedMessage * WindowProcMessage = 0;MRESULT EXPENTRY WindowProc (HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2)

{MRESULT mresult;EsDefineUserPrimitiveEnvironment(GlobalInfo);EsObject result, objHwnd, objMsg, objMp1, objMp2;extern int EsTerminated;if (EsTerminated) {

return WinDefWindowProc (hwnd, msg, mp1, mp2);}

if (RecursiveError) {EsTTYOutputString ("\nRecursive WindProc Failure.");EsTTYOutputString ("Using WinDefProc");return WinDefWindowProc (hwnd, msg, mp1, mp2);

}

/*Converts the arguments into Smalltalk objectsThe parameters are converted into Smalltalk objects.If the values are large enough, a LargeInteger maybe created. To prevent the garbage collectionfrom reclaiming any objects created, they aresaved on the Smalltalk stack for protection from the GC.

/*PrimitiveError = FALSE;if (EsU32ToInteger ((U_32) hwnd, &objHwnd) != EsPrimErrNoError) {PrimitiveError = TRUE;

} else {EsSaveObject(objHwnd);if (EsU32ToInteger ((U_32) msg, &objMsg) != EsPrimErrNoError) {

EsRestoreObject();PrimitiveError = TRUE;

} else {

EsSaveObject(objMsg);if (EsU32ToInteger ((U_32) mp1, &objMp1) != EsPrimErrNoError) {

EsRestoreObject(); EsRestoreObject();PrimitiveError = TRUE;

} else {EsSaveObject(objMp1);if (EsU32ToInteger ((U_32) mp2, &objMp2)

!= EsPrimErrNoError){

PrimitiveError = TRUE;EsRestoreObject(); EsRestoreObject(); EsRestoreObject();

Chapter 11. IBM Smalltalk Virtual Machine API 331

Page 346: IBM Smalltalk: Programmer's Reference

} else {objMp1 = EsRestoreObject();objMsg = EsRestoreObject();objHwnd = EsRestoreObject();

}}

}}

/* Sends the message to Smalltalk via call-in if there was no error */if (PrimitiveError) {

EsTTYOutputString ("\nWindProc:EsU32ToInteger failed");EsTTYOutputString ("Using WinDefProc");RecursiveError = TRUE;mresult = WinDefWindowProc (hwnd, msg, mp1, mp2);RecursiveError = FALSE;return mresult;

} else {if (EsSendMessage(EsPrimVMContext,

&result,WindowProcMessage->receiver,WindowProcMessage->selector,4,

objHwnd, objMsg, objMp1, objMp2) != 0) {EsTTYOutputString ("\nWindProc:EsSendMessage failed.");EsTTYOutputString ("Using WinDefProc");RecursiveError = TRUE;mresult = WinDefWindowProc (hwnd, msg, mp1, mp2);RecursiveError = FALSE;return mresult;

}}

/* -2|31 to +2|31 */if (EsIntegerToI32(result, &mresult) == EsPrimErrNoError) {

return mresult;}/* 0 to 2|32 */if (EsIntegerToU32(result, &mresult) == EsPrimErrNoError) {

return mresult;}

EsTTYOutputString ("\nWindProc Failed.");EsTTYOutputString ("Result was not an Integer");return WinDefWindowProc (hwnd, msg, mp1,mp2);

}EsUserPrimitive(installWindowProc){

EsObject result;

GlobalInfo = EsPrimVMContext->globalInfo;WindowProcMessage = (ESDirectedMessage *) EsPrimArgument(1);if (EsU32ToInteger ((U_32) WindowProc, &result) != EsPrimErrNoError) {

EsPrimFail (EsPrimErrInvalidClass, 1);}EsPrimSucceed (result);

}

EsDefinePrimitiveTable(WindowProcPrimitiveTable)EsPrimitiveTableEntry("installWindowProc", installWindowProc)EsEndPrimitiveTable

Smalltalk code that uses the primitive aboveThe Smalltalk code that uses the primitive above is as follows:

332 IBM Smalltalk: Programmer’s Reference

Page 347: IBM Smalltalk: Programmer's Reference

The primitive declarationinstallWindowProc: receiver selector: selector

"Private - Answer the address of the standard window proc.Install the receiver and selector as the message that issent for every operating system message."<primitive: installWindowProc>|self primitiveFailed

Sample use of the primitiveinitializeWindowClass

"Private - Get the standard IBM Smalltalk window procedure andregister the window class in the operating system."

| address |"Get the address of the window proc and install the receiver andselector. This message is sent from the window proc for everyoperating system message."address := self

installWindowProc: self makeFixedselector: #windowProc:msg:with:with: makeFixed.

"Register the Smalltalk window procedure."

WindowClass := 'WINDOWPROC'.Hab

winRegisterClass: WindowClasspfnWndProc: addressflStyle: CsSizeredrawcbWindowData: 4.

The Smalltalk code places the receiver and selector in fixed memory so that theycannot move during garbage collection.

This code is based on the IBM Smalltalk code for the window procedure. Somechanges were made for clarity, so the code above might not match exactly the codein IBM Smalltalk.

Platform requirementsThis section describes, for each platform on which IBM Smalltalk runs, thesoftware required to write user primitives, the calling convention required forPlatformFunction calls, and any other platform-specific information.

OS/2

Required softwareThe IBM VisualAge C++ compiler, or another compatible compiler, is required towrite user primitives.

User primitivesUser primitives must be placed in a separate DLL. The DLL name must bespecified in the Smalltalk primitive declaration.

PlatformFunction calling conventionAll functions called by way of the PlatformFunction mechanism must be declaredwith the _System calling convention.

Chapter 11. IBM Smalltalk Virtual Machine API 333

Page 348: IBM Smalltalk: Programmer's Reference

Microsoft Windows 95, Windows 98, and Windows NT

Required softwareThe IBM VisualAge C++ compiler, or another compatible compiler, and theWindows Software Development Kit are required to write user primitives. The userprimitive DLLs must be created under Windows 95, Windows 98, or Windows NT.

User primitivesUser primitives must be placed in a separate DLL. The DLL name must bespecified in the Smalltalk primitive declaration.

PlatformFunction calling conventionAll 32-bit functions called using the PlatformFunction mechanism must bedeclared with the __stdcall calling convention.

Pascal16 and cdecl16 PlatformFunctionsIBM Smalltalk supports an extra PlatformFunction calling convention known aspascal16 and cdecl16 on the OS/2 and Windows platforms. This convention allowsusers to call functions in 16-bit DLLs. The creation and calling syntax is identical tothe 32-bit syntax, but the type conversions are performed differently.

16-bit PlatformFunctions convert and push char, bool, int8, int16, uint8, and uint16 as16-bit values. pointer, object, struct, int32, and uint32 are converted and pushed as32-bit values.

An example pascal16 function is:add16: num16, and32: num32

<pascal16: int32 'MYDLL16.DLL':add16and32 int16 int32>|self primitiveFailed

The equivalent C function would look like:long FAR PASCAL add16and32(num16, num32){

return(num16 + num32);}

An example cdecl16 function is:add16: num16 and32: num32

<cdecl16: int32 'MYDLL16.DLL':_add16and32 int16 int32>|self primitiveFailed

The C function would look like:long FAR _cdecl add16and32(int num16, long num32){return(num16 + num32);}

All 16-bit functions must be declared FAR and exported from their DLL.PlatformFunction objects can also be created using the pascal16 and cdecl16 callingconventions.

Note: On OS/2, all FAR PASCAL functions are exported as uppercase. The IBMSmalltalk code must use an uppercase name to refer to these functions._cdecl functions prepend an underscore to the name. The Smalltalk codemust specify the underscore when calling these functions.

334 IBM Smalltalk: Programmer’s Reference

Page 349: IBM Smalltalk: Programmer's Reference

The calling convention C16 is an alias for pascal16 and will be removed in futurereleases.

Pascal16 and cdecl16 pointer conversionIBM Smalltalk pointers are normally addressed using the linear (0:32) memorymodel. Pascal16 and cdecl16 pointers use the selector:offset (16:16) model. When apointer, safePointer, object, or struct value is used as a parameter to a pascal16 orcdecl16 function, it is automatically converted from 0:32 to 16:16. If a pointer,safePointer, or object value is returned from a pascal16 or cdecl16 function, it isautomatically converted from 16:16 to 0:32. Immediate object values and the NULLpointer (value 0) are not converted (that is, their value is the same as 0:32 or 16:16).

Two internal PlatformFunctions have been provided so that users can perform theseconversions manually, if required. They can be accessed as follows:EsSelectorOffsetToLinear := "convert 16:16 to 0:32"

PlatformFunctioncallingConvention: 'c'function: 'EsSelectorOffsetToLinear'library: nilparameterTypes: #(uint32)returnType: #uint32.

EsLinearToSelectorOffset := "convert 0:32 to 16:16"PlatformFunction

callingConvention: 'c'function: 'EsLinearToSelectorOffset'library: nilparameterTypes: #(uint32)returnType: #uint32.

Note: If a pointer value is converted from 16:16 to 0:32 and then back to 16:16(either automatically or manually), the final value will not necessarily be thesame as the original 16:16 value. It will, however, point to the same physicalmemory location. Also, the functions do not assume that their argument isan IBM Smalltalk object pointer, so they will erroneously convert immediateobject values.

These functions are also available from within user primitives. They are defined asfollows:v U_32 EsSelectorOffsetToLinear(U_32 ptr)v U_32 EsLinearToSelectorOffset(U_32 ptr)

They are available only on OS/2.

UNIX platforms

Required softwareThe C compiler supplied with the operating system is required to write userprimitives.

User primitivesUser primitives are statically linked with the virtual machine for these platforms.You can create shared libraries containing user primitives.

PlatformFunction calling conventionAll functions called using the PlatformFunction mechanism must use the standardApplication Binary Interface (ABI) for the platform. Specialized callingconventions, such as inline, are not supported.

Chapter 11. IBM Smalltalk Virtual Machine API 335

Page 350: IBM Smalltalk: Programmer's Reference

Solaris platformsOn Solaris platforms, you must use SPARCompiler 2.0 to compile user primitives.

Primitive error codesAll errors reported by IBM Smalltalk are found in the pool dictionary namedSystemPrimitiveErrors. To determine the cause of a particular error, use:SystemPrimitiveErrors keyAtValue: errorNumber

In some cases, the error reported is 18 which is OSError. This indicates that anOSError occurred during some primitive or system initialization. In the case ofimage startUp, OSError 18 indicates that reading the image file resulted in an error.

Applications can return error codes from Smalltalk using the following code:System exit: errorCode withObject: returnObject

The following error codes can be returned from the API functions or displayed in aFatal Application Error dialog box. Users can add new error codes with valuesabove EsPrimErrMinUserError.

Note: Not all of these error messages can actually appear in the Fatal ApplicationError dialog.

Table 39. User Primitive Error Codes

Error Code Value Description

EsPrimErrNoError 0 No error occurred

EsPrimErrInvalidClass 1 An object did not have the correct type(class)

EsPrimErrIndexOutOfRange 2 An index was out of range

EsPrimErrNotIndexable 3 An object that must be indexable wasnot

EsPrimErrValueOutOfRange 4 A value was out of range

EsPrimErrReadOnly 5 An object was read-only and nothingcould be stored into it

EsPrimErrSignedNotDefined 6 Signed operations are not defined foran object

EsPrimErrFPOverflow 7 Floating point overflow occurred in theprimitive

EsPrimErrFPDomainError 8 Floating point domain error

EsPrimErrFPGeneralError 9 Other floating point errors

EsPrimErrDivideByZero 10 Divide by zero attempted

EsPrimErrInvalidSize 11 An object did not have the correct size

EsPrimErrNotEnoughMemory 12 There was not enough memory toallocate an object

EsPrimErrUnknownAPIType 15

EsPrimErrUnknownConversionType 16

EsPrimErrInvalidArgCount 17 Invalid argument count to theprimitive

336 IBM Smalltalk: Programmer’s Reference

Page 351: IBM Smalltalk: Programmer's Reference

Table 39. User Primitive Error Codes (continued)

Error Code Value Description

EsPrimErrOSError 18 An operating system error occurred(for EsPrimErrOSError, return theoperating system error code in theargumentNumber field of ESPrimFail)

EsPrimErrProcessDead 19 Invalid operation for a dead process

EsPrimErrProcessActive 20 Invalid operation for the active process

EsPrimErrUnboundFunction 22 Attempt to call an unboundPlatformFunction

EsPrimErrUnimplementedPrimitive 23 Primitive is not yet implemented

EsPrimErrInvalidInCallback 24 Invalid operation in a callback into theinterpreter

EsPrimErrCannotReturn 25 Attempt to return twice from a method

EsPrimErrDebugNotSupported 26 No debug operations are supported

EsPrimErrDNURecursion 27 doesNotUnderstand: is not understood

EsPrimErrProcessTerminatedDuring-CallIn

28 Active process terminated during acallback

EsPrimErrStackOverflow 29 The Smalltalk stack has overflowed

EsPrimErrInvalidReftype 30 An invalid OSObject reftype

EsPrimErrInvalidReference 31 An invalid OSObject reference

EsPrimErrInvalidOffset 32 An invalid OSObject offset

EsPrimErrImageFileOpenError 33 Could not open image file

EsPrimErrImageReadError 34 Read error occurred while loadingimage

EsPrimErrMaxMemorySegments-Exceeded

35 Maximum number of memorysegments exceeded

EsPrimErrRSGrowFail 36 RememberedSet grow failed

EsPrimErrImageFileInvalid 37 Image file is not an image

EsPrimErrSupportDLLMissing 38 A required DLL cannot be located

EsPrimErrInternalError 39 An unspecified internal error hasoccurred

EsPrimErrMaxImagesSavesExceeded 40 Maximum number of image savesexceeded. You are running anevaluation copy of IBM Smalltalk.

EsPrimErrAsyncQueueOverrun 41 The async message queue hasoverflowed

EsPrimErrNMI 42 NMI has occurred

EsPrimErrUnimplementedByteCode 43 An unimplemented bytecode wasexecuted

EsPrimErrImageSaveError 44 An error occurred during image save

EsPrimErrInvalidAsyncMessage 45 An invalid async message was posted

EsPrimErrDecimalError 46 An error occurred in the decimal mathlibrary

EsPrimErrDecimalPrecisionScale-Mismatch

47 Precision must be greater than scale

Chapter 11. IBM Smalltalk Virtual Machine API 337

Page 352: IBM Smalltalk: Programmer's Reference

Table 39. User Primitive Error Codes (continued)

Error Code Value Description

EsPrimErrDecimalInvalidScale 48 Scale must be positive

EsPrimErrDecimalInvalidPrecision 49 Precision must be strictly positive

EsPrimErrDecimalPrecisionOverflow 50 Precision exceeds the maximum

EsPrimErrInvalidMemorySegment 51 Not valid memory segment specified

EsPrimErrGPF 52 General protection fault

EsPrimErrGPFInvalidRead 53 General protection fault-read frominvalid memory location

EsPrimErrGPFInvalidWrite 54 General protection fault-write toinvalid memory location

EsPrimErrGPFInvalidInstruction 55 General protection fault-invalidinstruction executed

EsPrimErrOutOfScopeReturnFrom-CallIn

56 Attempt to return out of scope over acall in

EsPrimErrNoMoreEntryPoints 57 All available esEntryPoint addressesare in use

EsPrimErrInvalidRelocation 58 Invalid image relocation

EsPrimErrFPUnderflow 59 Floating point underflow

EsPrimErrExitDueToWalkback 60 Exit due to walkback

EsPrimErrEvaluationTimeLimit-Expired

61 Evaluation time limit has expired

EsPrimErrExitDueToStackDump 62 Exit due to error with stack dumpprovided

EsPrimErrMinUserError 8192 Users can add new error codes abovethis value

338 IBM Smalltalk: Programmer’s Reference

Page 353: IBM Smalltalk: Programmer's Reference

Chapter 12. Dynamic data exchange

Dynamic data exchange (DDE) is an interprocess communication mechanismwhereby two applications can exchange data in the style of a client/serverarchitecture.

This chapter:v Introduces dynamic data exchangev Explains how to build a DDE server and a DDE client

IntroductionA DDE conversation takes place between two applications. The client applicationinitiates a data exchange by requesting data from a server application. The serverresponds by sending the requested data to the client application. A server canprovide data to many clients, but a client can make requests of only one server. Anapplication can create many DDE clients in order to exchange data with one ormore DDE servers. An application can be both a client and a server at the sametime. As in all client/server architectures, the client application always initiates theDDE conversation.

The IBM Smalltalk implementation of DDE introduces DDE server and DDE clientobjects. DDE servers can supply many DDE clients, but a DDE client can requestfrom only one server. An application written in IBM Smalltalk can have as manyDDE servers and clients as needed.

Previously, users have employed the clipboard for exchanging data betweendifferent applications. This required the user to select the data, copy it to theclipboard (usually by selecting a menu option), activate the second application, andthen paste the data into that application (again, usually by selecting a menuoption). This process is wholly dependent on the user, not only for copying thedata, but also for updating the data. DDE provides a mechanism for the completeautomation of this process. A DDE server application, for example, can be made tosend client data automatically without any user intervention.

There are many uses for this type of data exchange. A stock portfolio manager isone example. Here a DDE stock server application might be created that, as part ofits initialization, would dial up a stock pricing service over a modem. It wouldthen collect data from the pricing service and make it available to any connectedDDE clients.

Upon startup, a DDE client application would make a request to connect to theDDE stock server. The stock server would acknowledge that request and establisha DDE conversation. The client application could then request continuous updateson a specified, named piece of data (in this case the name of the stock). When thedata changed, the stock server application would automatically send a notificationto the client application. Then the DDE client application could recalculate itsentire portfolio and present its user with new or updated information.

DDE concepts and definitionsBefore reading about building a DDE server or client, become familiar with thefollowing concepts and terms.

© Copyright IBM Corp. 1994, 2000 339

Page 354: IBM Smalltalk: Programmer's Reference

DDE clientAn application that acts as the receiver side of a DDE conversation with aDDE server application. In IBM Smalltalk, the DdeClient class implementsthe function and protocol to support the client side of a DDE conversation.An instance of DdeClient can connect to a DDE server (any application,Smalltalk or otherwise, that follows the particular platform DDE serverprotocol) and then make data requests to that server.

DDE serverAn application that acts as the producer side of a DDE conversation with aDDE client application (any application, Smalltalk or otherwise, thatfollows the particular platform DDE server protocol).

DDE event notificationOccurs in an application when a message arrives from the other side of aDDE connection. For example, a DDE client application receives an eventnotification when a particular piece of data in the DDE server applicationchanges, or a DDE server application receives an event notificationwhenever a client application requests a connection.

Default databaseUsed by a DdeServerManager to hold all the items that theDdeServerManager makes available to DDE clients through defaultprocessing.

Default processingOccurs when a server application enables the IBM Smalltalk DDE systemto handle all of the interaction with the DDE client. The server applicationcreates a database of topics along with the name of each data item within atopic, the format specification of each data item, and the current value ofeach data item. The server application’s only role is to update theappropriate database whenever a data item changes.

CallbackThe primary means by which an application responds to DDE events.Callbacks are procedures within an application that take some action inresponse to events emanating from a DDE client or server. In IBMSmalltalk, callbacks are methods in an application class that is using aDdeClient or DdeServerManager to manage a DDE conversation. Thesemethods (that is, their selectors) along with the application object itself areregistered with the DDE objects, so that when a particular DDE eventoccurs, the DDE object “calls back” to the application by sending thespecified method to the specified application object. If callbacks are notregistered with a DdeServerManager for one or more events, thenwell-defined default processing will take place.

ApplicationIn this chapter, the program that creates and uses the DdeServerManager, orthe DdeClient, or both. The word “application” is often used as one of thethree qualifiers for a piece of data. In DDE terms, a piece of data isidentified by an application, topic, and item. This chapter, however,identifies data by server name, topic, and item. In IBM Smalltalk, the nameof a DDE server is simply a Smalltalk String passed as a parameter whenthe DdeServerManager is created. Here is an example of the server name,

340 IBM Smalltalk: Programmer’s Reference

Page 355: IBM Smalltalk: Programmer's Reference

topic, and item hierarchy:

Data

Stocks

Topic Items

Time

Price

time (String)

time (Smalltalk Object)

BTRX (String)

EST (String)

Application(Server name)

10:25:36

10:25:36

25.60

104.56

Topic Identifies a logical grouping of data items within a named DDE server. Apiece of data is usually identified by an application (server name), topic,and item. In a spreadsheet application, for example, the topic might be thefile name of a loaded spreadsheet.

Item Identifies a piece of data within a named topic of a named DDE server. Anitem’s identification consists of a name and format specifier. The path to adata item is usually denoted by a hierarchy of application (server name),topic, and item.

FormatSpecifies how a piece of data is to be interpreted by the receiving side of aDDE conversation. In IBM Smalltalk, a format is specified by a SmalltalkString (case insensitive). All data transferred to/from a DdeClient or aDdeServerManager must be contained in a ByteArray object. The formatstring tells each side of the DDE conversation how that data is to beinterpreted. There are certain predefined formats. The only exception tothis rule is the format ‘String’ where the item being transferred must alsobe a Smalltalk String.

System topicsA set of predefined topics and items that provide information of generalinterest to DDE clients. Table 40 shows the predefined topics and items thatare supported by the default processing of the DdeServerManager.

Table 40. System topics

Topic Item Format Data

System Topics String A tab-delimited string of all the topics supportedby this server

System Formats String A tab-delimited string of all the formats for allitems

System SysItems String A tab-delimited string of all the items under theSystem topic

System TopicItemList String A tab-delimited string of all the items under theSystem topic

All topics TopicItemList String A tab-delimited string of all the items supportedby a topic

All topics Formats String A tab-delimited string of all the formatssupported by this topic

HotlinkA request by a DDE client to a DDE server to be notified immediately

Chapter 12. Dynamic data exchange 341

Page 356: IBM Smalltalk: Programmer's Reference

when a particular data item changes, and to include with that notificationthe value of the changed data item. That is, when a hotlinked data itemhas changed, the DDE server generates an event notification back to theclient and sends the changed piece of data along with that event notice.

WarmlinkA request by a DDE client to a DDE server to be notified when a particulardata item changes. Unlike a hotlink, the DDE server only sends the eventback to the client and it does not send the changed data item along withthe notice. With a warmlink, the DDE client can explicitly request thechanged data from the server anytime after it has received notification ofthe change.

ColdlinkA request by a DDE client to a DDE server to unlink an existing hotlink orwarmlink to a particular data item.

DDE classesThe following figure shows the typical Smalltalk DDE architecture. Either one ofthese objects could be any other application that supports the DDE protocol foreither a DDE server or a DDE client.

DdeServerManagerDdeClient

DdeServer

DdeServer

DdeServer

Callback

App ServerCallback code

App ClientCallback code

App Client code

DdeClientmessage

Server Application Client Application

The classes depicted in the figure are described in the following sections. Theirhierarchy is as follows:

ObjectDdeClass

DdeClientDdeServer

DdeServerManager

This hierarchy is not part of the windowing system (such as PM or Windows) butit does use the windowing system of the underlying platform.

DdeClient classAn instance of the DdeClient class represents the client side of a DDE conversation.Methods of DdeClient are available for connecting to a DDE server, requesting dataitems from the server, requesting links to data items (hotlink, warmlink, orcoldlink), registering callbacks for data change and connection termination events,sending data items to a server, querying server capabilities, and requestingcommand execution by the server. A DdeClient can connect to any DDE server

342 IBM Smalltalk: Programmer’s Reference

Page 357: IBM Smalltalk: Programmer's Reference

application, Smalltalk or otherwise, that supports the platform DDE protocols. Aninstance of DdeClient can connect to only one DDE server.

Note: Windows prevents a DDE client from seeing servers provided from the sameprogram (.exe).

DdeServer classAn instance of DdeServer represents a single connection to a single DDE clientapplication. Methods of DdeServer are available to send data to a client and todisconnect from a DDE conversation. The DdeServerManager class described belowis the primary application interface for building DDE programs.

DdeServerManager classInstances of DdeServerManager are used to manage multiple connections to DDEclient applications. Each connection maintained by a DdeServerManager isrepresented by a DdeServer object. There are two primary techniques thatapplications can employ in using a DdeServerManager. With the first technique anapplication simply registers with the DdeServerManager the callbacks for one ormore of the DDE server events (see Table 41) and directly handles the processingfor those events. For example, an application can provide the code to handle ahotlink request from a DDE client.

Alternatively, a second technique can be used that relies entirely on internal defaultprocessing of the DdeServerManager and requires little involvement by the serverapplication. To utilize this approach an application describes to a DdeServerManagera database of topics, along with the name of each data item within a topic, theformat specification of each data item, and the current value of each data item. TheDdeServerManager then handles all of the interaction with the DDE client. The onlyrole of the server application is to update the DdeServerManager’s databasewhenever a data item changes.

DdeServerManager has methods to add and remove DDE event callbacks, add andremove database items, and update items in the database.

Note: If a callback has not been hooked, default processing occurs. What thedefault processor does depends on the event that caused the callback anditems in the default database. If a callback is hooked and the returnValueinstance variable is set to nil, default processing still occurs.

DdeCallbackData classAn instance of DdeCallbackData is passed as a parameter to all DDE event callbackmethods. It contains data about the current event and has a returnValue attribute(set with returnValue:), which is used to return information back to the IBMSmalltalk DDE subsystem.

Table 41. DdeCallbackData instance variables

Instance variable (class) Description

item (String) Name of the data item

format (String) Format for the data (see “Formats of data transferredbetween DDE servers and clients” on page 362).

data (String or ByteArray) The actual data

application (String) The server name for this DDE conversation

topic (String) The topic name for this DDE conversation

Chapter 12. Dynamic data exchange 343

Page 358: IBM Smalltalk: Programmer's Reference

Table 41. DdeCallbackData instance variables (continued)

Instance variable (class) Description

reason (Symbol) Reason this callback is executing (contained in the PoolDictionary DdeConstants having the form DdeCR...)

returnValue (Boolean or nil) Value to be returned from the callback. See Table 46 onpage 364 for descriptions of return values and theirmeanings.

DdeCallbackData has access methods to obtain the server name, the topic name, adata item (name and possibly its value), and data item format specification. Theavailability and significance of the information in a DdeCallbackData object areevent dependent. For a list of callbacks and return values for theDdeServerManager, see Table 44 on page 363 and Table 46 on page 364. For a list ofcallbacks for the DdeClient, see Table 45 on page 363.

Building a DDE serverThere are two ways to build a DDE server: one has default processing for all clientrequests, and the other enables your application to handle them. The followingdescriptions use terms defined in the preceding section. An example follows eachdescription. See “Discussion of the DdeServerManager” on page 352 for furtherinformation.

Throughout this chapter the code always compares in a case-insensitive manner.Many different tests have been done with a wide variety of available software andthere is a wide variation among programs that preserve the case of strings andthose that do not. Therefore, it is always best to check strings in a case-insensitivemanner.

Building a DDE server that uses default processingTo build a DDE server application that uses default processing, do the following:1. Create a DdeServerManager.2. Build the default database by sending the addItem:topic:value:format: message to

the DdeServerManager for each item that you want to make available to DDEclients.

3. Send the updateItem:topic:value:format: message to the DdeServerManager eachtime the value of the item changes.

4. When the application is finished, send the free message to theDdeServerManager.

By using default processing, the DdeServerManager (along with the defaultdatabase) handles all connection requests from DDE clients as well as requests forhotlinks, warmlinks, coldlinks, and data.

By default, data sent from any DDE client to your DdeServerManager (a poke, inDDE terminology) is rejected. Requests from the client for the server to runcommands are also rejected. However, both of these callbacks can be hooked,enabling the application to service these requests.

An example DDE server that uses default processingTo build a DDE server application that uses default processing:

344 IBM Smalltalk: Programmer’s Reference

Page 359: IBM Smalltalk: Programmer's Reference

This example builds a DDE server that has the time and date in two differentformats for a total of four available items. The items are as follows:v The current time in a String formatv The current time as a Smalltalk objectv The current date in a String formatv The current date as a Smalltalk object

First, create a class called DdeTimeServer that is a subclass of Object. Give it the twoinstance variables described in Table 42.

Table 42. Instance variables for DdeTimeServer

Instance variable Description

ddeServerManager The instance of the DdeServerManager class that you are creating.

timerOn A flag indicating whether the timer is on or off. Turning the timeroff is important when the server shuts down.

Your new class looks like this:Object subclass: #DdeTimeServer

instanceVariableNames: 'ddeServerManager timerOn 'classVariableNames: ''poolDictionaries: ''

Now create a class method new to create a new server. Send the initialize method tothe new object in order to set it up.new

"Answer a new server after initializing it."|super new initialize

Before executing the new class method, you need to create the initialize method. Inthe initialize method, first create the DdeServerManager and name it Timer. Next,build the default database.

Note: With the default database setup you do not have to hook into any of thecallbacks provided by the DdeServerManager. All you need to do is to updatethe items when the timer goes off. Notice that for the format of ‘String,’ youpass a Smalltalk String for the data. When the format is ‘Smalltalk Object,’you use the IBM Smalltalk Swapper to convert the Smalltalk object into aByteArray. The method flatten to perform this function is specified in“Converting Smalltalk objects to a ByteArray and back” on page 372.

initialize"Private - Create and initialize a DdeServerManager. Set the nameof the server to 'Timer' and create two items in the item databaseunder the topic of 'Time'. The two items will be 'date' and 'time.'Support two formats for the items, a string format and a Smalltalkobject. Support the Smalltalk object format by using the IBMSmalltalk Swapper to turn a Smalltalk object into a ByteArray."

| currentDate currentTime |ddeServerManager := DdeServerManager name: 'Timer'.currentTime := Time now.currentDate := Date today.

ddeServerManageraddItem: 'time'topic: 'Time'value: currentTime printStringformat: 'String'.

Chapter 12. Dynamic data exchange 345

Page 360: IBM Smalltalk: Programmer's Reference

ddeServerManageraddItem: 'time'topic: 'Time'value: (self flatten: currentTime)format: 'Smalltalk Object'.

ddeServerManageraddItem: 'date'topic: 'Time'value: currentDate printStringformat: 'String'.

ddeServerManageraddItem: 'date'topic: 'Time'value: (self flatten: currentDate)format: 'Smalltalk Object'.

self timerOn: true.

At the end of initialization the timer is turned on by sending the timerOn: message,which in turn sends the timerSet message. The timer uses the Common Widgetstimer functionality so that when the timer goes off, the message timerProc: is sentto the application.timerOn: aBoolean

"Start/stop the timer depending on aBoolean."timerOn := aBoolean.self timerSet.

timerOn"Answer whether the timer is on or off."|timerOn.

timerSet"If the timer is on, reset it to go off in one second."self timerOn ifTrue: [

CwAppContext defaultaddTimeout: 1000receiver: selfselector: #timerProc:clientData: nil

]

Now all initialization has been completed. The main work of the server is now inthe method that is run whenever the timer goes off. When the timer goes off andthe timerProc: method is run, all the items in the default database are updated. Asthe items are updated, the DdeServerManager looks for any hot- or warmlinks to thedata and updates the clients that are linked to those items.timerProc: clientData

"The timer has gone off so save the current date and time and thenupdate the item database."

| currentDate currentTime |currentTime := Time now.currentDate := Date today.

ddeServerManagerupdateItem: 'time'topic: 'Time'value: currentTime printStringformat: 'String'.

ddeServerManagerupdateItem: 'date'topic: 'Time'value: currentDate printStringformat: 'String'.

346 IBM Smalltalk: Programmer’s Reference

Page 361: IBM Smalltalk: Programmer's Reference

ddeServerManagerupdateItem: 'time'topic: 'Time'value: (self flatten: currentTime)format: 'Smalltalk Object'.

ddeServerManagerupdateItem: 'date'topic: 'Time'value: (self flatten: currentDate)format: 'Smalltalk Object'.

self timerSet.

The final method that you need to implement is the free method. This methodstops the timer and frees up the DdeServerManager.free

"Close down by stopping the timer and freeing up theDdeServerManager."

self timerOn: false.ddeServerManager free.

You now have a DDE server that not only provides the current time and date toany DDE client but also allows access to the Systems Topics that should besupported by all servers.

In this example server, the time and date are both updated when the timer goesoff. An improvement to the code might be to only update the date (and possiblythe time) if it has changed since the previous update.

Building a DDE server that does not use default processingTo build a DDE server application that does not use default processing:1. Create a DdeServerManager.2. Hook the necessary DdeServerManager callbacks (DdeNcoldlinkCallback,

DdeNhotlinkCallback, DdeNinitiateCallback, DdeNrequestCallback,DdeNwarmlinkCallback).

3. Write the callback methods for each hooked callback.4. When the application is finished, send the free message to the

DdeServerManager.

If you follow this procedure, the DdeServerManager will not handle any requestsfrom DDE clients. Methods must be written and callbacks hooked in order toprovide service. This technique of providing DDE server services takes more workbut allows for more flexibility.

Suppose, for example, that a user wants an application to make data availablethrough DDE but there is so much data, or the data is so large, that it must bestored on secondary storage. When a DDE client requests data, the server mustread the data from secondary storage and return it to the client. To do this theapplication must hook the DdeNrequestCallback callback and write a method tohandle requests for data from a DDE client.

Note: It is possible to have callbacks handled by a combination of defaultprocessing and the DDE server application. If a callback is hooked, then theapplication takes responsibility. If the callback is not hooked, then defaultprocessing occurs.

Chapter 12. Dynamic data exchange 347

Page 362: IBM Smalltalk: Programmer's Reference

An example DDE server that does not use default processingThis example builds a DDE server that provides the time only in the String format.

Creating a timer: First, create a class called DdeTimeServer2 that is a subclass ofObject. It has the two instance variables described in Table 43.

Table 43. Instance variables for DdeTimeServer2

Instance variable Description

ddeServerManager The instance of the DdeServerManager class that you are creating.

timerOn A flag indicating whether the timer is on or off. Turning the timeroff is important when the server shuts down.

Thus, our new class looks like this:Object subclass: #DdeTimeServer2instanceVariableNames: 'ddeServerManager timerOn 'classVariableNames: ''poolDictionaries: 'DdeConstants '

Second, create a class method new to create a new server. Also send the initializemethod to the new object in order to set it up.new

"Create a new timer server and initialize it."|super new initialize

Third, create the initialize method. In the initialize method you first create theDdeServerManager and name it Timer. Next you hook up to the callbacks and turnthe timer on.initialize

"Private - Create and initialize a DdeServer. Hook all callbacks."ddeServerManager := DdeServerManager name: 'Timer'.

ddeServerManageraddCallback: DdeNcoldlinkCallbackreceiver: selfselector: #coldlink:clientData:callData:clientData: nil.

ddeServerManageraddCallback: DdeNhotlinkCallbackreceiver: selfselector: #hotlink:clientData:callData:clientData: nil.

ddeServerManageraddCallback: DdeNinitiateCallbackreceiver: selfselector: #initiate:clientData:callData:clientData: nil.

ddeServerManageraddCallback: DdeNrequestCallbackreceiver: selfselector: #request:clientData:callData:clientData: nil.

ddeServerManageraddCallback: DdeNwarmlinkCallbackreceiver: selfselector: #warmlink:clientData:callData:clientData: nil.

ddeServerManageraddCallback: DdeNterminationCallback

348 IBM Smalltalk: Programmer’s Reference

Page 363: IBM Smalltalk: Programmer's Reference

receiver: selfselector: #termination:clientData:callData:clientData: nil.

self timerOn: true.

At the end of initialization, turn the timer on by sending the timerOn: message,which in turn sends the timerSet message. These methods are implemented below.The timer uses the Common Widgets timer functionality so that when the timergoes off, the message timerProc: is sent to the application.timerOn: aBoolean

"Start/stop the timer depending on aBoolean."timerOn := aBoolean.self timerSet.

timerOn"Answer whether the timer is on or off."|timerOn.

timerSet"If the timer is on, reset it to go off in one second."self timerOn ifTrue: [

CwAppContext defaultaddTimeout: 1000receiver: selfselector: #timerProc:clientData: nil

]

Implementing server behavior: Next, create the callback methods that implementthe behavior of this server. First you implement the callback for theDdeNinitiateCallback. The initiate:clientData:callData: method checks that theapplication name and the topic to which the client is attempting to connect matchwhat the server is looking for. If they do match, then the application sends thenotifyClientOfSupportFor: message to the DdeServer and sets the return value of theDdeCallbackData object to true. To reject the connect attempt, set the return value ofthe DdeCallbackData object to false. Notice that you are not attempting to handle anempty string for the application name or the topic name. The code should beembellished to handle this possible situation.initiate: aDdeServer clientData: unused callData: ddeCallbackData

"Initiate callback - check the application name and topicand set the returnValue to true if they match."| app top |app := ddeCallbackData application asLowercase.top := ddeCallbackData topic asLowercase.

((app = 'timer') and: [top = 'time'])ifTrue: [

self message:('Connect. App = %1 Topic = %2'

bindWith: app with: top).aDdeServerManager notifyClientOfSupportFor: 'Time'.ddeCallbackData returnValue: true.

]ifFalse: [

self message: ('Reject. App = %1 Topic = %2'

bindWith: app with: top).ddeCallbackData returnValue: false.

]

Handling links: The code that follows is for the DdeNhotlinkCallback method. Themethod checks the item name and the format. It sets the DdeCallbackData object totrue if the item is supported and false otherwise.

Chapter 12. Dynamic data exchange 349

Page 364: IBM Smalltalk: Programmer's Reference

hotlink: ddeServer clientData: unused callData: ddeCallbackData"Hotlink callback - Check the item name and the format.Set the returnValue to true if the item is 'time' andthe format is 'String', false otherwise."

| item format string |item := ddeCallbackData item asLowercase.format := ddeCallbackData format asLowercase.

string := 'Item = %1 Format = %2' bindWith: item with: format.(item = 'time' and: [format = 'string'])

ifTrue: [self message: ('Hotlink. %1' bindWith: string).ddeCallbackData returnValue: true.

]

ifFalse: [self message: ('Hotlink rejected. %1' bindWith: string).ddeCallbackData returnValue: false.

]

The method for handling the warmlink and coldlink has the same form as themethod for the hotlink. Instead of implementing the code shown below, themethod could test the reason value of the DdeCallbackData object (by way of thereason message) and print out different messages based on the value that isreturned.warmlink: ddeServer clientData: unused callData: ddeCallbackData

"Warmlink callback - Check the item name and the format.Set the returnValue to true if the item is 'time' andthe format is 'String'."| item format string |

item := ddeCallbackData item asLowercase.format := ddeCallbackData format asLowercase.

string := 'Item = %1 Format = %2' bindWith: item with: format.(item = 'time' and: [format = 'string'])

ifTrue: [self message: 'Warm link. %1' bindWith: string.ddeCallbackData returnValue: false

]ifFalse: [

self message: 'Warm link rejected. %1' bindWith: string.ddeCallbackData returnValue: true.

]

Note: The Excel spreadsheet program sends coldlink messages with an emptystring as the format.

coldlink: ddeServer clientData: unused callData: ddeCallbackData"Coldlink callback - Check the item name."| item format string |

item := ddeCallbackData item asLowercase.format := ddeCallbackData format asLowercase.

string := 'Item = %1 Format = %2' bindWith: item with: format.item = 'time'

ifTrue: [self message: 'Cold link. %1' bindWith: string.ddeCallbackData returnValue: true.

]ifFalse: [

self message: ('Cold link rejected. %1' bindWith: string).ddeCallbackData returnValue: false.

]

350 IBM Smalltalk: Programmer’s Reference

Page 365: IBM Smalltalk: Programmer's Reference

Handling client requests: The next callback you implement isDdeNrequestCallback. This callback is run when the client requests data from theserver. As in previous examples, you check whether the item and the format arewhat you are looking for, then send the data to the client by sending the messagesendItem:value:format: to the DdeServer that was passed to the callback method. Thereturn value of the DdeCallbackData object should be set to true if the data is sent tothe client and false if the data is not sent to the client.request: ddeServer clientData: unused callData: ddeCallbackData

"Request callback - Check the item name and the format. If theymatch what you are looking for then send the data to the client."

| item format string |

item := ddeCallbackData item asLowercase.format := ddeCallbackData format asLowercase.string := 'Item = %1 Format = %2' bindWith: item with: format.

(item = 'time' and: [format = 'string'])ifTrue: [

self message: 'Request. %1' bindWith: string.ddeServer

sendItem: ddeCallbackData itemvalue: Time now printStringformat: 'String'.

ddeCallbackData returnValue: true.]ifFalse: [

self message: ('Request rejected. %1' bindWith: string).ddeCallbackData returnValue: false.

]

Ending: The last callback you implement is the DdeNterminationCallback. Thismethod should not attempt to disconnect. It only prints to the Transcript that theserver dropped a connection.termination: ddeServer clientData: unused callData: ddeCallbackData

"Termination callback - Print out a message that the server isdisconnecting."

self message: 'Connection terminated'.

Now all initialization has been completed and all the callbacks have been set up.The main work of the server is now contained in the method that is run wheneverthe timer goes off. When the timer goes off and the timerProc: method is run, theone supported item is updated. As the item is updated the DdeServerManager looksfor any hot- or warmlinks to the data and updates the clients that are linked tothat piece of data.timerProc: clientData

"The timer has gone off so update the item database."

ddeServerManagerupdateItem: 'time'topic: 'Time'value: Time now printStringformat: 'String'.

self timerSet.

Note: After the updateItem:topic:value:format: message is completed, the data passedas the value parameter is lost. The DdeServerManager does not keep a copyof this data. When the default database is used, the data is kept so thatwhen a client requests the data the DdeServerManager can give the data backwithout intervention from the application. The implication is that if a server

Chapter 12. Dynamic data exchange 351

Page 366: IBM Smalltalk: Programmer's Reference

has many items or lots of data, it might not be able to use default processingand the default database because of memory restrictions. In that case theserver has to hook the callbacks and process the events itself.

The message: method that has been used throughout the example follows:message: aString

"Print a message on the Transcript."

Transcript cr; show: 'Timer Server: ', aString

The final method that you need to implement is the free method. This methodstops the timer and frees up the DdeServerManager.free

"Close down by stopping the timer and closing down the DdeServer."

self timerOn: false.ddeServerManager notNil ifTrue: [ddeServerManager free]

You now have a DDE server that provides the current time in String format.

An improvement to the code might be to support the empty application name(server name) and an empty topic name as well as both the date and time in otherformats.

Discussion of the DdeServerManagerTo act as a DDE server, an application creates a DdeServerManager object using theclass method name:, which takes a string argument as the name of the newDdeServerManager. This is the name for DDE clients to use in establishing aconnection with the server. The application can then register for any of thecallbacks listed above for the DdeServerManager. When a DDE client connects to theserver, the DdeServerManager creates a new DdeServer object to handle theconversation with that client. Hence, an application only creates one instance ofDdeServerManager, but an instance of DdeServer is created for each conversationthat the DdeServerManager is managing. The following figure illustrates this setupof runtime DDE objects and applications.

Note: Applications should never directly create DdeServer objects.

Application

DdeServerManager DdeServer

DdeServer

DdeServer

Application

DdeClient

Application

DdeClient

Application

DdeClient

352 IBM Smalltalk: Programmer’s Reference

Page 367: IBM Smalltalk: Programmer's Reference

Default databaseTo offload DDE server event processing from the developer’s application to theDdeServerManager, you can create a database of topics and data items for theDdeServerManager, where the data items are stored with their name, format, andcurrent value. Items can be added to the database with the following message to aDdeServerManager:aDdeServerManager

addItem: itemNametopic: topicNamevalue: dataformat: formatName

Building a database of all topics and data items lets the DdeServerManager performits default processing in servicing requests from DDE clients, without requiring anyintervention from the application. To illustrate, the following code creates aDdeServerManager and builds a database of topics and items that will be serviced.| aDdeServerManager |aDdeServerManager := DdeServerManager name: 'Stocks'.aDdeServerManager

addItem: 'time'topic: 'Time'value: Time now printStringformat: 'String';addItem: 'time'topic: 'Time'value: (self flatten: Time now)format: 'Smalltalk Object';

addItem: 'BTRX'topic: 'Price'value: 26.50 printStringformat: 'String';

addItem: 'EST'topic: 'Price'value: 104.56 printStringformat: 'String'

The following figure shows an example DdeServerManager default database afterexecuting the previous code.

Data

Stocks

Topic Items

Time

Price

time (String)

time (Smalltalk Object)

BTRX (String)

EST (String)

Application(Server name)

10:25:36

10:25:36

25.60

104.56

The IBM Smalltalk Swapper makes it straightforward to use DDE to pass Smalltalkobjects back and forth between cooperating Smalltalk applications. The methodflatten: in the above code converts a Smalltalk object into a ByteArray. The Swappercan also be used on the receiving side of a DDE connection to unflatten theSmalltalk object. The code for doing this is specified in “Converting Smalltalkobjects to a ByteArray and back” on page 372.

Chapter 12. Dynamic data exchange 353

Page 368: IBM Smalltalk: Programmer's Reference

The default processing database for an instance of DdeServerManager contains asingle server name, one or more topics that are associated with that server name,and one or more items for each topic. An application should only use one instanceof a DdeServerManager.

Once a DdeServerManager’s database is constructed, the application need onlyupdate an item in the database when the data associated with that item changes.The DdeServerManager then automatically takes the appropriate action with anyDDE clients linked to that item. For example, if the price of the EST stock changes,then the application runs the following code:ddeServerManager

updateItem: 'EST'topic: 'Price'value: 100.01 printStringformat: 'String'

In response to this message, the DdeServerManager automatically updates anyclients that have links or outstanding requests for that data item (assuming that theapplication does not override the DdeNrequestCallback). In addition, theDdeServerManager can automatically respond to DDE client requests for any of thepredefined general-interest topics and items listed in Table 40 on page 341.

Initiate eventWhen a DDE client attempts to connect to a DDE server, the DdeNinitiateCallbackruns on the server application (assuming the DdeNinitiateCallback is hooked). TheDdeCallbackData object passed to the callback contains the topic strings and thename of the server to which the client is trying to connect. If the application wantsto accept the connect request, then it must send the following message:ddeServerManager notifyClientOfSupportFor: topicStr

topicStr is the server application topic string. Note that it is possible for the clientto send an empty string for the topic request. In this case, the server applicationshould send the message notifyClientOfSupportFor: for each topic that it supports. Itis also possible for the DDE client to use an empty string for the server name. Thisimplies that any server, regardless of name, can respond to the connect request. Forexample, a server application might implement the DdeNinitiateCallback callback asfollows:initiate: aDdeServerManagerclientData: clientDatacallData: callData

"If the application and the topic are empty, then notify theclient about both of the topics."

callData application isEmpty& callData topic isEmpty ifTrue: [

|aDdeServerManagernotifyClientOfSupportFor: 'Topic1';notifyClientOfSupportFor: 'Topic2'.

].

"If the application does not match the server name thenreject the connect request."callData application asLowercase = 'server' ifFalse: [

|self].

"At this point the application name matches our server name.Check for a connect request to a topic you support."callData topic = 'Topic1' ifTrue: [

|aDdeServerManagernotifyClientOfSupportFor: 'Topic1'.

354 IBM Smalltalk: Programmer’s Reference

Page 369: IBM Smalltalk: Programmer's Reference

].callData topic = 'Topic2' ifTrue: [

|aDdeServerManagernotifyClientOfSupportFor: 'Topic2'.

]."There is no topic that you support so reject the connect request."

Note: The return value was not used. See Table 46 on page 364.

If DdeServerManager default processing is being used for the initiate request (that is,the DdeNinitiateCallback is not hooked), then the DdeServerManager checks theserver name and the topic names in the default processing database and, if found,creates a connection for the requested topic. However, if the DdeServerManagerreceives an empty string for the server name or topic name, it responds by sendingnotifyClientOfSupportFor: for each topic in the default processing database. Onceconnected, a DDE client can request only items associated with the topic specifiedin the connect request. A client must disconnect and then reconnect to access itemsin a different topic. The following figure shows how a DDE client initiates aconnect request to a DDE server, thereby generating the initiate event.

Dde client

1.connect

ServerApplicationCallbackCode

DdeServerManager

2.DdeNinitiateCallback

3.notifyClientOfSupportFor:

Server application

4.connectacknowledgement

Client Application

Warmlink and hotlink eventAfter the DDE conversation has been established, a DDE client might try to link toa particular data item. When a client attempts a link to a data item, theDdeNwarmlinkCallback or DdeNhotlinkCallback is run on the server application(assuming DdeNwarmlinkCallback or DdeNhotlinkCallback are hooked). In this case,the DdeCallbackData object passed to the callback contains the name of the item, itsformat, and the current application and topic names. For example, to register forthe DdeNwarmlinkCallback, a DDE server application uses:ddeServerManager

addCallback: DdeNwarmLinkCallbackreceiver: selfselector: #warmLink:clientData:callData:clientData: nil

Chapter 12. Dynamic data exchange 355

Page 370: IBM Smalltalk: Programmer's Reference

The callback warmLink:clientData:callData: method looks like this:warmLink: aDdeServer clientData: clientData callData: callData

"A DDE client has requested a warm link to a piece of data. Checkthe name and format and if supported set the return value to trueto acknowledge the connect request. Otherwise set the return valueto false."

| item format |item := callData item asLowercase.format := callData format asLowercase.(item = 'time' and: [format = 'string'])

ifFalse: [callData returnValue: false]ifTrue: [

Transcript show: 'warmLink ', item, ' ', format.callData returnValue: true.

]

By setting the return value of the DdeCallbackData object to true, the DDE serverapplication has indicated that the item/format is supported. In that case, theDdeServerManager creates a link to that item for the client, and it generates thenecessary events back to the DDE client when the data item is updated. The serverapplication must set the return value of the DdeCallbackData object to true if theitem/format is supported and to false if the item/format is not supported. A nilreturn value in the DdeCallbackData object causes the DdeServerManager to look upthe item in its default database and, if found, link the client to that item.

Coldlink eventWhen a DDE client unlinks from a data item, the DdeNcoldlinkCallback is run on theDDE server application (assuming the DdeNcoldlinkCallback is hooked). As withhot- and warmlinking, the DdeCallbackData object passed to the callback containsthe name of the item to be unlinked, its format, and the current application andtopic names.

If the DDE server application sets the return value of the DdeCallbackData object totrue, then the DdeServerManager checks for an existing link to the data item and, ifone exists, it unlinks the client from that item. In this case, if a link to the dataitem does not exist, the DdeServerManager generates an error response back to theclient. On the other hand, a false return value in the DdeCallbackData object has noeffect on the linkage status of the specified data item.

The DdeNcoldlinkCallback is unique in that a nil return value in the DdeCallbackDataobject is the same as a true return value.

Request eventWhen a client wants to retrieve data from a server, the DdeNrequestCallback is runon the server application (assuming the DdeNrequestCallback is hooked). Here theDdeCallbackData object passed to the callback contains the name of the item, itsformat, and the current application and topic names. If the data is available, theapplication sets the return value of the DdeCallbackData object to true and sends themessage sendItem:value:format: to the DdeServer object passed as the first parameterof the callback. For example, to register for the DdeNrequestCallback, a DDE serverapplication uses:ddeServerManager

addCallback: DdeNrequestCallbackreceiver: selfselector: #request:clientData:callData:clientData: nil

The callback request:clientData:callData: method looks like:

356 IBM Smalltalk: Programmer’s Reference

Page 371: IBM Smalltalk: Programmer's Reference

request: aDdeServer clientData: clientData"A DDE client is requesting a piece of data. Check that the item andtopic and item are supported. If the item/format is not supported,set the return value to false. If the item/format is supported thensend the data to the client and set the return value to true."

| item format |item := ddeCallbackData item asLowercase.format := ddeCallbackData format asLowercase.(item = 'time' and: [format = 'string'])

ifFalse: [ddeCallbackData returnValue: false]ifTrue: [

aDdeServersendData: ddeCallbackData itemformat: 'String'with: Time now printString.

ddeCallbackData returnValue: true.]

If nil is set for the return value of the DdeCallbackData object (or if theDdeNrequestCallback is not hooked), the DdeServerManager performs its defaultprocessing, which in this case is to check for the item in the default database and iffound, send it back to the client.

Run and poke eventsWhen a DDE client wants to send data (called “poke” in DDE parlance) to aserver, the DdeNpokeCallback is run on the server application (assuming theDdeNpokeCallback is hooked). The DdeCallbackData object passed to the callbackmethod contains the name of the data item, its format, and the current applicationand topic names. Server handling of this event is similar to the hot/warm/coldlink events.

When a DDE client makes a command execution request on a server, theDdeNexecuteCallback is invoked on the server (again assuming theDdeNexecuteCallback is hooked). Here the DdeCallbackData object passed to thecallback method contains the command to be run (as a string), and the currentapplication and topic names. The command string can be accessed from theDdeCallbackData object through the execute message.

Termination eventWhen a DDE client shuts down or sends a connection termination request to aserver, the DdeNterminationCallback method is run on the server application. Theserver application should not try to disconnect at this point because the clientcannot be stopped from terminating the connection. This callback only exists tonotify the server that the connection is terminating. Also, the server applicationshould not try to free the DdeServer passed as the first parameter of the callback.The DdeServerManager manages the DdeServer objects for each connection and takesappropriate action as required.

Building a DDE clientThe following description uses terms defined in “DDE concepts and definitions” onpage 339. An example follows the description. See “Discussion of the DdeClient”on page 359 for further information.

To build a DDE client application:1. Create a DdeClient.

Chapter 12. Dynamic data exchange 357

Page 372: IBM Smalltalk: Programmer's Reference

2. Connect to a DDE server by sending the message connect:topic: to the DdeClientwith the name of the server and the name of the topic that you want to connectto.

3. After the connection is made, messages can be sent to the DdeClient to requestdata, link to data (hotlink, warmlink, or coldlink), send data to the server, orask the server to run a command.

4. To handle the arrival of data asynchronously from the server (that is, hotlinkedand warmlinked items), the application must hook the DdeNdataCallback or theDdeNchangeCallback callbacks.

5. To connect to a different server or topic, send the disconnect message to theDdeClient and then send the connect:topic: message with the name of the serverand the name of the topic to connect to.

6. When the application is finished, send the free message to the DdeClient.

An example DDE clientIn this example, a DDE client exchanges data with the example DDE server createdpreviously. This client connects to the server, sets up a hotlink to the time anddate, and prints it in the Transcript window when it changes.

First, create a class called DdeTimeClient that is a subclass of Object. It will have theddeClient instance variable that represents the instance of the DdeClient class thatyou will create.

Thus, your new class looks like:Object subclass: #DdeTimeClient

instanceVariableNames: 'ddeClient 'classVariableNames: ''poolDictionaries: 'DdeConstants '

Note: Include the pool dictionary DdeConstants because you are going to hook intoa callback that needs this pool dictionary.

Now, add a class method new to create a new client. Also send the initialize methodto the new object in order to set it up.new

"Create a new timer client and initialize it."|super new initialize

Now you create the initialize method. This method creates the DdeClient object andconnects it to the server. Next it hooks up to the hotlink callback so that when thedata at the server changes, the client is notified. Then the application attempts tohotlink to the time and date items at the server.initialize

"Initialize the dde client."ddeClient := DdeClient new.(ddeClient connect: 'Timer' topic: 'Time') ifFalse: [

|Transcript cr; show: 'Client cannot connect'.].ddeClient

addCallback: DdeNdataCallbackreceiver: selfselector: #data:clientData:callData:clientData: nil.

358 IBM Smalltalk: Programmer’s Reference

Page 373: IBM Smalltalk: Programmer's Reference

(ddeClient hotLink: 'time' format: 'Smalltalk Object')ifFalse:[

Transcriptcr;show:'Cannot hotlink to time'

].

(ddeClient hotLink: 'date' format: 'Smalltalk Object')ifFalse:[

Transcriptcr;show:'Cannot hotlink to time'

].

Next, create the hotlink callback method. All callbacks take three parameters: theDDE object calling the method, the client data passed when the callback washooked, and the DdeCallbackData object containing the information about thecallback.

When the callback is run the method unflattens the data in the DdeCallbackDataobject from a ByteArray into a Smalltalk object (because this is what we hotlinkedto in the first place). The unflatten: method takes a ByteArray and uses the IBMSmalltalk Swapper to convert it back into a Smalltalk object. The code for doingthis is specified in “Converting Smalltalk objects to a ByteArray and back” onpage 372.

After converting the data back to a Smalltalk object, the method then prints theobject in the Transcript window.data: aDdeClient clientData: clientData callData: callData

"Hotlink callback - unflatten the data and display it."

| data |data := self unflatten: callData data.Transcript

cr;show: data printString.

The final method that you need to implement is the free method. This method freesup the DdeClient.free

"Free up the dde client resource."ddeClient free.

Discussion of the DdeClientFor an application to become a DDE client, it simply creates an instance of theDdeClient class and connects it to a DDE server. The connection message to a DDEserver includes the server name and the name of the topic the client is interestedin. A DDE client can be established by running the following code:ddeClient := DdeClient new.ddeClient connect: serverName topic: topicName.

where serverName and topicName are instances of String.

Note: Once a DdeClient connects to a server for a particular topic, it cannot connectto a different server or a different topic on the same server, unless it firstterminates the existing connection and then reconnects to a new server, ortopic, or both.

Chapter 12. Dynamic data exchange 359

Page 374: IBM Smalltalk: Programmer's Reference

QueriesA client application can query for information about the DDE servers currentlyrunning. There are three methods of DdeClient that provide data on all of theavailable DDE servers:

queryAllQueries all servers for all possible topics, and returns a Dictionary wherethe key is the application name and the value is a Set containing all of thetopic names supported by that application.

queryServersFor:Queries all servers for a specified topic, and returns a Set containing thenames of the applications that handle the topic.

queryTopicsFrom:Queries a particular named server for all of the topics it supports, andreturns a Set containing the names of the topics handled by that server.

Requesting dataA client application can request a specific data item from the server using therequestData:format: message:result := ddeClient requestData: item format: format

The format specification tells the server what format the client is interested in. Ifthe server does not respond with data, the result is nil.

Hot- and warmlinking to itemsA client application might want a DDE server to notify it when a particular dataitem changes. It does this by sending one of two messages to the DdeClient:ddeClient hotLink: item format: format.

orddeClient warmLink: item format: format.

The format specification tells the server what format the client is interested in. ThehotLink:format: or warmLink:format: messages return true to indicate that the serversupports the data item in the specified format. However, if either message returnsfalse, then the server either does not support the data item or it does not supportthe specified format for the data item.

For a client application to receive notification of a change for a hotlinked dataitem, it must register the DdeNdataCallback with its DdeClient object. When thehotlink callback runs, the actual changed data is passed in the DdeCallbackDataobject where it can be retrieved with the data message. For example, to register theDdeNdataCallback, a client application uses:ddeClient

addCallback: DdeNdataCallbackreceiver: selfselector: #hotLink:clientData:callData:clientData: nil

The client’s implementation of the hotlink callback method looks like:hotLink: ddeClient clientData: clientData callData: callData

"The data at the server has changed. Go get the data."| item format string data|

item := callData item.format := callData format.data := callData data.

360 IBM Smalltalk: Programmer’s Reference

Page 375: IBM Smalltalk: Programmer's Reference

stringdata notNilifTrue: ['Data arrived %1 %2']ifFalse: ['Data unavailable %1 %2']

Transcriptcr;show: (string bindWidth: item with: format).

Likewise, for a client application to receive notification of a change for awarmlinked data item, it must register the DdeNchangeCallback with its DdeClientobject. However, unlike a hotlink callback, the changed data item is not passed tothe callback in the DdeCallbackData object. To obtain the changed data, the clientapplication must explicitly request it from the server by using therequestData:format: message on the DdeClient passed to the callback as the firstparameter. This message returns the data from the server if it is available,otherwise it returns nil. The following code warmlinks the client application to anitem and processes the event when that item changes at the server:ddeClient

addCallback: DdeChangeCallbackreceiver: selfselector: #warmLink:clientData:callData:clientData: nil

andwarmLink: ddeClient clientData: clientData callData: callData

"The data at the server has changed. Go get the data."| item format string data|item := callData item.format := callData format.data := ddeClient requestData: item format: format.

string :=data notNil

ifTrue: ['Data arrived %1; %2']ifFalse ['Data unavailable %1; %2']

Transcriptcr;show: (string bindWidth: item with: format).

Coldlinking itemsA client application unlinks from an item previously hot- or warmlinked bysending the coldLink:format: message to a DdeClient:ddeClient coldLink: anItem format: aString.

This message returns true if the item successfully unlinks. It returns false if the itemcannot be unlinked. An item cannot be unlinked if it was never linked, or if theitem, its format, or both did not exist on the server. After this message is sent, theclient application is no longer notified of updates to that item from the server.However, it can still use the requestData:format: method on the DdeClient to querythe server for the data item.

Sending data to the serverA client application can send data to the DDE server by sending thesendItem:value:format: message to the DdeClient object:ddeClient sendItem: item value: value format: format.

The form of this message is the same as sendItem:value:format: of a DdeServer object.Here, true is returned if the server accepts the data; otherwise, false is returned.

Chapter 12. Dynamic data exchange 361

Page 376: IBM Smalltalk: Programmer's Reference

Executing commands at the serverA client application can ask a server to run a command by sending the messageexecute: to the DdeClient object along with a string containing the command to berun:ddeClient execute: 'someCommand param1 param2'

Here, true is returned if the server runs the command, and false is returned if itcannot.

Formats of data transferred between DDE servers and clientsAny data item transferred between DDE servers and clients must have aspecification of its format so that it can be properly interpreted by the other side ofthe connection. In IBM Smalltalk each format is described by a Smalltalk String.Here are the predefined formats available for both the OS/2 and Windowsplatforms:v ‘String’v ‘Bitmap’v ‘MetaFilePict’v ‘Sylk’v ‘Dif’v ‘Tiff’v ‘Dib’v ‘Palette’v ‘OwnerDisplay’v ‘DspText’v ‘DspBitmap’v ‘DspMetaFilePict’v ‘Rtf’v ‘Link’

The data to be transferred, with one exception, must be provided to the respectiveDDE object as a ByteArray. For example, if a DDE server is serving up bitmap data,then the server application provides the DdeServerManager a format specification of‘Bitmap’ and a ByteArray object containing the bitmap data. The only exception isthe ‘String’ format where the data is always provided to the DDE objects as aSmalltalk String.

Callbacks for handling DDE eventsEach DdeClient and DdeServerManager expects to have an application handle theDDE events as they occur (unless default processing is used). These events arehandled by callbacks. For each possible DDE event, the application that creates aDdeClient or DdeServerManager registers one of its methods as the callback tohandle that event. To register a callback, the application sends the messageaddCallback:receiver:selector:clientData: to the respective DdeClient orDdeServerManager.

The callback argument of this message identifies the particular DDE event that isto be hooked. The receiver argument identifies the object that will be sent thecallback message, which is specified with the three-parameter message selector inthe selector argument. The clientData argument specifies optional data that ispassed to the callback method when it is run. The names identifying the DDEevents, or callbacks, are defined in the pool dictionary DdeConstants. The followingtable identifies the callback names for the DdeServerManager.

362 IBM Smalltalk: Programmer’s Reference

Page 377: IBM Smalltalk: Programmer's Reference

Table 44. DdeServerManager callbacks

Callback Explanation

DdeNcoldlinkCallback A client is requesting to terminate a link to an item.

DdeNwarmlinkCallback A client is creating a warmlink to a data item.

DdeNhotlinkCallback A client is creating a hotlink to a data item.

DdeNpokeCallback A client is sending data to the server.

DdeNinitiateCallback A client is trying to establish a connection to the server.

DdeNexecuteCallback A client is requesting the server to run a command.

DdeNrequestCallback A client is requesting data from the server.

DdeNterminationCallback The client is terminating the connection with the server.

The following table identifies the callback names for the DdeClient.

Table 45. DdeClient callbacks

Callback Explanation

DdeNchangeCallback The item at the server has changed. The client must requestthe data from the server.

DdeNdataCallback The item at the server has changed and the data is availablefrom the DdeCallbackData object through the data message.

DdeNterminationCallback The server is terminating the connection with the client.

Thus, to set up a DdeServerManager to handle the DDE run callback, use code likethe following:aDdeServerManager

addCallback: DdeNexecuteCallbackreceiver: selfselector: #execute:clientData:callData:clientData: nil.

All DDE callbacks are handled in the same manner as Common Widget callbacks.When a callback runs, its first parameter is the particular DdeServer or DdeClientobject that originated the event; the second parameter is the client data object thatwas provided when the callback was registered; and the last parameter is aDdeCallbackData object that contains the information about the event (that is, anydata associated with the event), the current server name, the current topic, and soon. From the example above, the callback method that responds to the DDE runevent looks like this:execute: aDdeServer clientData: clientData callData: callData

"A client has asked to run a command. Print the command in thetranscript and set the return value to true to indicate that thecommand was run."Transcript

cr;show: ('Execute : %1' bindWith: callData execute).

callData returnValue: true.

Return valuesA method responding to a DdeServerManager callback can return information backto the source of the event through the returnValue attribute of a DdeCallbackDataobject. This value can be set through the returnValue: message. A return value of nil

Chapter 12. Dynamic data exchange 363

Page 378: IBM Smalltalk: Programmer's Reference

(the default) causes default processing to be performed by the DdeServerManager.The following table describes the return values for DdeServerManager callbacks.

Table 46. DdeCallbackData return values for handling DdeServerManager Callbacks

Callback Return value: true Return value: false Return value: nil

DdeNcoldlinkCallback The link has been broken. The link has not beenbroken.

If there is a link to theitem, then break it.

DdeNwarmlinkCallback The item and format aresupported.

The item and format are notsupported.

If the item is in thedefault database, thencreate a link to it.

DdeNhotlinkCallback The item and format aresupported.

The item and format is notsupported.

If the item is in thedefault database, thencreate a link to it.

DdeNpokeCallback The server accepts the data. The server rejects the data. The server rejects thedata.

DdeNinitiateCallback N/A. To connect the DDEclient send the messagenotify:ClientOfSupportFor: tothe DdeServerManagerparameter of the callback.

N/A. To reject the connectrequest do not send themessagenotify:ClientOfSupportFor: tothe DdeServerManagerparameter of the callback.

If the server name andthe topic to which theDDE client is attemptingto connect exist in thedefault database, then aconnection is made.

DdeNexecuteCallback The server can run thecommand.

The server cannot run thecommand.

The server cannot run thecommand.

DdeNrequestCallback The data has been sent tothe client. Send thesendItem:value:format:message to the DdeServerparameter of the callback.

The data has not been sentto the client. The IBMSmalltalk DDE subsystemsends a negativeacknowledgment to theclient.

If the data is in thedefault database, then itis sent to the client.Otherwise, a negativeacknowledgment is sentto the client.

DdeNterminationCallback N/A N/A N/A

For the DdeClient callbacks DdeNchangeCallback, DdeNdataCallback, andDdeNterminationCallback, the return value is ignored whether the return value istrue, false, or nil.

DDE protocolsThe following sections describe public protocols for these classes:v DdeServerManagerv DdeClassv DdeServerv DdeClient

DdeServerManager public class methodsname: Answers a new DdeServerManager with the specified name (a String).

Return value: An instance of DdeServerManager.

DdeServerManager public instance methodsaddCallback:receiver:selector:clientData:

Adds a callback to one of the receiver’s callback lists.

364 IBM Smalltalk: Programmer’s Reference

Page 379: IBM Smalltalk: Programmer's Reference

Generally speaking, a DdeServerManager expecting to interact with anapplication declares one or more callback lists as resources, and theapplication adds to these callback lists the callbacks that are invokedwhenever the predefined callback conditions are met. Callback lists areresources, so that the application can set or change the function that isinvoked.

Callbacks are not necessarily invoked in response to any event; aDdeServerManager can call the specified routines at any arbitrary point inits code, whenever it wants to provide a “hook” for application interaction.For example, all DdeServerManager objects provide a terminationCallbackresource to enable applications to interpose a routine to be run when aDDE connection is broken.

This message adds a new callback to the end of the callback list. A callbackis invoked as many times as it occurs in the callback list.

callbackNameThe resource name of the callback list to which the callback is to beappended.

receiverThe object to send the callback message to.

selector The three-parameter message selector to send.

clientDataAn object to be passed to the receiver of the callback message asthe clientData parameter when the callback is invoked, or nil.

addItem:topic:value:format:Adds an item to the database.

item A String identifying the name of the item.

topic A String identifying the topic to which the item belongs.

value The data that is named by item. If the format is ‘String,’ the valuemust be a Smalltalk String, otherwise it must be a ByteArray.

format A String identifying the format of the data.

free Frees any allocated resources. The DdeServerManager cannot be used at anytime after this message is sent.

name Answers a String that is the name of the receiver.

notifyClientOfSupportFor:Notifies the client attempting to connect that the receiver supports thespecified topic.

topicStringA String identifying the name of the topic.

removeAllCallbacks:Deletes all callbacks from a callback list.

This message removes all the instance callback messages identified by thespecified callback name, regardless of the value of the clientData associatedwith each message. This is in contrast to removeCallback:..., which removesthe specified callback only if a specified clientData argument also matches.

callbackNameThe resource name of the callback list from which the callback is tobe removed.

Chapter 12. Dynamic data exchange 365

Page 380: IBM Smalltalk: Programmer's Reference

removeCallback:receiver:selector:clientData:Deletes a callback from a callback list.

This message removes a callback message identified by callbackName.

The callback is removed only if both the callbackName and clientData matcha callback/data pair in the list. No warning message is generated if acallback to be removed fails to match a callback or clientData in the list.Use removeAllCallbacks:... if you want to remove a particular callbackregardless of the value of its clientData.

callbackNameThe resource name of the callback list from which the callback is tobe deleted.

receiverThe object to match against the callback receiver in the callback list.

selector The three-parameter message selector which is to be used to matchagainst the callback in the callback list.

clientDataThe object to match with the clientData object in the callback listentry.

removeItem:topic:format:Removes an item from the database. Answers false if the item was notremoved, or answers true if the item was removed.

item A String identifying the name of the item.

topic A String identifying the topic to which the item belongs.

format A String identifying the format of the data.

Return value:

true Item was removed.

false Item was not in the database and could not be removed.

servers Answers a set of DdeServers that are all the manager’s current servers (thatis, connections).

testModeAnswers a Boolean indicating the current test mode.

A Windows limitation prevents a DDE client from seeing servers providedfrom the same program (.exe).

If you need to see DDE servers created from the same image as the DDEclient, set testMode to true. While testMode is true other clients cannot seethe servers from this program (.exe).

Return value:

true Test mode is on.

false Test mode is off.

testMode:Sets the current test mode. If the answer is true, it turns the test mode on.If false, it turns the test mode off.

A Windows limitation prevents a DDE client from seeing servers providedfrom the same program (.exe).

366 IBM Smalltalk: Programmer’s Reference

Page 381: IBM Smalltalk: Programmer's Reference

If you need to see local servers, set testMode to true. While testMode is true,other clients can not see the servers from this program (.exe).

timeoutReturn an Integer indicating the number of milliseconds before a servertimes out.

timeout:Sets the timeout value for any new connections.

numberOfMillisecondsAn Integer number of milliseconds.

updateItem:topic:value:format:Updates an item in the database if it exists. Then updates any links to thatitem that any DDE clients might have. The links to the item are updatedeven if the item is not in the default database.

item A String identifying the name of the item.

topic A String identifying the topic to which the item belongs.

value The data that is named by item. If the format is ‘String,’ then valuemust be a Smalltalk String, otherwise it must be a ByteArray.

format A String identifying the format of the data.

DdeClass public instance methodsaddCallback:receiver:selector:clientData:

Adds a callback to one of the receiver’s callback lists.

Generally speaking, a dde object expecting to interact with an applicationdeclares one or more callback lists as resources; the application adds tothese callback lists the callbacks that are invoked whenever the predefinedcallback conditions are met. Callback lists are resources, so that theapplication can set or change the function that is invoked.

Callbacks are not necessarily invoked in response to any event; a dde objectcan call the specified routines at any arbitrary point in its code, wheneverit wants to provide a “hook” for application interaction. For example, alldde objects provide a terminationCallback resource to enable applications tointerpose a routine to be run when the DDE instance is disconnected.

This message adds a new callback to the end of the callback list. A callbackis invoked as many times as it occurs in the callback list.

callbackNameThe resource name of the callback list to which the callback is to beappended.

receiverThe object to send the callback message to.

selector The three-parameter message selector to send.

clientDataAn object to be passed to the receiver of the callback message asthe clientData parameter when the callback is invoked, or nil.

connectedAnswers a Boolean indicating whether or not the receiver is connected to aremote DDE object.

Return value:

Chapter 12. Dynamic data exchange 367

Page 382: IBM Smalltalk: Programmer's Reference

true Receiver is connected.

false Receiver is not connected.

disconnectDisconnect the DDE conversation. This causes a DdeNterminationCallbackevent.

removeAllCallbacks:Deletes all callbacks from a callback list.

This message removes all the dde instance’s callback messages identified bycallbackName, regardless of the value of the clientData associated with eachmessage. This is in contrast to removeCallback:..., which removes thespecified callback only if a specified clientData parameter also matches.

callbackNameThe resource name of the callback list to which the callback is to beremoved.

removeCallback:receiver:selector:clientData:Deletes a callback from a callback list.

This message removes a callback message identified by callbackName.

The callback is removed only if both the callback object and clientDatamatch a callback/data pair in the list. No warning message is generated ifa callback to be removed fails to match a callback or clientData in the list.Use removeAllCallbacks:... if you want to remove a particular callbackregardless of the value of its clientData.

callbackNameThe resource name of the callback list from which the callback is tobe deleted.

receiverThe object to match against the callback receiver in the callback list.

selector The three-parameter message selector which is to be used to matchagainst the callback in the callback list.

clientDataThe object to match with the clientData object in the callback listentry.

timeoutAnswers an Integer indicating the timeout value in milliseconds.

timeout:Sets the timeout value for this DDE conversation.

numOfMillisecondsAn Integer number of milliseconds.

DdeServer public instance methodsdisconnect

Disconnect this DDE conversation. This causes a DdeNterminationCallbackevent.

notifyClientOfSupportFor:Notifies the client attempting a connection that the receiver supports the

368 IBM Smalltalk: Programmer’s Reference

Page 383: IBM Smalltalk: Programmer's Reference

specified topic. If the server wants to notify the client that multiple itemsare supported, this message can be sent multiple times, once for each topicsupported.

topicStringA String identifying the topic.

A new DdeServer is created to support this connection.

sendItem:value:format:Sends data to the client. Answers true if the data was received by theclient, false otherwise.

item A String to identify the data.

value The data that is to be sent to the client. If the format is ‘String,’ thevalue must be a Smalltalk String. Otherwise, value must be aByteArray.

format A String identifying the format that the data is in.

Return value:

true Client received the item.

false Client did not receive the item.

DdeClient public instance methodscoldLink:format:

Tells the server to disconnect a link.

item A String identifying the item to disconnect.

format A String identifying the format of the item to be disconnected.

Return value:

true The server disconnected the link to the item.

false The server cannot disconnect the link to the item.

connect:topic:Attempts to connect to a DDE server identified by applicationString withtopic topicString. Only the first server to acknowledge is connected. Allother connections are terminated. Processing of the connections from theservers happens elsewhere. Answers true if the receiver is connected.Otherwise, answer false.

applicationStringA String identifying the name of the application to connect to.

topicStringA String identifying the name of the application’s topic to beconnected to.

Return value:

true The connection was made.

false The connection cannot be made.

execute:Asks the server to run a command string on behalf of the receiver.Answers true if the server ran the command. Otherwise, answers false.

Chapter 12. Dynamic data exchange 369

Page 384: IBM Smalltalk: Programmer's Reference

commandStringA String identifying the command to be run by the server.

Return value:

true The server runs the command.

false The server cannot run the command.

free Frees any allocated resources. After this message is sent, the receiver isinvalid and cannot be used.

hotLink:format:Attempts to create a link to item so that when the item is updated by theserver, a callback (DdeNdataCallback) is called, sending the data as part ofthe callback.

Answers a Boolean indicating whether the server accepted the request.

item A String identifying the name of the item to hotlink to.

format A String identifying the format that the data should be in when itcomes back from the server.

Return value:

true The item is hotlinked.

false The item cannot be hotlinked.

queryAllQueries all servers for all topics. Answers a Dictionary of Sets with theapplication name as the key and a Set of topic names as the value.

queryServersFor:Queries all servers for a topic. Answers a Set of applications (instances ofString) that handle the topic.

topicStringA String naming the topic of interest.

queryTopicsFrom:Queries a server for all topics that it supports. Answers a Set of topics(instances of String) that are handled by the application.

applicationStringA String identifying the name of the server.

requestData:format:Requests data from the server.

item A String identifying the name of the item to retrieve.

format A String identifying the format that the data should be in when itcomes back from the server.

Return value:

nil The server could not provide the data.

String The format requested was ‘String’ and, therefore, the data from theserver is a Smalltalk String.

ByteArrayThe format requested was something other than ‘String’ andtherefore the data from the server is a ByteArray.

370 IBM Smalltalk: Programmer’s Reference

Page 385: IBM Smalltalk: Programmer's Reference

send:value:format:Sends data to the server. This is a DDE “poke”.

item A String identifying the name of the item to send to the server.

value The data that is to be sent to the client. If the format is ‘String,’ thevalue must also be a Smalltalk String. Otherwise, value must be aByteArray.

format A String identifying the format that the data should be in when itis returned from the server.

Return value:

true The server accepts the data.

false The server rejects the data or a time out has occurred.

warmLink:format:Attempts to create a link to item so that when the item is updated by theserver, a callback (DdeNdataCallback) is called. The data is not sent as partof the callback.

item A String identifying the item to disconnect.

format A String identifying the format of the item to be disconnected.

Return value:

true The item is warmlinked.

false Item cannot be warmlinked.

When the ENVY/Image DDE Examples configuration map is loaded, one of theapplications that is loaded is DdeExamples. This application contains a number ofclasses that facilitate the testing of the DDE classes. The loading of this applicationrequires that the ENVY/Swapper configuration map be loaded.

Protocols common to DdeServer and DdeClientThe following protocols are common to DdeClient and DdeServer:

TimeoutsBoth DdeClient and DdeServer objects can associate timeout values with their DDEconversations. Because the IBM Smalltalk DDE model is synchronous, the timeoutvalues are used to time out responses to DDE requests across the connection. If aresponse to a DDE requests timeout, then the value returned from the requestmessage is either nil or false, depending upon the context of the particular requestmessage. In other words, a timeout looks like a failure for the request message.The timeout value can be set with the timeout: message in the following way:ddeClient timeout: numberOfMilliseconds

orddeServer timeout: numberOfMilliseconds

The DdeServerManager also has a timeout: message that sets the timeout value forany new DdeServer connections that are made.

The default timeout value is set to 1000 milliseconds (1 second).

Chapter 12. Dynamic data exchange 371

Page 386: IBM Smalltalk: Programmer's Reference

DisconnectBoth the DdeClient and the DdeServer can disconnect the DDE conversation at anytime if they are sent the disconnect message:ddeClient disconnect

orddeServer disconnect

FreeAny DdeClient or DdeServerManager must be sent the free message when they areno longer required by their respective applications. This cleans up and releases anyoperating system resources that these objects have allocated. For example:ddeClient free.

orddeServerManager free.

Converting Smalltalk objects to a ByteArray and backThe following section provides information for these earlier sections:v “An example DDE server that uses default processing” on page 344v “Discussion of the DdeServerManager” on page 352v “An example DDE client” on page 358

The example method DdeTimeServer>>flatten: (in the DdeExamples application)converts a Smalltalk object into a ByteArray. The code to do this (using the IBMSmalltalk Swapper) is:flatten: anObject

"Flatten anObject into a ByteArray."| aByteArray size dumper |dumper := ObjectDumper new.size := dumper totalSizeBeforeUnload: anObject.aByteArray := Array with: (ByteArray new: size).dumper

unload: anObjectintoByteObjects: aByteArrayoffsetsIntoByteObjects: 0maximumLimit: sizeerrorStream: Transcript.

|aByteArray at: 1

The example method DdeTimeClient>>unflatten: (in the DdeExamples application)converts a ByteArray object into a Smalltalk object. The code to do this (using theSwapper) is:unflatten: aByteArray

"Answers an object from a ByteArray.Call the Swapper ObjectLoader to rebuild the object."| bytes |bytes := Array with: aByteArray.|ObjectLoader new

loadFromByteObjects: bytesoffsetsIntoByteObjects: 0errorStream: nil.

Test casesYou can run the following test cases to exercise some of the DDE functionsdescribed in this chapter.

372 IBM Smalltalk: Programmer’s Reference

Page 387: IBM Smalltalk: Programmer's Reference

SpreadsheetTo run this test case evaluate the following:DdeSpreadsheetClient new open

This opens up a window with a menu named DDE. Next start Microsoft Excel(Excel version 4.0 is used in this example) and fill in two cells with numbers.Under the Microsoft Excel menu Formula choose Define Name. This optionenables these cells to be named x and y, respectively. Save the spreadsheet with thename ddesrvr.xls. (The DDE client looks for a server with this name.)

The window in this test case provides a menu for the following:v Connecting to the spreadsheetv Hotlinking, warmlinking, and coldlinking to the two itemsv Requesting the items from the server

There is also a menu option for bringing up a dialog showing the available servers,topics, and items.

Spreadsheet window coordinatesTo run this test case evaluate the following:

This opens up a window such that whenever the mouse passes over the window,the x and y position of the mouse is displayed in the upper left corner of thewindow. The name of the server is ‘DdeExample,’ and there is a topic named‘Mouse.’ Under this topic there are two items ‘xpos’ and ‘ypos.’

Next, start up Microsoft Excel and in a cell enter:=DdeExample|Mouse!xpos

And in another cell enter:=DdeExample|Mouse!ypos

As the mouse is moved over the Smalltalk window, the coordinates change in thespreadsheet.

Two windows exchanging dataTo run this test case, evaluate the following:DdeTestClient new open.DdeTestServer new open.

This opens up two windows—one a DDE client and the other a DDE server. Bothwindows are able to interact with each other for the exchange of informationthrough DDE.

The menu items on the DDE server enable the server to update the item. Themenu items on the DDE client enable the client to connect to the server,hotlink/warmlink/coldlink to the data item, request data from the server, pokedata to the server, and ask the server to run a command. The client can also bringup a dialog showing the available servers, topics, and items.

When the server sends the item, it uses the IBM Smalltalk Swapper to flatten theSmalltalk object into a ByteArray, and the client uses the Swapper to turn theByteArray back into a Smalltalk object before displaying it in the Transcriptwindow.

Chapter 12. Dynamic data exchange 373

Page 388: IBM Smalltalk: Programmer's Reference

Updating time and dateTo run this test case, evaluate the following:DdeTimeServer new.DdeTimeClient new.

This creates a server and a client that do not have an interface but are primarily foruse as example code. The server in this case hooks to a timer and updates a timeand date item. The client connects to the server and hotlinks to the time and date.When the items are updated, the client displays the time/date in the Transcriptwindow.

The time and date items in this test case are in the ‘Smalltalk Object’ format. As in“Two windows exchanging data” on page 373, the client and server use theSwapper to convert a ByteArray to/from a Smalltalk object.

Updating time in the String formatTo run this test case, evaluate the following:DdeTimeServer2 new.

This creates a server as in “Updating time and date”, but only the current time inthe ‘String’ format is supported. The client from “Updating time and date” doesnot work with this server. Instead, use Microsoft Excel by entering into a cell:= Timer|Time!time

The current time appears in the cell. It is in a floating point format but can bechanged by choosing Format/Number from the menu.

Platform-specific supportThe IBM Smalltalk DDE subsystem was developed as an extension to the DDEsupport provided by IBM OS/2 and Microsoft Windows. The following figureillustrates the layers provided by the IBM Smalltalk DDE subsystem.

Application

IBM Smalltalk DDE

platform interfaceclasses and methods

IBM Smalltalk

IBM Smalltalk

The application programmer can skip the provided IBM Smalltalk DDE layer andprogram directly to the operating system support mechanisms in the platforminterface layer.

In the platform interface layer, objects have been created for all C data types forboth IBM OS/2 and Microsoft Windows. These data types include items such asDDEACK, DDEADVISE, DDEDATA, and HWND for Microsoft Windows, orDDEINIT, DDESTRUCT, CONVCONTEXT, and HWND for IBM OS/2. These dataobjects are named by prefixing the data type name with OS, and applying

374 IBM Smalltalk: Programmer’s Reference

Page 389: IBM Smalltalk: Programmer's Reference

bicapitalization rules. For example, HWND becomes OSHwnd. Additionally, eachoperating system C function has been converted to a corresponding Smalltalkmethod. To understand this conversion, consider the standard OS/2 functionWinDdePostMsg:WinDdePostMsg( hwndDest, hwndSource, msg, ddeStruct, 1)

This function has been converted to the following:OSHwnd>>winDdePostMsg: hwndFrom wm: wm pddest:pddest

flOptions:flOptions

In translating C functions to Smalltalk, two rules have been applied:v If there is no Smalltalk object that corresponds to the first parameter, then the

receiver of the message is OSCall. Otherwise, the receiver is the first parameterof the function.

v The Smalltalk message selector is formed from the C function name and theremaining parameter names.

Chapter 12. Dynamic data exchange 375

Page 390: IBM Smalltalk: Programmer's Reference

376 IBM Smalltalk: Programmer’s Reference

Page 391: IBM Smalltalk: Programmer's Reference

Chapter 13. National Language Support

National Language Support (NLS) can be very important. Today’s internationalbusiness climate often requires that application designers support the globalmarketplace and invest in NLS enablement in the initial design stages. IBMSmalltalk supports this process.

This chapter describes:v IBM Smalltalk National Language Supportv Tools for developing international software

Overview of IBM Smalltalk National Language SupportIBM Smalltalk implements common NLS protocols modeled after the POSIX.1Standard for Information Technology (IEEE Std. 1003.1-1990). This ANSI-C basedapproach has also been adopted by X Release 5.

IBM Smalltalk adds NLS support classes and extends existing classes to supportplatform-specific character sets, collation order, currency, date format, and timeformat.

NLS concepts and definitionsThis chapter assumes familiarity with the following terms.

Coded character setCharacters that define how integer code points are interpreted anddisplayed. A code point is simply a numeric value—its semanticinterpretation (for example, a vowel, whitespace, or punctuation) andgraphical interpretations (that is, associated glyph) are defined by thecoded character set associated with the code point.

Note: A coded character set is sometimes referred to as a code page orcode set. For the purposes of this chapter these terms aresynonymous.

Composite messageA localized message composed of several smaller localized strings andassembled at run time (typically using message templates).

ExternalizationThe process of separating language- and culture-dependent informationfrom the processing of an application. For example, messages displayed tousers are often hard-coded into applications and limit the usefulness of theapplication outside of the language and culture for which it was designed.The process of externalization enables the application to be easily adaptedfor use in numerous locales.

External message dictionaryA dictionary (usually a pool dictionary) that contains localized messagesfor a particular locale and character set, stored in a disk file.

Indexed external messageA localized message that is further identified and accessed by an integerkey and is stored in a disk file.

© Copyright IBM Corp. 1994, 2000 377

Page 392: IBM Smalltalk: Programmer's Reference

InternationalizationThe process of designing an application in a manner that is independent ofthe local customs and culture in which it was developed. In practice, thismeans ensuring that the application makes no assumptions aboutlanguage, local customs, or character set, thus creating an application thatis location-neutral.

Note: Internationalization is referred to as NL-enablement orNLS-enablement. An internationalized application is often termedNLS-enabled.

LanguageThe whole body of written words and system of combining words used bya particular group of people; for example, English or French.

LocaleA language/territory combination that dictates conventions for thepresentation of information, such as collation order, character classification,monetary and numeric formats, and date and time formats. Both languageand territory are necessary to identify a locale because the same languagemight be spoken in many geographic areas, each of which has distinctcultural conventions.

Note: A country might, but does not necessarily, identify a particularlocale. For example, Canada supports two distinct locales: FrenchCanada and English Canada. Simply knowing that an application isdestined for Canada is insufficient.

LocalizationRefers to the process of adapting software to a particular locale (language,territory, and character set). An internationalized application contains nocode that is dependent on the end user’s language, the characters neededto represent the language, or any formats such as time, date, and currencythat the user expects to see and interact with. Because the language- andculture-dependent information is separate from the application sourcecode, the application does not need to be rewritten or recompiled to bemarketed in different countries. Instead, the only requirement is for theexternalized information to be localized by translation experts.

Localized messageA message string that has been designed for a specific locale and characterset combination. Localized messages are referenced in application codethrough identifiers that are independent of locale and character set.

Message catalogA file that resides in secondary storage that can contain indexed externalmessages and external message dictionaries. A single message catalogmight contain indexed external messages and external message dictionariesfor multiple locale and character set combinations.

Message templateA string template containing field identifiers that are replaced with stringarguments to form a composite message. For example, binding themessage template ″This is a %1 message template″ with the string ″useful″produces the composite message ″This is a useful message template.″

378 IBM Smalltalk: Programmer’s Reference

Page 393: IBM Smalltalk: Programmer's Reference

TerritoryA linguistic or cultural entity that might or might not correspond to ageographic area; for example, Arabic, Canadian, Japanese, Mexican, andYugoCroatian.

The POSIX locale modelThe POSIX locale model divides locale-dependent information into six localecategories that assist in the development of internationalized applications. Eachlocale category controls the behavior of a predefined set of operations and isassociated with a particular locale. Locale categories are represented by symbolicconstants describing their function and are prefixed by LC_. The locale categoriesdefined by the POSIX model are listed in the following figure, along with a briefdescription of the responsibilities and functions controlled by each category.

LC_MESSAGES

LC_NUMERIC

LC_TIME

LC_MONETARY

LC_CTYPE

POSIX Locale

LC_COLLATE Responsibility:Functions:

Responsibility:Functions:

Responsibility:Functions:

Responsibility:Functions:

Responsibility:Functions:

Responsibility:Functions:

Controls string collation (sort order).strcoll(), strxfrm().

Controls character classification & conversion.isalpha(),islower(),ispunct(),isspace(),isupper(),toupper(),tolower().

Controls printing of monetary values.localeconv().

Controls the language in which messages are displayed.nl_info() / langinfo().

Controls the printing of numeric values.localeconv().

Controls the printing of dates and times.strfmtime().

Each locale category controls the behavior of a predefined set of operations andensures that the operations under its control behave properly for the localeassociated with the category. For example, the LC_COLLATE category maintainsinformation pertinent to string sorting, and, if configured for the U.S. Englishlocale, ensures that strings are sorted according the rules for U.S. English.

Locale categories function independently within an application and need not beassociated with the same locale. For example, it is possible for an application toformat monetary quantities according to the rules for U.S. English and to displaymessages in French by setting the LC_MONETARY and LC_MESSAGES categoriesappropriately.

Each process (application) maintains its own set of locale category information, andcan configure the locale categories appropriately for the needs of the application.The POSIX locale model provides a well defined set of locale-sensitive operationsand a mechanism for controlling the behavior of these operations. By using theselocale-sensitive operations, the same internationalized application can supportseveral locales simply by altering the settings of the locale categories.

Overview of internationalizationA perfect internationalized application contains no code that is dependent on theend user’s language, on the characters needed to represent the language, or on anyformats such as time, date, and currency that the user expects to see and interactwith. In order to minimize the cost of localizing an application (adapting it for aparticular locale) the following elements should not be represented explicitly inapplication code:v Displayed message strings, including the following:

– Help text– Menu items– Prompts– Labels– Error messages

Chapter 13. National Language Support 379

Page 394: IBM Smalltalk: Programmer's Reference

v Other locale-dependent information, including the following:– Bitmaps– Icons– Geometry

When language- and culture-dependent information is separate from theapplication source code, the application does not need to be rewritten to bemarketed in different countries. Instead, the only requirement is for theexternalized information to be localized by translation experts.

Overview of localized messagesLocalized messages are dependent upon the language and territory in which theyare intended to be used, and on the availability of the characters used to representtheir contents. This means that localized messages are associated with a specificlocale and character set. Character sets and fonts are closely related, and aredescribed in detail in the latter part of this section.

The following figure shows the relationship between localized messages, locales,and character sets:

Localized Message Contains Message texte.g. ’This is an english message’

Locale Character Set

depends-on

e.g. *(’english’ ’us’) e.g. ’iso5658-1’

Common Graphics SubsystemCLDT subsystem

The Common Language Data Types (CLDT) subsystem provides the class Locale tohelp determine the current language and territory. These values can be obtained byevaluating Locale current language and Locale current territory. The languageand territory of a localized message determine what message text should bedisplayed.

The IBM Smalltalk Common Widgets subsystem enables you to explicitly specifythe font used by a particular widget. If localized text is to be displayed correctly, itis critical that you be aware of the fonts (and their coded character sets) that areused in widgets that display this text.

A coded character set defines a mapping between code points (Characters) andglyphs. A character set, in conjunction with a locale, also defines the semanticvalue of a Character (for example, whether the Character is uppercase, lowercase, adigit, or so on).

380 IBM Smalltalk: Programmer’s Reference

Page 395: IBM Smalltalk: Programmer's Reference

The following figure shows the relationship between fonts, code points, andglyphs.

Code Point (Character)

65

Font

65

64

63

66..

.

Character Set(e.g. iso8859-1)

Other font information

Displayed GlyphA

B

?

>

In addition to font metrics such as size (for example, 11 point) and style (forexample, bold, italic) every font maintains a mapping from character values tographical representations, called a coded character set. The coded character setassociated with a font determines how an character value is translated into itsgraphical representation.

The translation of code points into their visual representation might necessitatethat a single localized message for a particular locale be stored separately for eachsupported character set. Consider the font ‘-microsoft-courier new-bold-i-normal-0-0-96-96-m-0-iso8859-1,’ whose character set is ‘iso8859-1.’ In this font, the characterwith the graphical representation à is associated with the code point 224 (Charactervalue: 224). In character set ‘ibm-437’ the same visual representation is associatedwith the code point 133 (Character value: 133). Thus, in order to display the text “àla mode”, a distinct localized message is required for each character set. It is thedeveloper’s responsibility to ensure that localized messages are appropriate for thefont of the widgets in which they are being displayed.

Note: The Common Widgets subsystem allows you to specify the font used by aparticular widget explicitly. To display localized text correctly, you must beaware of the fonts (and their character sets) that are used in widgets thatdisplay this text.

The following code fragment demonstrates how to query a widget for the characterset used by its font. This code fragment assumes that the variable aWidget refers tothe widget whose font is being queried. Note that if the font being queried doesnot conform to the X Logical Font Description (XLFD) naming convention theCgLogicalFontDescription>>name: message can answer nil.| aWidget fontName fontDescription |...fontName := aWidget fontList fontStruct name.fontDescription := CgLogicalFontDescription name: fontName.

"If font is unknown, use iso8859-1 by default."fontDescription isNil ifTrue: [|'iso8859-1'].|fontDescription characterSet

Chapter 13. National Language Support 381

Page 396: IBM Smalltalk: Programmer's Reference

Overview of message catalogsApplications that are expected to function in several locales must display localizedmessages, and therefore require some facility to store and retrieve these messagesfor a particular locale and character set. The POSIX.1 standard does not define anymechanism for storing or retrieving localized messages; however, IBM Smalltalksupports a mechanism for storing and retrieving localized messages modeled afterthe message catalogs described by the X/Open Portability Guide.

An X/Open message catalog consists of a disk file, external to application code,that can be translated to support a variety of locales and character sets. TheX/Open message catalog identifies each message numerically and providesprotocols for opening and closing message catalogs, and for retrieving localizedmessages. Message catalogs are specified using a portable C-like text file, and arecompiled into a machine-specific (non-portable) message file.

In IBM Smalltalk, the basic mechanism for maintaining localized messages externalto the application is the NlsMessageCatalog class. Instances of NlsMessageCatalog usethe IBM Smalltalk Swapper as the basis of a platform-independent mechanism forwriting and retrieving messages to and from secondary storage. TheNlsMessageCatalog class provides protocols and a file structure designed specificallyfor storing localized messages.

Unlike an X/Open message catalog, the NlsMessageCatalog allows localizedmessages for several locales to be maintained in a single file. TheNlsMessageCatalog provides protocols for storing and retrieving Indexed ExternalMessages that are identified by numeric constants, and are used to reduce memoryrequirements of an application. The NlsMessageCatalog also provides extendedcapabilities for storing and retrieving External Message Dictionaries, which providean efficient mechanism for loading large numbers of messages.

The NlsMessageCatalog uses the following keys to identify localized messages:

languageA variable-length, lowercase, single-byte string defining the language of agiven locale. This value is taken from the IBM Smalltalk locale namingconventions described in Table 52 on page 411. For example, ‘english,’‘french.’

territoryA variable-length, lowercase, single-byte string defining the region of agiven locale. This value is taken from the IBM Smalltalk locale namingconventions described in Table 52 on page 411. For example, ‘us,’ ‘arabic.’

coded character setA variable-length, single-byte string describing the character set of the fontthat is used by widgets to display the localized messages. This value isplatform dependent and is provided by the Common Graphics subsystem.For example, ‘ibm-437,’ ‘iso8859-1.’

Locating message catalogsThe X/Open UNIX standard defines an environment variable called NLSPATH thatspecifies the directories to be searched for localized files. The Locale class providessimilar facilities for IBM Smalltalk applications through the NlsPath variable, whichcontains a collection of directory paths to search for message catalogs.

382 IBM Smalltalk: Programmer’s Reference

Page 397: IBM Smalltalk: Programmer's Reference

The nlsPath and nlsPath: methods are provided to query and set the value of theNlsPath variable. The value of the NlsPath variable is not affected by reinitializingthe current locale.

Note: All NlsMessageCatalog protocols that read from a specified path first assumethe path to be absolute. If the first attempt to open this file fails, it isassumed to be a relative path name located in one of the directoriesspecified by Locale nlsPath. Therefore, once NlsPath is set, you need onlyspecify the name of the desired message catalog when using theNlsMessageCatalog read operations described in the following section.

National Language Support classesIn IBM Smalltalk, the six locale categories defined by the POSIX model aresupported by the classes LCCollate, LCCType, LCMonetary, LCMessages, LCNumeric,and LCTime. The class Locale provides access to the current settings of localecategories, and protocols to update locale categories from values specified by theoperating system.

An instance of class Locale is created and initialized with the currently configuredplatform locale information at image startup. This instance is known as the currentlocale and can be accessed by sending current to the Locale class. The current localecannot be set explicitly, only initialized from operating system values.

The current locale maintains instances of the LCCollate, LCCType, LCMonetary,LCMessages, LCNumeric, and LCTime classes that are used to control date and timeprinting, character sorting, and string sorting. A detailed description of theseobjects, and the protocols used to access them, is presented in the sections entitled“Obtaining Locale, LCCType, and LCCollate objects” on page 384 and “ObtainingLCMessages, LCMonetary, LCNumeric, and LCTime objects” on page 385. Allapplications concerned with NLS enablement should use the information availablefrom the current locale.

Support for double-byte charactersThis section describes the classes that provide support for double-byte characters.This section is of particular interest to developers whose applications will bedeployed in languages such as Japanese where the size of the alphabet exceeds 255characters and thus requires the use of double-byte characters.

CharactersCharacters are defined to be unique objects that represent code points. Single-bytecharacters are restricted to values in the range 0 to 255. Double-byte charactershave values in the range 0 to 65535. The interpretation of character values isdependent on a coded character set. Several Character protocols (that is, theprotocols concerned with collation, character classification, and case conversion)have been refined or extended to be consistent with National Language Supportrequirements.

String classesThe classes String and DBString are used to represent sequences of characters inIBM Smalltalk. DBString represents a sequence of Characters that can take valuesbetween 0 and 65535 (that is, double-byte characters). Similarly, String represents asequence of Characters that can take values between 0 and 255 (that is, single-bytecharacters). Both String and DBString support efficient character-based accessingand indexing operations. Common Widgets and Common File System subsystem

Chapter 13. National Language Support 383

Page 398: IBM Smalltalk: Programmer's Reference

protocols answer and accept instances of String or DBString as appropriate for thecurrent locale and object being passed or returned.

IBM Smalltalk does not support Symbols containing double-byte characters.

Sending the message asDBString converts a String or DBString into a DBString.Sending the message asSBString to an instance of String answers the receiver,because it cannot contain double-byte characters. Sending asSBString to an instanceof DBString converts the receiver into a String if possible; however, this messagefails if the receiver contains characters with values greater than 255, in which casenil is returned.

Attempting to store a Character with value greater than 255 into a String is an error.IBM Smalltalk provides the Locale>>isDBLocale method to determine if a locale usesdouble-byte characters. The isDBLocale message answers a boolean value indicatingwhether or not the receiver locale uses double-byte characters.

A locale that supports double-byte characters should use DBString as its stringclass. When sent to an instance of Locale, the preferredStringClass message answerseither String or DBString, whichever class is appropriate for the locale representedby the receiver. For example, if the current locale is #(’japanese’ ’japan’), thenpreferredStringClass answers DBString.

The preferredStringClass message is of particular use in creating streams used inapplication code. For example, the practice of writingWriteStream on: String new.

results in an exception if a double-byte character (a Character with value greaterthan 255) is ever appended to this stream. The following code is portable, and usesthe string class appropriate for the current locale.WriteStream on: Locale current preferredStringClass

new.

Obtaining Locale, LCCType, and LCCollate objectsThe platform default locale is defined as the current set of international andformatting values available from the operating system. This is the only locale thatis always guaranteed to be available.

If the information obtained from the operating system identifies the platformdefault locale as one of the IBM Smalltalk supported locales (see the sectionentitled “Locales and platform representation” on page 415), then the language andterritory fields of the current locale are set accordingly. If the platform defaultlocale cannot be identified, the territory and language fields are set to the string‘<unknown>.’ It is possible that the information obtained from the operatingsystem might only partially identify a locale (that is, either the language orterritory). In such a case the value that cannot be determined is set to the string‘<unknown>.’

The class LCCType has only one valid instance in the image, and no protocols areprovided to create new instances explicitly. New instances of Locale and LCCollateare obtained by sending new to the classes. These instances of Locale and LCCollatecan be localized manually using the protocols described in “Manual localization”on page 412.

384 IBM Smalltalk: Programmer’s Reference

Page 399: IBM Smalltalk: Programmer's Reference

When the current locale is initialized, new LCCType and LCCollate objects arecreated, initialized, and stored. The current LCCType and LCCollate objects can beretrieved by sending the lcCType and lcCollate messages to the current locale(Locale current).

Upon successful initialization of the current locale the relocalize message is sent toevery application and subapplication currently loaded in the image, in prerequisiteorder (that is, Kernel first). Applications can use this mechanism to perform anyrequired locale-specific configuration.

Obtaining LCMessages, LCMonetary, LCNumeric, and LCTimeobjects

When the current locale is initialized, new LCMessages, LCMonetary, LCNumeric,and LCTime objects are created, initialized, and stored. The current LCMessages,LCMonetary, LCNumeric, and LCTime objects can be retrieved by sending thelcMessages, lcMonetary, lcNumeric, and lcTime messages to the current locale (Localecurrent).

Multiple instancesIBM Smalltalk supports the use of multiple LCMessages, LCMonetary, LCNumeric,and LCTime objects. Each instance of these classes maintains information for aparticular locale and can be created using the for: protocol. The argument to the for:message is an array of two strings specifying the language and territory for whichinformation is to be retrieved.

New instances for the platform default localeNew instances of the LCMessages, LCMonetary, LCNumeric, and LCTime classes canbe created and initialized for the platform default locale using the for: protocol andan array of two empty strings—that is, #(’’ ’’)—as the parameter. This platformdefault value is always guaranteed to be available. The following code exampleanswers a new LCMonetary object initialized for the platform default locale.LCMonetary for: #('' '')

New instances for different localesNew instances of the LCMessages, LCMonetary, LCNumeric, and LCTime classes canbe created, and initialized, for a particular locale using the for: protocol and anarray containing the language and territory strings of the requested locale as theargument. For a complete list of valid language and territory combinations, refer toTable 52 on page 411. You can see what language and territory combinations youroperating system supports by evaluating Locale knownLocales.

If the information for the requested locale is not available, the for: message answersnil. Otherwise, the newly created and initialized object is answered. The followingcode fragment queries the operating system for the monetary formattinginformation for the territory 'us' and language 'english.' Note that the territoryand language strings must be in lowercase.LCMonetary for: #('english' 'us')

Example usage of locale-specific informationThe following method uses the current Locale and LCMessages, to print a list ofitems using the locale-defined data separator:printedItems: anIndexableCollection

"Print the items in anIndexableCollection separated by the data separatorfor the current locale."

| stream sep |

Chapter 13. National Language Support 385

Page 400: IBM Smalltalk: Programmer's Reference

sep := Locale current lcMessages dataSeparator.stream := WriteStream on: Locale current preferredStringClass new.1 to: anIndexableCollection size - 1 do: [:index |

(anIndexableCollection at: index) printOn: stream.stream nextPutAll: sep].

anIndexableCollection last printOn: stream.|stream contents

NLS-enabled classesSeveral base classes in the image make use of locale-dependent information heldby the current locale (Locale current). A summary of these classes follows:

Character (CLDT)<=, <, >=, >

Collates characters according to the collation ordering for the U.S. Englishlocale on OS/2 3.0 and Microsoft Windows 3.11, or the collation orderingfor the C locale on X-Motif.

asLowercase, asUppercasePerforms case conversions according to the LCCType object associated withthe current locale (Locale current lcCType).

isAlphaNumeric, isDigit, isLetter, isLowercase, isPunctuation, isUppercasePerforms character classification according to the LCCType object associatedwith the current locale (Locale current lcCType).

LCCollate (NLS)compareCharacter:and:

Collates characters according to the LCCollate object associated with thecurrent locale (Locale current lcCollate).

compareString:and:Collates strings according to the LCCollate object associated with thecurrent locale (Locale current lcCollate).

Date (CLDT)printOn:

Prints the date in the format specified by the LCCTime object associatedwith the current locale (Locale current lcTime).

String (CLDT)<=, <, >= , >, sameAs:

Collates characters according to the collation ordering for the U.S. Englishlocale on OS/2 3.0 and Microsoft Windows 3.11, or the collation orderingfor the C locale on X-Motif.

asLowercase, asUppercasePerforms case conversions according to the LCCType object associated withthe current locale (Locale, current lcCType).

Time (CLDT)printOn:

Prints the time in the format specified by the LCTime object associated withthe current locale (Locale current lcTime).

386 IBM Smalltalk: Programmer’s Reference

Page 401: IBM Smalltalk: Programmer's Reference

Locale-specific sortingThe String and Character collation operations use collation ordering for U.S. Englishon Windows and OS/2 3.0, and the ordering for the C locale on X-Motif. Youshould use the compareString:and: and compareCharacter:and: methods provided byLCCollate to perform locale-specific sorting. You can use a SortedCollection to sort acollection based on the current locale by specifying a sort block that uses thecurrent LCCollate instance. See the following example:"Warning: do not retrieve the lcCollate from the locale inside thesort block because if the locale is changed the Sorted Collectionmay become inconsistent."| lcCollate |lcCollate := Locale current lcCollate.|SortedCollection sortBlock: [:a :b |

(lcCollate compareString: a and: b) = 2 ].

Number formatting

Currency symbol, spacing, and sign locationsYou format monetary values using a combination of the pSepBySpace, pSignPosn,pCsPrecedes, nSepBySpace, nSignPosn, and nCsPrecedes values. The first three valuesare used when formatting positive values, and the last three when formattingnegative values. Together these variables control the relative positions of thecurrency symbol and sign indicator. Instances of the LCMonetary class are used tohold these parameters for a particular locale.

The following table illustrates the use of these parameters in formatting thenon-negative monetary value 1.25. The same formatting rules are also used toformat negative monetary values by changing the positive sign character to anegative sign character.

The pCsPrecedes value indicates the relative position of the currency symbol informatted monetary qualities.0 The currency symbol follows the monetary quantity.1 The currency symbol precedes the monetary quantity.

The SepBySpace value indicates if the currency symbol is separated from themonetary quantity by a space in formatted monetary quantities.0 No space separates currency symbol from monetary quantity.1 A space separates currency symbol from monetary quantity.2 A space separates currency symbol and positive sign if adjacent.

The pSignPosn value specifies the relative position of the positive sign stringformatted monetary quantities.0 Parentheses enclose both the quantity and the currency symbol.1 The positive sign follows the quantity and the currency symbol.2 The positive sign follows the quantity and the currency symbol.3 The positive sign immediately precedes the currency symbol.4 The positive sign immediately follows the currency symbol.

Table 47. Numeric formats specified by currency symbol, spacing, and sign location

pSepBySpace

2 1 0

Chapter 13. National Language Support 387

Page 402: IBM Smalltalk: Programmer's Reference

Table 47. Numeric formats specified by currency symbol, spacing, and signlocation (continued)

psCsPrecedes = 0 pSignPosn = 0 (1.25 $) (1.25$) (1.25$)

pSignPosn = 1 +1.25 $ +1.25 $ +1.25 $

pSignPosn = 2 1.25$ + 1.25$ + 1.25$ +

pSignPosn = 3 1.25 +$ 1.25 +$ 1.25 +$

pSignPosn = 4 1.25 $+ 1.25 $+ 1.25 $+

pCsPrecedes = 1 psignPosn = 0 ($1.25) ($1.25) ($1.25)

pSignPosn = 1 + $1.25 + $1.25 + $1.25

pSignPosn = 2 $1.25 + $1.25 + $1.25 +

pSignPosn = 3 + $1.25 + $1.25 + $1.25

pSignPosn = 4 $+ 1.25 $+ 1.25 $+ 1.25

Numeric groupingsA grouping string is used to specify the size of each group of digits in formattedmonetary and numeric quantities. The grouping string consists of a series ofnumbers separated by spaces. The first number in the string indicates the size ofthe group of digits immediately to the left of the decimal indicator.

The following numbers have special meaning in the grouping string:127 Perform no further grouping0 Repeat last grouping

The effects of the grouping string on monetary formatting are most easilyvisualized by example. The following table illustrates formatting the number123456789 as a function of the grouping string, using a comma as the separator.

Table 48. Use of the grouping string to format numeric values

Grouping string Resultant formatted numeric quantity

‘3’ 123456,789

‘3 0’ 123,456,789

‘3 2’ 1234,56,789

‘3 2 127’ 1234,56,789

‘3 2 0’ 12,34,56,789

‘127’ 123456789

‘’ 123456789

Locale change notification and the image startup sequenceA special SubApplication class protocol is provided to enable applications toreconfigure in response to Locale initialization.1. The current Locale is determined based on the platform default locale.2. The message preStartUp is sent to all loaded (sub)applications in prerequisite

order.3. The message localize is sent to all loaded (sub)applications in prerequisite order.4. The message startUp is sent to all loaded (sub)applications in prerequisite

order.

388 IBM Smalltalk: Programmer’s Reference

Page 403: IBM Smalltalk: Programmer's Reference

Applications can override the localize method to perform any requiredlocale-specific configuration.

Note: The Locale class is initialized automatically at image startup, and can bereinitialized manually by evaluating Locale initializeCurrentLocale. Forexample, when using Windows 3.11, you might want to update the currentlocale after changing the settings in the International control panel.

SubApplication classlocalize

This message informs currently loaded Application and SubApplicationclasses that the current locale has been changed. This message is sent to allloaded Application and SubApplication classes on image startup, and eachtime the current locale is successfully initialized (that is, by evaluatingLocale initializeCurrentLocale).

Tools for developing international softwareThis section describes the IBM Smalltalk tools that assist in the development ofinternationalized applications by externalizing displayed messages such as helptext, menu items, and labels.

Loading externalization toolsTools provided to assist in developing internationalized software are contained in aconfiguration map entitled IBM Smalltalk NLS Externalization that includes thefollowing applications:

NlsExternalizationRuntimeThis application provides the classes and protocols required for readinglocalized text at runtime.

NlsExternalizationToolsThis application provides additional protocols for creating files that containlocalized text, and for converting these files to platform resource formats.

Using message templatesMany applications use language-dependent text throughout to provide localizedmenu selections, warning and error message descriptions, and help text. Often, thedisplay of language-dependent text requires the insertion of locale-dependentstring arguments into a message template. The processing used to construct acomposite message from various components can introduce unwanted languagedependencies and can act as a barrier to localization. The following example showsa locale-specific way to construct a composite message:displayWarningFor: userName operation: anOperation

"Display a warning message on the Transcript warning the user calleduserName that the operation called anOperation cannot be performed."Transcript

cr;show: 'Sorry, ', userName;show: ' I cannot perform', anOperation;show: '!'.

This technique is commonly used in the construction of messages displayed tousers. This technique is a barrier to localization because it embedslanguage-specific semantics in the processing used to construct the message. Somelanguages might require that the contents of the userName field appear after theanOperation field, or that a punctuation mark other than an exclamation mark (!) be

Chapter 13. National Language Support 389

Page 404: IBM Smalltalk: Programmer's Reference

used to terminate the message. The approach illustrated in the preceding examplecannot support these requirements and is not suitable for use in aninternationalized application.

IBM Smalltalk provides a mechanism for replacing tokens in a message templatewith variable arguments. A template string is a String or DBString containingconstant text and token identifiers that are replaced with arguments specified bythe developer. Token identifiers consist of a percent character (%) and a numericfield identifier in the range one to nine (1-9).

A template string is expanded based on arguments provided by the developerusing the bindWith:, bindWith:with:, bindWith:with:with:, bindWith:with:with:with:, orbindWithArguments: methods. The numeric portion of the token identifier indicateswhich argument should replace the token when the template is expanded to createa composite message (for example, %1 corresponds to the first argument, %2corresponds to the second argument, etc.). The double percent escape sequence(‘%%’) is replaced by a single percent character in the composite message.

A template string permits arguments to be printed selectively, and in arbitraryorder as illustrated in the following table. Although arguments are provided in afixed order, there is no restriction placed on their order of appearance in thetemplate string. Arguments that are not referenced in the template string areignored; an error is generated if a template string references a missing argument.

Table 49. Sample message templates and results

Sample template and arguments Resultant message

‘%1 %2 %3’ bindWith: ‘one’ with: ‘two’ with: ‘three’ ‘one two three’

‘%3 %2 %1’ bindWith: ‘one’ with: ′two’ with: ‘three’ ‘three two one’

‘%1 %2 %1’ bindWith: ‘one’ with: ‘two’ with: ‘three’ ‘one two one’

‘An %1 of embedded text’ bindWith: ‘example’ ‘An example of embeddedtext’

‘This is a percent sign %%.’ bindWith: ‘’ ‘This is a percent sign %’

‘Unused are %1.’ bindWith: ‘ignored’ with: ‘unused’ ‘Unused are ignored’

‘Missing arguments are %2.’ bindWith: ‘errors’ Exception occurs

The following example shows the use of message templates to assist ininternationalizing an application. It illustrates how the use of a message templateavoids the language-specific dependencies exhibited by the previous example.Notice that languages that require the contents of the userName field to appearafter the anOperation field, or different punctuation, can be supported simply bychanging the template string. Normally, the template string would be externalized,thereby permitting the application to be localized without modification of sourcecode.displayWarningFor: userName operation: anOperation"Display a warning message on the Transcript warning the user calleduserName (a String) that the operation called anOperation(a String) cannot be performed."

| template |template := 'Sorry, %1, I cannot perform %2!'.Transcript

cr;show: (template bindWith: userName with: anOperation).

390 IBM Smalltalk: Programmer’s Reference

Page 405: IBM Smalltalk: Programmer's Reference

Note: This example is not fully internationalized because it contains a hard-codedreference to the template 'Sorry, %1 I cannot perform %2!'. Tools andtechniques for removing hard coded references to strings are discussed in“Removing hard-coded strings”.

Referencing and initializing localized messagesThe process of removing hard-coded references to language-dependent text froman application is known as string externalization, because the process results inlanguage-dependent textual information being stored externally to the application.

Language- and culture-dependent strings in an internationalized IBM Smalltalkapplication are stored as pool dictionary variables and are accessed directly(without the need for accessor methods) in application source code. Appropriatelanguage-dependent strings are bound to language-independent messageidentifiers (pool dictionary variables) in response to changes of locale. Thus, thelanguage independent identifiers are used throughout the application source coderegardless of the target language.

The following example shows the conversion of the previous example toincorporate an externalized string reference.displayWarningFor: userName operation: anOperation

"Display a warning message on the Transcript warning the user calleduserName that the operation called anOperation cannot be performed."Transcript

cr;show:(MyAppWarningTemplate1 bindWith: Username with: anOperation).

The original template string 'Sorry, %1, I cannot perform %2!' has been replacedby a reference to a pool variable called MyAppWarningTemplate1. This method isnow language-independent and can be localized simply by modifying the value towhich the pool variable MyAppWarningTemplate1 is bound. Pool variables are mosteasily rebound using the features provided by NlsMessageCatalog.

The MyAppWarningTemplate1 pool variable must be reflected in the code thatdeclares and initializes the pool dictionaries used by the application. It is theresponsibility of each application to declare pool dictionaries and variables,initialize the values of pool variables (typically using an NlsMessageCatalog), andremove the pools when the application is unloaded.

Removing hard-coded stringsLiteral arrays containing strings require special attention when strings are beingexternalized. The manner in which Smalltalk expressions are parsed does not allowstrings in literal arrays to be replaced with pool variables because items in literalarrays are themselves assumed to be literals.messageArray

"Answer an Array of language-dependent message strings."

|('message1' 'message2' 'message3' 'message4')

Externalizing the strings contained in the method illustrated previously requiresthat the literal array be replaced with an explicitly created array. The externalizedversion is presented in the following example. Notice that the string literals havebeen replace with pool variables (Message1, Message2, etc.) and that the arraycontaining the elements is now created explicitly.

Chapter 13. National Language Support 391

Page 406: IBM Smalltalk: Programmer's Reference

messageArray"Answer an Array of language-dependent message strings."

|Arraywith: Message1with: Message2with: Message3with: Message4

Overview of the message localization processThis section illustrates the IBM Smalltalk model by demonstrating how messagesare localized in response to a change in locale and a particular character set inresponse to the localize message. The following localization process ensures that theapplication contains messages appropriate for the current locale.

For purposes of demonstration we define the class MyNlsEnabledClass that iscontrolled by MyNlsEnableApplication as follows. Further assume that the pooldictionary variables used in MyNlsMessages have initialized (via initialization code)to contain messages for an English U.S. locale and the iso8859-1 character set.Object subclass: MyNlsEnabledClass

instanceVariableNames: 'instvar1 instvar2'classVariableNames: ''poolDictionaries: 'MyNlsMessages'

Step 1: Replace hard-coded strings with pool dictionaryvariablesThe programmer has internationalized the MyNlsEnabledApplication and placed thethree messages used by the class (MsgCut, MsgCopy, MsgPaste) into a shared poolcalled MyNlsMessages. The initial state—localized for (’english’ ’us’)—of theMyNlsMessage pool is shown in the following table.

Table 50. MyNlsMessage (localized for (’english’ ’us’))

’MsgCopy’ ’Copy’

’MsgCut’ ’Cut’

’MsgPaste’ ’Paste’

Step 2: Respond appropriately to the localize messageIBM Smalltalk initializes the current locale when the Smalltalk image is started,and sends the localize message to all loaded applications. The application thatcontrols MyNlsEnabledClass responds to the localize message as follows:1. The application queries the current locale and detects that messages should be

updated for a (’french’ ’france’) locale.2. The application determines which font will be used in the widgets to display

localized messages using methods in Common Graphics. Once the font hasbeen determined, its coded character set is queried and found to be ’iso8859-1.’

3. The application retrieves messages for #(’french’ ’france’) and coded characterset ’iso8859-1’ from an external file using an NlsMessageCatalog. TheNlsMessageCatalog automatically rebinds the pool dictionary variables inMyNlsMessages.

Step 3: Ensure that messages are successfully localizedAll references to the pool dictionary variables contained in MyNlsMessages nowcontain appropriately localized messages for the current locale and the desiredcharacter set. The final state of the MyNlsMessages pool is shown in the followingtable.

392 IBM Smalltalk: Programmer’s Reference

Page 407: IBM Smalltalk: Programmer's Reference

Table 51. MyNlsMessage—localized for #(’french’ ’france’)

’MsgCopy’ ’Copier’

’MsgCut’ ’Découper’

’MsgPaste’ ’Affichier’

Using message catalogsTypically, interactive applications make extensive use of labels, menus, and helptext, all of which require localization in an international application. Aninternationalized application that fetches all localized messages at once and storesthem within the image using pool dictionary variables should not experience anydecrease in user interface response compared to an application that useshard-coded message strings. An application might also contain descriptive errormessages that are used only when an condition arises. By maintaining the localizedmessages on secondary storage and only loading them as required, the memoryrequirements of the application are reduced.

The NlsMessageCatalog has been designed to efficiently support these twopredominant uses of display text in applications through the following twomechanisms.

External message dictionariesExternal message dictionaries are designed for use when all localized messagesare to be retrieved at once and stored in a pool dictionary within Smalltalk.External message dictionaries are identified by locale and character set, and for thisreason only one message dictionary can be stored in an NlsMessageCatalog for agiven locale and character set.

An external message dictionary is a Dictionary keyed by a message identifier (pooldictionary variable name) containing localized messages. NlsMessageCatalogprovides protocols specifically tailored for storing and retrieving pool dictionariescontaining localized messages.

Advantage:High-speed loading for large numbers of messages and fast access timewhen individual messages are referenced.

Disadvantage:Requires more memory because messages are loaded from disk and storedwithin the Smalltalk image.

Indexed external messagesIndexed external messages are designed for use when messages are maintained onsecondary storage and loaded individually, as needed. Indexed external messagesare identified by locale, character set, and a numeric message identifier.

An indexed external message is a single, localized message that is identifiednumerically and stored for a particular locale and character set. TheNlsMessageCatalog provides protocols specifically tailored for storing and retrievingindexed messages. Indexed external message identifiers are integers and should beassigned sequentially starting at 1, because a collection whose size corresponds tothe largest indexed message identifier is maintained on secondary storage. Thecareful numbering of messages can reduce the amount of space needed insecondary storage.

Chapter 13. National Language Support 393

Page 408: IBM Smalltalk: Programmer's Reference

Advantage:Space savings because localized messages are stored on disk.

Disadvantage:Slower access time because messages are read from disk individually.

Note: Both indexed external messages and external message dictionaries areassociated with a particular locale and character set. Many indexed externalmessages and/or a single external message dictionary can be stored within thesame file for a given locale and character set combination.

Messages externalized using a NlsMessageCatalog (both external messagedictionaries and indexed external messages) typically contain only strings, but cancontain any Smalltalk object that can be dumped by the Swapper without specialdumping options. (Refer to the IBM Smalltalk User’s Guide for a completedescription of limitations.)

Although the NlsMessageCatalog is capable of storing Smalltalk objects other thanstrings, the developer should be aware that platform resource files cannot storearbitrary Smalltalk objects. If the message catalog is to be converted to a platformresource format, it must only contain strings.

Obtaining instances of NlsMessageCatalogInstances of NlsMessageCatalog are associated with a single disk file.NlsMessageCatalog instances are created using NlsMessageCatalog>>#on:, which takesa single String argument that specifies the absolute or relative pathname of thenew or existing message catalog file."Create an NlsMessageCatalog using an absolute path."NlsMessageCatalog on: 'c:\nls\message.cat' "Windows & OS/2”NlsMessageCatalog on: '/usr/nls/messages.cat' "UNIX"

"Create an NlsMessageCatalog in the current directory."NlsMessageCatalog on: 'messages.cat'.

Using external message dictionaries

Unloading external message dictionariesThe unload:language:territory:characterSet: protocol is used to create (or add to) amessage file that contains a dictionary of messages for a particular locale andcharacter set. The protocol can also be used to overwrite the value of an existingexternal message dictionary. You must intitialize the dictionary being dumped withthe correct keys and values before unloading. Several external message dictionariescan be stored in a single message catalog file by making repeated calls usingunload:language:territory:characterSet:.

The following example creates an NlsMessageCatalog that contains an externalmessage dictionary. This example assumes the use of a pool dictionary calledMyNlsMessages containing localized message strings. Return values of allNlsMessageCatalog operations must be checked to ensure that the operation hassucceeded."A code fragment to create a message catalog file containing 'demo.cat'containing an external message dictionary for the ('english' 'us') localeand the 'iso8859-1' character set."

| catalog |catalog := NlsMessageCatalog on: 'demo.cat'.

"Create the message catalog file."

394 IBM Smalltalk: Programmer’s Reference

Page 409: IBM Smalltalk: Programmer's Reference

(catalog unload: MyNlsMessageslanguage: 'english'territory: 'us'characterSet: 'iso8859-1') ifFalse: [

|self error: 'Unload error: ',catalog currentErrorString].

Loading messages into a pool dictionaryThe loadLanguage:territory:characterSet:intoDictionary: protocol is used to update anexisting pool dictionary with values retrieved from a message catalog file. TheNlsMessageCatalog answers a Boolean value indicating success or failure of the loadoperation.

The following example loads messages into an existing pool dictionary using anNlsMessageCatalog. The example assumes the existence of a pool dictionary calledMyNlsMessages into which all messages can be loaded. You must check the returnvalues of all NlsMessageCatalog operations to ensure that the operation hassucceeded."A code fragment to load messages from an existing message catalog filecalled 'demo.cat' for the #('english' 'us') locale and the 'iso8859-1'character set."

| catalog |catalog := NlsMessageCatalog on: 'demo.cat'.

(catalog loadLanguage: 'english'territory: 'us'characterSet: 'iso8859-1'intoDictionary: MyNlsMessages) ifFalse: [

|self error: 'Load error: ',catalog currentErrorString].

Note: No keys are added to an existing pool by theloadLanguage:territory:characterSet:intoDictionary: operation. Only the values ofthe existing keys are modified. This features ensures that unused sharedpool variables removed during packaging are not reintroduced inNlsMessageCatalog.

When pool variables are referenced directly in source code, the associationscontained in the pool dictionary are directly referenced by instances ofCompiledMethod. As a result, when a pool dictionary is localized, the associationsthat contain the localized messages must be directly modified. Assigning alocalized version of the pool dictionary to the global variable that references thedictionary does not work. The NlsMessageCatalog contains protocols that directlymodify the associations that contain localized messages and ensure consistency ofloaded messages.

Loading messages without initializing a pool dictionaryThe loadLanguage:territory:characterSet: protocol is used to load an external messagedictionary from a message catalog file without loading into a pool dictionary. TheNlsMessageCatalog answers the Dictionary of messages retrieved from disk, or nil ifan error occurs.

The following example shows how to load an external message dictionary withoutinitializing a pool dictionary. You must check the return values of allNlsMessageCatalog operations to ensure that the load operation has succeeded."A code fragment to load messages from an existing message catalog filecalled 'demo.cat' for the #('english' 'us') locale and the 'iso8859-1'character set."

| catalog |catalog := NlsMessageCatalog on: 'demo.cat'.

Chapter 13. National Language Support 395

Page 410: IBM Smalltalk: Programmer's Reference

(catalog loadLanguage: 'english'territory: 'us'characterSet: 'iso8859-1') isNil ifTrue: [

|self error: 'Load error: ',catalog currentErrorString].

Declaring pool dictionary keysThe declareKeysFor:language:territory:characterSet: message can be used to declarekeys in a pool dictionary from a message catalog file. This operation reads theexternal message dictionary for a specified language, territory, and character setfrom a message catalog file and declares new keys in a user-supplied pool.

The declareKeysFor:language:territory:characterSet: operation does not affect values ofexisting pool variables and does not remove keys from the supplied pool. Thevalues of newly declared keys are the same as the key to assist in identification ofmissing translations. The NlsMessageCatalog answers true if this operation succeeds,otherwise answers false.

The following example demonstrates how to declare pool keys from a messagecatalog file. This example assumes the existence of the pool dictionaryMyNlsMessages in which keys will be declared."Declare the pool MyNlsMessages and populate it with keys based on themessages stored for #('english' 'us' 'iso8859-1')."

| pool catalog |pool := Smalltalk declarePoolDictionary: #MyNlsMessages.catalog := NlsMessageCatalog on: 'demo.cat'.

(catalogdeclareKeysFor: poollanguage: 'english'territory: 'us'characterSet: 'iso8859-1') ifFalse: [

|self error: 'Declaration error: ',catalog currentErrorString].

Using declareKeysFor:language:territory:characterSet: can simplify the pool declarationprocess, but only if you are using an unmanaged pool dictionary. This methodcannot be used to declare keys in a managed pool.

Defining managed pool dictionariesYou can define managed pool dictionaries using variable declaration methods.When you do so, tag the pool declaration with a PRAGMA field, which identifiesthe pool dictionary as an NLS pool dictionary. The PRAGMA field is a stringprefixed by NLS followed by a space and the name of the catalog (without anextension).

You should place the following variable declaration in the application thatmanages the pool dictionary. The following variable declaration method declares apool dictionary called MyNlsMessages, which contains two pool variables (Message1and Message2) whose catalog file is mynls.cat._PRAGMA_MyNlsMessages

"%%PRAGMA DECLARE(name: MyNlsMessages isPool: true pragma: 'NLS mynls')(pool: myNlsMessages declarations: (

(name: Message1)(name: Message2)

))"

396 IBM Smalltalk: Programmer’s Reference

Page 411: IBM Smalltalk: Programmer's Reference

Deleting external message dictionariesYou can delete an external message dictionary from a message catalog file usingthe deleteDictionaryLanguage:territory:characterSet: protocol. This operation removesonly the external message dictionary stored for the specified language, territory,and character set and does not affect any indexed external messages or othermessage dictionaries. The following example demonstrates how to delete anexternal message dictionary from a message catalog file."Remove the message dictionary stored for #('english' 'us' 'iso8859-1')."| catalog |catalog := NlsMessageCatalog on: 'demo.cat'.(catalog

deleteDictionaryLanguage: 'english'territory: 'us'characterSet: 'iso8859-1') ifFalse: [

|self error: 'Deletion error: ',catalog currentErrorString].

Note: Deleting an external message dictionary does not immediately decrease thesize of the message catalog file on disk. Deleted external dictionaries aremarked as garbage and their space is reclaimed when the message catalogfile is compressed. See “Compression” on page 402 for a discussion of thecompression of message catalog files.

Deletion is a permanent operation and cannot be undone. After an external messagedictionary is deleted, it is lost.

Using indexed external messagesWhen using indexed external messages, you can perform the following operations:v Unload to create or add messagesv Load to retrieve messagesv Delete to remove messages

Unloading indexed external messagesThe unload:language:territory:characterSet:index: protocol is used to create or add anindexed message to a message catalog file for a particular locale and character set.This protocol can also be used to overwrite the value of an existing indexedexternal message. Several indexed external messages can be stored in a singlemessage catalog file by making repeated calls usingunload:language:territory:characterSet:index:. The following example illustrates theprocess of unloading indexed messages into a message catalog file. Return valuesof all NlsMessageCatalog operations must be checked to ensure that the operationhas succeeded."A code fragment to create a message catalog file called 'demo.cat'containing a single indexed external message for the #('english' 'us')locale and the 'iso8859-1' character set."

| catalog |catalog := NlsMessageCatalog on: 'demo.cat'.

"Create the message catalog file."(catalog unload: 'This is an indexed external message'

language: 'english'territory: 'us'characterSet: 'iso8859-1'index: 1) ifFalse: [

|self error: 'Unload error: ',catalog currentErrorString].

Loading indexed external messagesThe loadLanguage:territory:characterSet:index: protocol retrieves an indexed externalmessage from a message catalog file. The NlsMessageCatalog answers the message

Chapter 13. National Language Support 397

Page 412: IBM Smalltalk: Programmer's Reference

retrieved from the catalog, or nil if an error occurs. The following exampleillustrates the procedure for loading indexed external messages."A code fragment to load indexed external message number 1 from anexisting message catalog file called 'demo.cat' for the #('english' 'us')locale and the 'iso8859-1' character set."

| catalog |catalog := NlsMessageCatalog on: 'demo.cat'.

(catalog loadLanguage: 'english'territory: 'us'characterSet: 'iso8859-1'intoDictionary: MyNlsMessagesindex: 1) isNil ifTrue: [

|self error: 'Load error: ',catalog currentErrorString].

Deleting indexed external messagesYou can delete an indexed external message from a message catalog file using thedeleteIndex:language:territory:characterSet: protocol. This operation removes only theindexed external message stored for the specified language, territory, character set,and index and does not affect any other indexed external messages or messagedictionaries. The following example demonstrates how to delete an indexedexternal message from a message catalog file."Removes the indexed external message number 1 for the#('english' 'us') locale and the 'iso8859-1' character set."

| catalog |catalog := NlsMessageCatalog on: 'demo.cat'.

(catalogdeleteIndex: 1language: 'english'territory: 'us'characterSet: 'iso8859-1') ifFalse: [

|self error: 'Deletion error: ',catalog currentErrorString].

Note: Deleting an indexed external message does not immediately decrease thesize of the message catalog file on disk. Deleted indexed external messagesare marked as garbage and their space is reclaimed when the messagecatalog file is compressed. See “Compression” on page 402 for a discussionof the compression of message catalog files.

Deletion is a permanent operation and cannot be undone. After an external messagedictionary is deleted, it is lost.

Deleting locales from a message catalog fileYou can delete an entire locale from a message catalog file using thedeleteLanguage:territory:characterSet:index: protocol. This operation removes both theindexed external messages and the external message dictionary stored for thespecified language, territory, and character set and does not affect objects stored forany other locale. The following example demonstrates how to delete a locale froma message catalog file."A code fragment to remove all objects stored for the#('english' 'us') locale and the 'iso8859-1' character set."

| catalog |catalog := NlsMessageCatalog on: 'demo.cat'.

(catalogdeleteLanguage: 'english'

398 IBM Smalltalk: Programmer’s Reference

Page 413: IBM Smalltalk: Programmer's Reference

territory: 'us'characterSet: 'iso8859-1') ifFalse: [

|self error: 'Deletion error: ',catalog currentErrorString].

Note: Deleting a locale does not immediately decrease the size of the messagecatalog file on disk. Deleted locales are marked as garbage and their space isreclaimed when the message catalog file is compressed. See “Compression”on page 402 for a discussion of the compression of message catalog files.

Deletion is a permanent operation and cannot be undone. Once deleted, all objectsstored for a locale are lost.

Support for extended localesIt is sometimes desirable for applications to use message catalog files to storeinformation other than localized messages. To avoid confusing the language,territory, and character set triples used to store this additional information withthose that contain localized messages the notion of extended locale has beenadopted. An extended locale is defined as a language, territory, character set triplewhere the language string begins with the ’$’ character.

Extended locales are intended to be used to identify objects other than localizedmessages which are stored in message catalog files. For example, the #(’$Comment’’Comment’ ’Comment’) extended locale could be used by an application tomaintain a comment about the message catalog file.

The following protocols are provided to determine what language, territory, andcharacter set combinations are supported by a message catalog file. Each of thefollowing protocols answers a collection of ordered triples representing thelanguage, territory, and character sets for which application-defined objects orlocalized messages have been stored. The following protocols report errors byanswering nil.

messageIdentifiersAnswers a collection containing language, territory, and character settriples from which localized messages are stored, excluding objects storedfor extended locales.

hiddenMessageIdentifiersAnswers a collection containing language, territory, and character settriples which are used to identify extended locales.

allMessageIdentifiersAnswers a collection containing all language, territory, and character settriples for which messages are stored, including objects stored for extendedlocales.

The following example illustrates the use of the preceding protocols:"A code fragment to determine the locales and character setssupported by a message catalog file."

| catalog translations extendedLocales allIdentifiers |catalog := NlsMessageCatalog on: 'demo.cat'.translations := catalog messageIdentifiers.extendedLocales := catalog hiddenMessageIdentifiers.allIdentifiers := catalog allMessageIdentifiers|Array

with: translationswith: extendedLocaleswith: allIdentifiers

Chapter 13. National Language Support 399

Page 414: IBM Smalltalk: Programmer's Reference

As a convenience, the NlsMessageCatalog provides thesupportsLanguage:territory:characterSet: message to determine if a message catalogfile supports a particular language, territory, and character set combination. Thismessage answers a Boolean value indicating whether or not the requestedcombination is supported. The following example demonstrates how to use thesupportsLanguage:territory:characterSet: protocol."Testing a message catalog file to determine if messages are storedfor #('english' 'us' 'iso8859-1')."| catalog |catalog := NlsMessageCatalog on: 'demo.cat'.|catalog

supportsLanguage: 'english'territory: 'us'characterSet: 'iso8859-1'

Note: The messageIdentifiers message is useful for selecting an alternative set oflocalized messages if the supportsLanguage:territory:characterSet: messageindicates that no messages are available for the requested language, territory,and character set.

CompatibilitiesNlsMessageCatalog supports compatibilities, a mechanism to facilitate the sharingof translations among locales. Compatibilities can also be used to describe thedefault messages to be used in the event that the message catalog file does notcontain messages for the current locale and character set.

NlsMessageCatalog compatibilities are stored in a sequenceable collection (array) ofarrays. The first element of each array describes the primary language, territory,and character set (locale triple) for which localized message strings are actuallystored in the catalog file. The remaining elements of each array describe localeswhich are compatible with, and can use the messages of, the primary locale. Acatalog file contains one set of compatibilities."Structure of NlsMessage Catalog Compatibilities"#(#(#('japanese' 'japan' 'ibm-932')#('japanese' 'japanese' 'japan' 'microsoft-shiftjis'))#(#('german' 'germany' 'iso8859-1')#('german' '*' 'iso8859-1'))#(#('english' 'us' 'ansi-ascii')#('*' '*' '*')))

NlsMessageCatalog>>localeCompatibleWithLanguage:territory:characterSet: can be usedto determine the locale whose messages are compatible with a given language,territory, and character set. The compatibilities depicted in the example aboveindicate that the catalog contains messages for primary localesjapanese-japan-ibm-932, german-germany-iso8859-1, and english-us-ansi-ascii.

Given a locale triple, localeCompatibleWithLanguage:territory:characterSet: firstdetermines if messages are explicitly stored for that locale. In the above example,the locale japanese-japan-ibm-932 is actually stored in the catalog. Therefore,localeCompatibleWithLanguage:territory:characterSet uses the messages of this locale

400 IBM Smalltalk: Programmer’s Reference

|||||||||||||||

|

Page 415: IBM Smalltalk: Programmer's Reference

without consulting the compatibility information. Similarly, localesgerman-germany-iso8859-1 and english-us-ansi-ascii use their stored messages.

If messages for the given locale are not explicitly stored in the catalog,localeCompatibleWithLanguage:territory:characterSet: uses the compatibility informationto determine the compatible locale. The process starts with the first array (forexample, (’japanese-japan-ibm-932’ ’japanese-japan-microsoft-shiftjis’) in the previousexample) and proceeds sequentially until the last array (for example,(english-us-ansi-ascii’ ’*-*-*’) in the previous example). If an element of an arraymatches the given locale the messages of the primary locale (for example,japanese-japan-ibm-932) are considered to be compatible with the given locale.Compatibility matching stops after the first match is found.

The last compatibility illustrated in the previous example, #(’english-us-ansi-ascii’’*-*-*’), indicates that if no other array was able to match the given locale triple,use *-*-* to match the locale triple, and default to using english-us-ansi-asciimessages. ANSI-ASCII characters are contained in the lower portion of manycharacter sets and thus provide a reasonable fall-back."Sharing localized messages using compatibilities"

german-switzerland-iso8859-1

matches#('german' 'germany' 'iso8859-1')#('german' '*' 'iso8859-1')

and uses'german' 'germany' 'iso8859-1'.

The next examplegerman-switzerland-ibm–850

does not match'german' '*' 'iso8859-1'

and therefore uses messages for'english' 'us' 'ansi-ascii'.

The next examplejapanese-japan-microsoft-shiftjis

matches#('japanese' 'japan' 'ibm-932')#('japanese' 'japan' 'microsoft-shiftjis')

and uses messages for'japanese' 'japan' 'ibm-932'.

The compatibilities from the example suggest that the application has iso8859-1translations for German, but likely has has not been localized for differentGerman-speaking territories. In other words, the application likely has a singleGerman version sold in multiple German-speaking territories. The example aboveillustrates the results of the compatibilities matching process as applied to thecompatibilities described in the example showing the structure ofNlsMessageCatalog compatibilities. The locale english-us-ansi-ascii is an abstract

Chapter 13. National Language Support 401

Page 416: IBM Smalltalk: Programmer's Reference

locale. Abstract locales do not correspond to actual platform supported locates;however, they can be used to help organize the messages of a catalog.

Storing and retrieving compatibilitiesNlsMessageCatalog provides the compatibilities and compatibilities: methods to retrieveand store message catalog compatibilities. The following example illustrates theprocess of storing and retrieving message catalog compatibilities."Set and retrieve the compatibilities of a message catalog file."| catalog compatibilities |compatibilities :=#(#(#('japanese' 'japan' 'ibm-932')#('japanese' 'japanese' 'japan' 'microsoft-shiftjis'))#(#('german' 'germany' 'iso8859-1')#('german' '*' 'iso8859-1'))#(#('english' 'us' 'ansi-ascii')#('*' '*' '*')))catalog := NlsMessageCatalog on: 'demo.cat'.(catalog compatibilities: compatibilities) ifFalse: [

|self error: 'Unload error: ',catalog currentErrorString].

|catalog compatibilities

CompressionDeletion of objects from a message catalog file is accomplished by marking objectsas unreachable and does not require the message catalog file to be entirelyrewritten. Furthermore, the structure of NlsMessageCatalog files allocates extra spaceto objects stored with the file to allow efficient object modification. For thesereasons a compression phase is necessary to reclaim space used by unreachableobjects and to remove extra space allocated to live objects.

The compressMinimal: method is used to compress a message catalog file. Thismethod accepts a Boolean argument that indicates whether the file should becompressed to its smallest possible size (at the expense of object modificationefficiency). If true is passed as a parameter to compressMinimal: then all space usedby unreachable objects is reclaimed and extra space allocated to live objects is alsoremoved. If false is passed, all space used by unreachable objects is reclaimed, butextra space allocated to live objects remains."Compress the message catalog file 'demo.cat' first leaving extraspace for future growth, then to its minimum size."| catalog |catalog := NlsMessageCatalog on: 'demo.cat'.(catalog compressMinimal: false) ifFalse: [

|self error: 'Compression error: ',catalog currentErrorString].(catalog compressMinimal: true) ifFalse: [

|self error: 'Compression error: ',catalog currentErrorString].

Note: When compressing message catalog files during the development cycle, it isdesirable to use compressMinimal: false option to ensure that updatingmessage catalog files is as efficient as possible. When all modifications havebeen done, you can use the compressMinimal: true option to minimize thesize of the message catalog file.

402 IBM Smalltalk: Programmer’s Reference

||||||||||||||||||||||

Page 417: IBM Smalltalk: Programmer's Reference

LimitationsNlsMessageCatalogs can contain only objects that can be dumped by the Swapperwithout special dumping options. (Refer to the IBM Smalltalk User’s Guide .)

Error detection and descriptionBecause NlsMessageCatalog is intended for use at runtime and debugging facilitiesmight not be available, error codes are employed to provide an error tracingmechanism. The value of the current error code should be examined after eachoperation to determine if an error occurred during the last operation. Alternatively,the hasErrorOccurred message can be used to check if an error occurred during thelast operation.

List of error codesThe following list includes all error codes and their corresponding messages. Eacherror code is associated with a descriptive error string and an error object, which istypically related to the current error or the cause of the current error. This errorobject can be obtained by sending the currentErrorObject message to an instance ofNlsMessageCatalog. Similarly, the descriptive error string can be obtained bysending the currentErrorString to an instance of NlsMessageCatalog. Theinterpretation of the error object for each error is provided below.

0 Error string: ’No Errors.’

Error object: nil

1000 Error string: ’Locale not supported.’

Error object: Locale name for which messages could not be found.

1002 Error string: ’The pool being initialized contains keys for which notranslations exist.’

Error object: A set of the keys missing translations.

1003 Error string: ’Could not open specified file.’

Error object: The pathname of the file that could not be opened.

1004 Error string: ’Non-portable messages detected.’

Error object: The message strings that are not portable.

1005 Error string: ’Error renaming file. Ensure file name is valid and no oldworking files exist.’

Error object:Array

with: name of file being renamedwith: name of rename targetwith: CfsError resulting from failed attempt to rename file.

1006 Error string: ’Error removing secondary working file.’

Error object:Array

with: name of secondary working filewith: CfsError resulting from failed attempt to rename file.

1007 Error string: ’Invalid attempt to crossload.’

Error object: An instance of NlsMessageCatalogHeader.

1010 Error string: ’File write error.’

Chapter 13. National Language Support 403

Page 418: IBM Smalltalk: Programmer's Reference

Error object:Array

with: an instance of NlsMessageCatalogHeaderwith: number of bytes that should have been writtenwith: number of bytes actually written

1011 Error string: ’FatalError: Object size estimation failed—working file iscorrupt.’

Error object: Object for which size estimation failed.

1012 Error string: ’Catalog file is corrupt (or not a catalog file).’

Error object: An instance of NlsMessageCatalogHeader.

1013 Error string: ’Invalid indexed message identifier (must be >0).’

Error object: The invalid indexed message identifier.

1014 Error string: ’Indexed message not found.’

Error object:Array

with: Locale name for which message could not be found.with: Index of message which could not be found.

1015 Error string: ’No messages stored for locale.’

Error object: Locale name for which messages could not be found.

1016 Error string: ’No message dictionary available.’

Error object: Locale name for which messages could not be found.

1017 Error string: ’Locale not found.’

Error object: Locale name for which messages could not be found.

2000 Error string: ’Error encountered loading object.’

Error object: An instance of ObjectLoader.

2001 Error string: ’Error encountered dumping object.’

Error object: An instance of ObjectDumper.

Support for packagingThe NlsMessageCatalog function described in the previous sections is partitionedbetween the applications NlsExternalizationRuntime and NlsExternalizationTools tosupport packaging.

NlsExternalizationRuntime provides the necessary class definitions forNlsMessageCatalog, its support classes, and all protocols required for reading andquerying message catalog files. NlsExternalizationTools defines extensions to thebasic NlsMessageCatalog and its support classes to enable creation of messagecatalog files. If the application being packaged has no requirement to createmessage catalog files at runtime, only the NlsExternalizationRuntime applicationshould be included in the packaged image.

The NlsExternalizationTools application also defines the RCConverter class that assistsin converting localized message dictionaries to Microsoft Windows and OS/2resource file formats. The RCConverter class is intended primarily for use in adevelopment image and should most likely be excluded from a runtime image.

404 IBM Smalltalk: Programmer’s Reference

Page 419: IBM Smalltalk: Programmer's Reference

Support for platform resource formatsThe subclasses of NlsPlatformResourceConverter are provided to enable pooldictionaries containing localized messages to be stored in and retrieved fromplatform resource file formats.

RCConverterDynamic link libraries (.DLL files) created using the Microsoft and IBM OS/2resource compilers are supported. The class RCConverter can produce a resourcecompiler input file from a pool dictionary, and can re-create the pool dictionaryfrom the input file and the dynamic link library it produces.

Structure of the resource compiler input fileThe first portion of the resource compiler input file generated by the RCConverter isa comment that identifies the file along with the date and time when it wascreated.

Immediately following the first comment is a series of define statements thatdescribe the pool dictionary from which the file was created. Localized messagesstored as IBM Smalltalk pool variables are identified by string keys in a pooldictionary; however, when these messages are stored in dynamic link libraries theymust be identified by ordinal constants. The conversion of string identifiers toordinal values is accomplished by associating each string identifier with an ordinalvalue using a define statement in the resource compiler input file. For example:define <aPoolDictionaryKey> <anInteger>

Localized messages and their associated comments follow the series of definestatements. Localized messages are represented as entries in a STRINGTABLEstatement associated with an ordinal value declared in the series of definestatements.

Note: The resource file representation of a string can be quite different from itsSmalltalk appearance. Many non-printing and special characters must beconverted into the ’\DDD’ format for use with the resource compiler. Whenretrieved from a dynamic link library using an RCConverter or aPlatformFunction the string is equivalent to the original Smalltalk string.

Creating resource compiler input filesRCConverter provides the convertMessages:toResourceFile: andconvertMessages:comments:toResourceFile: methods to convert a dictionary containinglocalized messages into a resource compiler input file. The dictionary containinglocalized messages must be keyed by string identifiers, and can contain onlymessages conforming to the conditions described in “RCConverter limitations” onpage 407. An attempt to convert a dictionary containing messages that are notvalid generates an error.

In addition to a file name and a dictionary containing localized messages, theconvertMessages:comments:toResourceFile: method accepts a dictionary containingcomments to be written into the resource compiler input file. The dictionarycontaining comments should have the same keys as the dictionary that containslocalized messages. The comment dictionary must conform to the same limitationsthat apply to message dictionaries, but need not contain a comment for everymessage in the dictionary being converted.

The following code example creates a resource compiler input file:

Chapter 13. National Language Support 405

Page 420: IBM Smalltalk: Programmer's Reference

"Create a resource compiler input file."| dict comments |dict :=

Dictionary newat: 'X' put: 'localized message X';at: 'Y' put: 'localized message Y';at: 'Z' put: 'localized message Z';yourself.

comments :=Dictionary new

at: 'X' put: 'comment X';at: 'Y' put: 'comment Y';yourself.

"Store the new pool dictionary in Smalltalk."Smalltalk at: #DemoPool put: dict.

RCConverter newconvertMessages: (Smalltalk at: #DemoPool)comments: commentstoResourceFile: 'demo.rc'

The preceding example illustrates how dictionaries containing localized messagesand comments are converted into a resource compiler input file. The exampleproduces the resource compiler input file called demo.rc, whose contents arepresented in the following example:/* Resource File for: #DemoPool.

This file is generated automatically for use as the input file for theMicrosoft Resource Compiler. When this file was constructed Smalltalkmessage identifiers were converted into numeric identifiers stored asa group of #define statements within this file.

This file is: demo.rcCreation date: 14.03.94 at: 14,37,12

This file was created with the following Smalltalk locale settings:

Language: germanTerritory: switzerlandCode page/Language driver: deu

*/

#define X 0#define Z 1#define Y 2

STRINGTABLEBEGIN

0, "localized message X" /* comment X */1, "localized message Z"2, "localized message Y" /* comment Y */

END

Reading from platform resource filesRCConverter provides the indexFrom: and messagesFromDLL:index: methods torebuild a dictionary containing localized messages from messages stored in adynamic link library (DLL).

Dynamic link libraries use integers to identify localized messages and IBMSmalltalk pool dictionaries use string identifiers. You must provide the mappingbetween string identifiers to be used in the reconstructed dictionary and theinteger identifier used by the dynamic link library. The indexFrom: method can beused to reconstruct an index from a resource compiler input file based upon a

406 IBM Smalltalk: Programmer’s Reference

Page 421: IBM Smalltalk: Programmer's Reference

series of define statements that bind string identifiers to integer values. Thefollowing example demonstrates the process of rebuilding an index from anexisting resource compiler input file:"Retrieve an index by parsing a resource compiler input file."|RCConverter new indexFrom: 'demo.rc'

The messagesFromDLL:index: protocol answers a reconstructed dictionary oflocalized messages based upon the contents of a dynamic link library and an indexprovided by the developer. messagesFromDLL:index: accepts any dictionary thatprovides mappings between strings and integers as its index parameter, althoughthe indexFrom: method is the recommended mechanism for generating the index.The messagesFromDLL:index: method does not require a resource compiler input fileto function. The following example illustrates the reconstruction of a dictionarycontaining localized messages from a dynamic link library:"Answer a dictionary reconstructed from a DLL."| converter index |converter := RCConverter new.index := converter indexFrom: 'demo.rc'.|converter messagesFromDLL: 'demo.dll' index: index.

RCConverter limitationsMessages must be instances of String or DBString containing Characters whosevalues are strictly greater than zero (1 to 65535).

Note: The resource file representation of a single Character can range from 1 to 4bytes. Characters expanded in this manner are the special or nonprintingcharacters whose values are 1 through 31, 34, and 127. For example,(Character value: 7) has a resource file representation of: ’\007.’

RCConverter error codesAll errors codes and their corresponding messages are detailed below. Each errorcode is associated with a descriptive error string and an error object, which istypically related to or the cause of the current error. This error object can beobtained by sending the message currentErrorObject to an instance of RCConverter.Similarly, the descriptive error string can be obtained by sending the messagecurrentErrorString to an instance of RCConverter. The interpretation of the errorobject for each error follows.

Error codeMessage

2 Error string: ’Message names cannot contain double byte characters.’

Error object: The invalid message name.

3 Error string: ’Message cannot contain characters of value < 2.’

Error object: The invalid message text.

4 Error string: ’Some of the messages contain non-string objects.’

Error object: The invalid message name.

5 Error string: ’Some of the messages contain empty strings. Messages cannotbe empty strings.’

Error object: The invalid message text.

6 Error string: ’Invalid message name the phrase _part_ is a reserved token.’

Error object: The invalid message name.

7 Error string: ’File Error: Could not open specified file.’

Chapter 13. National Language Support 407

Page 422: IBM Smalltalk: Programmer's Reference

Error object: File name (String) of the file that could not be opened.

8 Error string: ’Could not open DLL’

Error object: File name (String) of the DLL that could not be opened.

9 Error string: ’Could read messages from DLL.’

Error object: The integer identifier of the unreadable message.

10 Error string: ’Could not close resource DLL.’

Error object: The module handle that could not be closed.

11 Error string: ’Could not read index from resource file DLL.’

Error object: File name (String) of the invalid resource file.

Localization support APIThe following classes provide protocols that directly support theinternationalization and localization of software.v NlsMessageCatalogv RCConverter

NlsMessageCatalog class methodson: Answers a new, initialized instance of the receiver on the file specified by

the absolute or relative path aPathName (String).

NlsMessageCatalog instance methodsallMessageIdentifiers

Determines which locales are supported by localized messages stored inthe file specified by the receiver’s path. Answers a collection of all localenames for which the catalog file specified by path has mappings includinglocale names starting with the ″$″ character whose names are not returnedby the messageIdentifiers protocol. Answers nil if an error occurs.

compatibilitiesAnswers an array of compatibility arrays, nil if no compatibility arrays canbe located. Each compatibility array has the following form:#(<primary local triple> "Triple for which messages are

actually stored."<compatible pattern> "Triple for locale compatible with primary."...(compatible pattern> "Triple for local compatible with primary.")

compatibilities:Unloads anArrayOfcompatibilityArrays into the file represented by thereceiver. The format of the argument anArrayOfcompatibilityArrays isdescribed in the compatibilities method comment. Answers true on success,otherwise answers false.

compressMinimal:Compresses the file represented by the receiver removing any dead areas.If compressToMinimumSize is true, the file is made its smallest possible size.If compressToMinimumSize is false, padding is included in the new file sothat future writes might not need to grow the file. Answers true ifsuccessful, otherwise answers false

408 IBM Smalltalk: Programmer’s Reference

Page 423: IBM Smalltalk: Programmer's Reference

currentErrorAnswers the integer error code describing the last error that occurred.Answers 0 if no errors have occurred.

currentErrorObjectAnswers the object(s) that caused the last error that occurred. This can be asingle object or an array of objects. Refer to “List of error codes” onpage 403.

currentErrorStringAnswers a string of the last error that occurred. This string offers anexplanation of the last error, and appends extended error information fromthe Swapper, if appropriate.

declareKeysFor:language:territory:characterSet:Loads the localized messages stored in the receiver at the key specified bythe language, territory, and character set (strings). Declares keys in thespecified pool dictionary if they are missing. The values of newly declaredkeys are the same as the key to allow identification of missing translations.Answers true on success, otherwise answers false.

deleteDictionaryLanguage:territory:characterSet:Deletes the external message dictionary for the locale specified by thelanguage, territory, and character set (strings) from the catalog file specifiedby the receiver’s file name. Answers true if the external dictionary messageis successfully removed, otherwise answers false.

deleteIndexLanguage:territory:characterSet:Deletes the indexed message specified by the index for the locale specifiedby the language, territory, and character set (strings) from the catalog filespecified by the receiver’s file name. Answers true if the localized messagewas successfully removed, otherwise answers false.

deleteLanguage:territory:characterSet:Deletes all messages for the locale specified by the language, territory, andcharacter set (strings) from the catalog file specified by the receiver’s filename. Answers true if the messages are successfully removed, otherwiseanswers false.

fileNameAnswers a String that is the fileName of the message catalog filerepresented by the receiver. The fileName is the string passed as anparameter to the on: method.

fileName:Sets the fileName of the message catalog file represented by the receiver tothe specified string.

hasErrorOccurredAnswers true if an error has occurred in the receiver, otherwise answersfalse.

hiddenMessageIdentifiersDetermines which locales are supported by localized messages stored inthe file specified by the receiver’s path. Answers a collection of thesupported locale names, in which the locale names start with a ″$″character. These names are not returned by the messageIdentifiers protocol.Answers nil if an error occurs.

indexesForLanguage:territory:characterSet:Determines which indexed message identifiers are available for the locale

Chapter 13. National Language Support 409

Page 424: IBM Smalltalk: Programmer's Reference

specified by the language, territory, and character set (strings). Answers acollection of indexed message identifiers (positive integers) for which themessage catalog file specified by the receiver’s file name has mappings.Answers nil if an error occurs.

loadLanguage:territory:characterSet:Answers the dictionary of localized messages specified by the language,territory, and character set stored in the file specified by the receiver’s path.Answers the dictionary of retrieved messages if successful, otherwiseanswers nil.

loadLanguage:territory:characterSet:index:Answers the indexed message specified by the positive integer index forthe locale and character set specified by language, territory, and characterset, contained in the file specified by path. Answers the localized messageretrieved from disk if successful, answers nil otherwise.

loadLanguage:territory:characterSet:intoDictionary:Localizes the specified EsPoolDictionary using message for the localespecified by the language, territory, and character set (strings). Modifies theassociation in the pool dictionary with localized messages contained in thefile specified by path. Answers true if successful, otherwise answers false.

Note: Only keys already in the pool have their values set.

localeCompatibleWithLanguage:territory:characterSet:Retrieves and examines the receiver’s compatibilities array and determineswhich message identifier best matches the language, territory, andcharacter set.

If the message catalog file contains messages for the specified language,territory, and character set, the compatibilities are not examined and anarray containing the specified the language, territory, and character set isreturned. Otherwise the matching process examines each line of thecompatibilities array (whose format is described in the compatibilitiesmethod comment). Within a line of the compatibilities, array patterns areexamined from left to right. If no match is found on a given line, thesearch continues to the following lines until a match is found or no morelines are available. A match occurs if the three elements of the patternarray match language, territory, and character set.

Answers a three-element array consisting of strings that identify thelanguage, territory, and character set. Answers nil if an error occurs or if nocompatibility matches the supplied arguments.

messageIdentifiersDetermines which locales are supported by localized messages stored inthe file specified by the receiver’s path. Answers a collection of the localenames for which the message catalog file specified by path has mappings.Answers nil if an error occurs.

objectPlatformAnswers the object platform from which the message catalog file specifiedby the receiver’s path was dumped. Answers a string indicating the objectplatform, or nil if an error occurs.

pathNameAnswers a string that contains the full path name of the message catalogfile represented by the receiver (nil if the full path has not yet beencomputed).

410 IBM Smalltalk: Programmer’s Reference

Page 425: IBM Smalltalk: Programmer's Reference

supportsLanguage:territory:characterSet:Determines whether the specified file contains localized messages for thelocale specified by the string’s language, territory, and character set.Answers true if the locale is supported, false if unsupported, or nil if anerror occurs.

unload:language:territory:characterSet:Stores the localized messages contained in the specified pool dictionary forthe locale defined by the language, territory, and character set in the filespecified by the receiver’s fileName. Answers true if successful, otherwiseanswers false.

unload:language:territory:characterSet:index:Stores the given localized message as an indexed message in a filespecified by the receiver’s fileName, for the locale defined by the language,territory, and character set, and the positive integer index. Answers true ifsuccessful, otherwise answers false.

RCConverter class methodsnew Answers a new, initialized instance of the receiver.

RCConverter class methods instance methodsconvertMessages:comments:toResourceFile:

Creates a file resourcePath that can be used as input to the Microsoft or IBMOS/2 resource compilers. This method converts the contents of thespecified pool dictionary into numbered messages in the input file, storingthe mapping as a series of define statements, and annotates this input filewith comments contained in the specified comment dictionary. Answerstrue if successful, otherwise answers false.

convertMessages:toResourceFile:Creates a file resourcePath that can be used as input to the Microsoft or IBMOS/2 resource compilers. This method converts the contents of thespecified pool dictionary into numbered messages in the input file storingthe mapping as a series of define statements. Answers true if successful,otherwise answers false.

indexFrom:Parses the specified input file of the Microsoft or IBM OS/2 resourcecompiler and answers a dictionary that contains the pool key-numericmappings stored in the define statements of the input file. Answers nil if anerror occurs.

messagesFromDLL:index:Answers the dictionary rebuilt from the specified dynamic link libraryusing the mapping between dictionary keys and numeric identifierscontained in the index. Answers the rebuilt dictionary if successful, nil ifan error occurs.

IBM Smalltalk locale namesTable 52. Supported language and territory combinations

Language Territory Language Territory

arabic arabic hungarian hungary

croatian yugoCroatian icelandic iceland

czech czechoslovakia italian italy

Chapter 13. National Language Support 411

Page 426: IBM Smalltalk: Programmer's Reference

Table 52. Supported language and territory combinations (continued)

Language Territory Language Territory

danish denmark italian switzerland

dutch belgium japanese japan

dutch netherlands korean korea

english australia lappish lapland

english britain lettish latvia

english canada lithuanian lithuania

english ireland maltese malta

english new zealand norwegian norway (Bokmal)

english us norwegian norway (Nynorsk)

estonian estonia polish poland

faeroese faeroeIsl portuguese brazil

farsi iran portuguese portugal

finnish finland russian russia

french belgium simpChinese china

french canada slovak czechoslovakia

french france spanish mexico

french switzerland spanish spain (Mod)

german austrian spanish spain (Trad)

german germany swedish sweden

german switzerland thai thailand

greek greece tradChinese taiwan

hebrew israel turkish turkey

hindi india urdu pakistan

Manual localizationMethods are provided to access and change the state information of LCCollate,LCMonetary, LCMessages, LCNumeric, LCTime, and Locale objects. In particular, thefollowing methods are provided to enable you to perform further localization bymanually setting the values of various fields. This can be used to override valuesobtained from the platform, or to configure locale-specific values on platforms thatdo not provide the information.

Note: Some platforms do not have a one-to-one match with all of the formattinginformation maintained by LCCollate, LCCType, LCMonetary, LCMessages,LCNumeric, LCTime, and Locale. To prevent an error, a universal policy forcesinitialization of such variables to U.S. English. A description of values thatcannot be obtained from the platform, and their default values, is presentedin “Locales and platform representation” on page 415.

LCCollatecollateTable:

Sets the collateTable. The collate table is a ByteArray consisting of 256positions. The value at each position is the collating weight of a given

412 IBM Smalltalk: Programmer’s Reference

Page 427: IBM Smalltalk: Programmer's Reference

character. The character with the highest collating weight appears first inan alphabetical sort. Information for the character with value 0 is stored atposition 1, and so on.

LCMessagesdataSeparator:

Sets the data separator string explicitly.

noStr: Sets the localized versions of the string ’No.’

yesStr: Sets the localized versions of the string ’Yes.’

LCMonetarycurrencySymbol:

Sets the currency symbol used when printing a formatted monetaryquantity.

fracDigits:Sets the number of fractional digits that appear in a formatted numericquantity.

intCurrSymbol:Sets the currency symbol used when printing an international monetaryquantity.

intFracDigits:Sets the number of fractional digits that appear in a formatted monetaryquantity.

monDecimalPoint:Sets the decimal point used when formatting a monetary quantity.

monGrouping:Sets the manner in which digits are grouped in a formatted monetaryquantity.

monThousandsSep:Sets the thousands separator used in a formatted monetary quantity.

nCsPrecedes:Combined with the following two methods, controls the formatting ofnegative monetary quantities.

nSepBySpace:Combined with the preceding and following methods, controls theformatting of negative monetary quantities.

nSignPosn:Combined with the preceding two methods, controls the formatting ofnegative monetary quantities.

negativeSign:Sets the indicator used to indicate a negative quantity in a formattedmonetary quantity.

positiveSign:Sets the indicator used to indicate a positive quantity in a formattedmonetary quantity.

Chapter 13. National Language Support 413

Page 428: IBM Smalltalk: Programmer's Reference

pCsPrecedes:Combined with the following two methods, controls the formatting ofnon-negative monetary quantities.

pSepBySpace:Combined with the preceding and following methods, controls theformatting of non-negative monetary quantities.

pSignPosn:Combined with the preceding two methods, controls the formatting ofnon-negative monetary quantities.

LCNumericdecimalPoint:

Sets the decimal point used when formatting a numeric quantity.

grouping:Sets the manner in which digits are grouped in a formatted numericquantity.

thousandsSep:Sets the thousands separator used in a formatted numeric quantity.

LCTimeabDay: Sets the abbreviated days names.

abMon:Sets the abbreviated month names.

amPm: Sets the two-element array used to represent the ante-meridian (beforenoon) and post-meridian (after noon) indicator strings. Element1 is AM;Element2 is PM.

day: Sets the full day names.

dFmt: Sets the date format template for the printing of dates.

dtFmt: Sets the date-time format template for the printing of dates and times.

mon: Sets the month names.

tFmt: Sets the time format template for the printing of times.

LocalecountryAbbreviation:

Sets the receiver’s two-character ISO country abbreviation string.

language:Sets the descriptive language string for the receiver’s locale.

territory:Sets the descriptive territory string for the receiver’s locale.

414 IBM Smalltalk: Programmer’s Reference

Page 429: IBM Smalltalk: Programmer's Reference

Locales and platform representationThe concept of a locale defined by language and territory provides aplatform-independent method of specifying international language-dependentsettings. NLS functions translate the IBM Smalltalk locale names to platform valuesas illustrated in the following figure:

The following sections detail the mapping from IBM Smalltalk locale definitions toplatform values and discuss items of interest for each supported platform.Although you normally do not need to map locale descriptions onto platformvalues, this section illustrates the source of some platform limitations.

Note: When platforms do not have a one-to-one match with all of the formattinginformation maintained by LCCollate, LCCType, LCMonetary, LCMessages,LCNumeric, LCTime, and Locale, these methods are initialized with EnglishU.S. values. “Manual localization” on page 412 describes methods that youcan use to override values obtained from the platform, or to configurelocale-specific values on platforms that do not provide the information.

OS/2 Presentation ManagerAs illustrated in the figure above, each IBM Smalltalk locale name corresponds toan ordered pair of integers representing an OS/2 country code and OS/2 codepage. Table 54 on page 416 defines the mappings from IBM Smalltalk localedefinitions to country code and code page pairs. Locales that are not directlysupported by the operating system are marked with a horizontal bar and are notavailable on OS/2.

For OS/2 Presentation Manager, the platform locale information is a combinationof values retrieved from the operating system and the country control panelsettings. When the platform default locale is requested (for example, LCMonetaryfor: #(' ')), values are taken from the country control panel settings. Wheninformation for a specific locale is requested (for example, LCMonetary for:#('english' 'us')), the default values for that locale are obtained from theoperating system, even if the locale requested is the same as the platform defaultlocale.

When information is unavailable from the platform, U.S. English default values areprovided. The following table shows the values that are not available from theoperating system, along with their default values.

Note: The country control panel setting for monetary leading zero is notsupported and is ignored on OS/2.

Chapter 13. National Language Support 415

Page 430: IBM Smalltalk: Programmer's Reference

Table 53. Items not provided by OS/2 and their default values

Class Item IBM Smalltalk default value

LCMessages noStr ’No’

yesStr ’Yes’

LCMonetary intCurrSymbols Set to same operating system-suppliedvalue as currencySymbol

intFracDigits Set to same operating system-suppliedvalue as fracDigits

monGrouping ’3 0’

monThousandsSep Set to operating system thousandsseparator

negativeSign ’-’

positiveSign ’’

LCNumeric decimalPoint Set to same operating system-suppliedvalue as monDecimalPoint

grouping ’3 0’

LCTime abDay #(’Sun’ ’Mon’ ’Tues’ ’Wed’ ’Thu’ ’Fri’’Sat’)

abMon #(’Jan’ ’Feb’ ’Mar’ ’Apr’ ’May’ ’Jun’’Jul’ ’Aug’ ’Sep’ ’Oct’ ’Nov’ ’Dec’)

day #(’Sunday’ ’Monday’ ’Tueday’’Wednesday’ ’Thusday’ ’Friday’’Saturday’)

mon #(’January’ ’February’ ’March’ ’April’’May’ ’June’ ’July’ ’August’ ’September’’October’ ’November’ ’December’)

Use of the country control panelChanging the current country using the country control panel does not change theplatform default locale. The platform default locale is defined by the config.sysfile and can be modified using the OS/2 selective install.

Table 54. Map from locale names to OS/2 platform values

Locale langauge Locale territory Countrycode

Code pages

arabic arabic 785 864, 437 850

croatian yugoCroatian 38 852, 850

czech czechoslovakia 42 852, 850

danish denmark 45 865, 850

dutch belgium 32 437, 850

dutch netherlands 31 437, 850

english australia 61 437, 850

english britain 44 437, 850

english canada – –

english ireland – –

english new zealand – –

english us 1 437, 850

416 IBM Smalltalk: Programmer’s Reference

Page 431: IBM Smalltalk: Programmer's Reference

Table 54. Map from locale names to OS/2 platform values (continued)

Locale langauge Locale territory Countrycode

Code pages

estonian estonia – –

faeoroese faeroelsl – –

farsi iran – –

finnish finland 358 437, 850

french belgium 32 437, 850

french canada 2 863, 850

french france 33 437, 850

french switzerland 41 437, 850

german austria – –

german germany 49 437, 850

german switzerland 41 437, 850

greek greece – –

hebrew israel 972 862, 437, 850

hindi india – –

hungarian hungary 36 852, 850

icelandic iceland 354 850, 861

italian italy 39 437, 850

italian switzerland 41 437, 850

japanese japan 81 932, 942, 437, 850

korean korea 82 949, 944, 437, 850

lappish lapland – –

lettish latvia – –

lithuanian lithuania – –

maltese malta – –

norwegian norway (Bokmal) – –

norwegian norway (Nynorsk) 47 865, 850

polish poland 48 852, 850

portuguese brazil – –

portuguese portugal 351 860, 850

russian russia – –

simpChinese china 86 936, 946, 437, 850

slovak czechoslovakia 42 852, 850

spanish mexico 3 437, 850

spanish spain (Mod) 34 437, 850

spanish spain (Trad) 34 437, 850

swedish sweden 46 437, 850

thai thailand – –

tradChinese taiwan 88 938, 948, 437, 850

turkish turkey 90 857, 850

Chapter 13. National Language Support 417

Page 432: IBM Smalltalk: Programmer's Reference

Table 54. Map from locale names to OS/2 platform values (continued)

Locale langauge Locale territory Countrycode

Code pages

urdu pakistan – –

Microsoft WindowsAs illustrated in the diagram at the beginning of this section, each IBM Smalltalklocale name maps directly to a pair of language and sublanguage identifierconstants. The following table defines the mappings from IBM Smalltalk localedefinitions to language and sublanguage identifier pairs. The language andsublanguage constants are defined in the WINNT.H header file that is part of theWindows NT software development kit.

Table 55. Windows platform values and IBM smalltalk locale names

IBM Smalltalk Locale Name Platform Mapping

Language Territory Language ID Sublanguage ID

arabic arabic – –

croatian yugoCroatian – –

czech czechoslovakia LANG_CZECH SUBLANG_DEFAULT

danish denmark LANG_DANISH SUBLANG_DEFAULT

dutch belgium LANG_DUTCH SUBLANG_DUTCH_BELGIAN

dutch netherlands LANG_DUTCH SUBLANG_DUTCH

english australia LANG_ENGLISH SUBLANG_ENGLISH_AUS

english britain LANG_ENGLISH SUBLANG_ENGLISH_UK

english canada LANG_ENGLISH SUBLANG_ENGLISH_CAN

english ireland LANG_ENGLISH SUBLANG_ENGLISH_EIRE

english new zealand LANG_ENGLISH SUBLANG_ENGLISH_nz

english us LANG_ENGLISH SUBLANG_ENGLISH_US

estonian estonia – –

faeroese faeroeIsl – –

farsi iran – –

finnish finland LANG_FINNISH SUBLANG_DEFAULT

french belgium LANG_FRENCH SUBLANG_FRENCH_BELGIAN

french canada LANG_FRENCH SUBLANG_FRENCH_CAN- ADIAN

french france LANG_RENCH SUBLANG_FRENCH

french switzerland LANG_FRENCH SUBLANG_FRENCH_SWISS

german austria LANG_GERMAN SUBLANG_GERMAN_AUS- TRIAN

german germany LANG_GERMAN SUBLANG_GERMAN

german switzerland LANG_GERMAN SUBLANG_GERMAN_SWISS

greek greece LANG_GREEK SUBLANG_DEFAULT

hebrew israel – –

hindi india – –

hungarian hungary LANG_HUNGARIAN SUBLANG_DEFAULT

icelandic iceland LANG_ICELANDIC SUBLANG_DEFAULT

418 IBM Smalltalk: Programmer’s Reference

Page 433: IBM Smalltalk: Programmer's Reference

Table 55. Windows platform values and IBM smalltalk locale names (continued)

IBM Smalltalk Locale Name Platform Mapping

italian italy LANG_ITALIAN SUBLANG_ITALIAN

italian switzerland LANG_ITALIAN SUBLANG_ITALIAN_SWISS

japanese japan LANG_JAPANESE SUBLANG_DEFAULT

korean korea LANG_KOREAN SUBLANG_DEFAULT

lappish lapland – –

lettish latvia – –

lithuanian lithuania – –

maltese malta – –

norwegian norway (Bokmal) LANG_NORWEGIAN SUBLANG_NORWEGIAN_BOK-MAL

norwegian norway (Nynorsk) LANG_NORWEGIAN SUBLANG_NORWEGIAN_NY-NORSK

polish poland LANG_POLISH SUBLANG_DEFAULT

portuguese brazil LANG_PORTUGUESE SUBLANG_PORTUGUESE

portuguese portugal LANG_PORTUGUESE SUBLANG_PORTUGUESE_BRA-ZILIAN

russian russia LANG_RUSSIAN SUBLANG_DEFAULT

simpChinese china LANG_CHINESE SUBLANG_CHINESE_SIMPLI- FIED

slovak czechoslovakia LANG_SLOVAK SUBLANG_DEFAULT

spanish mexico LANG_SPANISH SUBLANG_SPANISH_MEXICAN

spanish spain (Mod) LANG_SPANISH SUBLANG_SPANISH_MODERN

spanish spain (Trad) LANG_SPANISH SUBLANG_SPANISH_TRADI-TIONAL

swedish sweden LANG_SWEDISH SUBLANG_DEFAULT

thai thailand – –

tradChinese taiwan LANG_CHINESE SUBLANG_CHINESE_TRADI-TIONAL

turkish turkey LANG_TURKISH SUBLANG_DEFAULT

urdu pakistan – –

Use of the system control panelNLS information is drawn from the settings of the system control panel. IBMSmalltalk recognizes a given locale based upon a specific combination of countryand language settings. These parameters are set through the country and languagesections of the International control panel on Windows NT, and via the regionalsettings tab of the International control panel on Windows 95 or Windows 98.

An attempt to initialize the current locale for a particular locale will fail unless theInternational control panel has the country and language options set appropriately.For example, on Windows NT, if English U.S. is the desired locale, theInternational control panel must have the country set to United States and theLanguage set to English (American) before the image is started or the locale ismanually reinitialized. Note that the language must be set to English (American);that the setting English (International) does not work.

Chapter 13. National Language Support 419

Page 434: IBM Smalltalk: Programmer's Reference

Note:

v Windows 95 and Windows 98 unify the country and language settingsinto a single selection in the regional control panel, eliminatingmismatched language and country selections.

v When information is unavailable from the platform, English U.S. defaultvalues are provided. The following table shows the items that are notavailable from the operating system, along with their default values.

v The number of decimal digits specified in the number format section ofthe International control panel is not used.

v The International control panel setting for monetary leading zero is notsupported and is ignored.

v IBM Smalltalk uses the short date format from the International controlpanel; the long date format is ignored.

Table 56. Items not provided by Windows and their default values

Class Item IBM Smalltalk defaultvalue

LCMessages noStr ’No’

yesStr ’Yes’

AIX, HP-UX, and SolarisThe illustration at the beginning of this section shows how each IBM Smalltalklocale name maps directly to a string describing an operating system locale. Thefollowing tables define the mappings from the IBM Smalltalk locale names toplatform locale names for AIX, HP-UX, and Solaris respectively. Locales that arenot directly supported by the particular operating system are marked in the tablewith a horizontal bar.

Table 57. Map from locale names to AIX platform mappings

IBM Smalltalk Locale NameI Platform Mappings

Language Territory Locale Name

arabic arabic ’AR_AA’ or ’ar_AA’

croatian yugoCroatian ’hr_HR’

czech czechoslovakia ’cs_CZ’

danish denmark ’Da_DK’ or ’da_DK’

dutch belgium ’Nl_BE’ or ’nl_BE’

dutch netherlands ’Nl_NL’ or ’nl_NL’

english australia –

english britain ’En_GB’ or ’en_GB’

english canada –

english ireland –

english new zealand –

english us ’En_US’ or ’en_US’

estonian estonia –

faeroese faeroeIsl –

farsi iran –

finnish finland ’Fi_FI’ or ’fi_FI’

420 IBM Smalltalk: Programmer’s Reference

Page 435: IBM Smalltalk: Programmer's Reference

Table 57. Map from locale names to AIX platform mappings (continued)

IBM Smalltalk Locale NameI Platform Mappings

Language Territory Locale Name

french belgium ’Fr_BE’ or ’fr_BE’

french canada ’Fr_CA’ or ’fr_CA’

french france ’Fr_FR’ or ’fr_FR’

french switzerland ’Fr_CH’ or ’fr_CH’

german austria –

german germany ’De_DE’ or ’de_DE’

german switzerland ’De_CH’ or ’de_CH’

greek greece ’eI_GR’

hebrew israel ’Iw_IL’ or ’iw_IL’

hindi india –

hungarian hungary ’hu_HU’

icelandic iceland ’Is_IS’ or ’is_IS’

italian italy ’It_IT’ or ’it_IT’

italian switzerland –

japanese japan ’Ja_JP’ or ’ja_JP’

korean korea ’ko_KR’

lappish lapland –

lettish latvia –

lithuanian lithuania –

maltese malta –

norwegian norway (Bokmal) ’No_NO’ or ’no_NO’

norwegian norway (Nynorsk) ’No_NO’ or ’no_NO’

polish poland –

portuguese brazil –

portuguese portugal ’Pt_PT’ or ’pt_PT’

russian russia ’ru_RU’

simpChinese china –

slovak czechoslovakia ’sk_SK’

spanish mexico –

spanish spain (Mod) ’Es_ES’ or ’es_ES’

spanish spain (Trad) ’Es_ES’ or ’es_ES’

swedish sweden ’Sv_SE’ or ’sv_SE’

thai thailand –

tradChinese taiwan ’zh_TW’

turkish turkey ’Tr_TR’

urdu pakistan –

Chapter 13. National Language Support 421

Page 436: IBM Smalltalk: Programmer's Reference

Table 58. HP-UX and IBM Smalltalk locale names

IBM Smalltalk Locale Name Platform Mapping

Language Territory Locale Name

arabic arabic ’ar_SA.arabic8’ or ’ar_DX.arabic8’ or’ar_SA.iso88596’

croatian yugoCroatian ’hr_HR.iso88592’

czech czechoslovakia ’cs_CZ.iso88592’

danish denmark ’Da_DK.roman8’ or ’da_DK.iso88591’

dutch belgium ’Nl_BE’ or ’nl_BE’

dutch netherlands ’Nl_NL.roman8’ or ’nl_NL’

english australia –

english britain ’En_GB.roman8’ or ’en_GB.iso88591’

english canada –

english ireland –

english new zealand –

english us ’En_US.roman8’ or ’en_US.iso88591’

estonian estonia –

faeroese faeroeIsl –

farsi iran –

finnish finland ’Fi_FI.roman8’ or ’fi_FI.iso88591’

french belgium –

french canada ’Fr_CA.roman8’ or ’fr_CA.iso88591’

french france ’Fr_FR.roman8’ or ’fr_FR.iso88591’

french switzerland –

german austria –

german germany ’De_DE.roman8’ or ’de_DE.iso88591’

german switzerland –

greek greece ’eI_GR.greek8’ or ’el_GR.iso88597’

hebrew israel ’Iw_IL.hebrew8’ or ’iw_IL.iso88598’

hindi india –

hungarian hungary ’hu_HU.iso88592’

icelandic iceland ’Is_IS.roman8’ or ’is_IS.iso88591’

italian italy ’It_IT.roman8’ or ’it_IT.iso88591’

italian switzerland –

japanese japan ’Ja_JP.SJIS’ or ’ja_JP.kana8’

korean korea ’ko_KR.eucKR’

lappish lapland –

lettish latvia –

lithuanian lithuania –

maltese malta –

norwegian norway (Bokmal) ’No_NO.roman8’ or ’no_NO.iso88591’

norwegian norway (Nynorsk) ’No_NO.roman8’ or ’no_NO.iso88591’

422 IBM Smalltalk: Programmer’s Reference

Page 437: IBM Smalltalk: Programmer's Reference

Table 58. HP-UX and IBM Smalltalk locale names (continued)

IBM Smalltalk Locale Name Platform Mapping

Language Territory Locale Name

polish poland ’pl_PL.iso88592’

portuguese brazil –

portuguese portugal ’Pt_PT.roman8’ or ’pt_PT.iso88591’

russian russia ’ru_RU.iso88595’

simpChinese china ’zh_CN.hp15CN’

slovak czechoslovakia ’sk_SK.iso88592’

spanish mexico –

spanish spain (Mod) ’Es_ES.roman8’ or ’es_ES.iso88591’

spanish spain (Trad) ’Es_ES.roman8’ or ’es_ES.iso88591’

swedish sweden ’Sv_SE.roman8’ or ’sv_SE.iso88591’

thai thailand ’th_TH.tis620’

tradChinese taiwan ’zh_TW.ccdc’ or zh_TW.big5’ or’zh_TW.eucTW’

turkish turkey ’Tr_TR.turkish8’ or ’tr_TR.iso88599’

urdu pakistan –

Table 59. Solaris and IBM Smalltalk locale names

Smalltalk Locale Name Platform Mapping

Language Territory Locale name

arabic arabic –

croatian yugoCroatian –

czech czechoslovakia –

danish denmark ’da’

dutch belgium ’nl_BE’

dutch netherlands ’nl’

english australia ’en_AU’

english britain ’en_UK’

english canada ’en_CA’

english ireland ’en_IE’

english new zealand ’en_NZ’

english us ’en_US’

estonian estonia –

faeroese faeroeIsl –

farsi iran –

finnish finland ’su’

french belgium ’fr_BE’

french canada ’fr_CA’

french france ’fr’

french switzerland ’fr_CH’

Chapter 13. National Language Support 423

Page 438: IBM Smalltalk: Programmer's Reference

Table 59. Solaris and IBM Smalltalk locale names (continued)

Smalltalk Locale Name Platform Mapping

Language Territory Locale name

german austria –

german germany ’de’

german switzerland ’de_CH’

greek greece –

hebrew israel –

hindi india –

hungarian hungary –

icelandic iceland –

italian italy ’it’

ilian switzerland –

japanese japan ’ja’ or ’japanese’

korean korea –

lappish lapland –

lettish latvia –

lithuanian lithuania –

maltese malta –

norwegian norway (Bokmal) ’no’

norwegian norway (Nynorsk) ’no’

polish poland –

portuguese brazil ’pt_BR’

portuguese portugal ’pt’

russian russia –

simpChinese china –

slovak czechoslovakia –

spanish mexico ’es_MX’

spanish spain (Mod) ’es’

sish spain (Trad) ’es’

swedish sweden ’sv’

thai thailand –

tradChinese taiwan –

turkish turkey –

urdu pakistan –

424 IBM Smalltalk: Programmer’s Reference

Page 439: IBM Smalltalk: Programmer's Reference

Chapter 14. Inter-process communication

UNIX operating systems provide each process with an environment consisting ofvariable names paired with values. This chapter contains the protocol specificationfor accessing the processes and environment variables of the host operatingsystem. These environment variables can be used by the process to determine theuser’s configuration. Information such as search path, home directory, and username can be retrieved from the environment. With access to these environmentvariables, a Smalltalk application can query the values and configure itselfappropriately.

The following classes are provided: UNIXEnvironment, UNIXProcess,UNIXReadPipeStream, and UNIXWritePipeStream.

The UNIXEnvironment class is used by the UNIXProcess class to provide anenvironment for new processes.

The UNIXProcess class controls other operating system processes from withinSmalltalk. The UNIXProcess class supports both interactive and passive processes.Interactive processes support stream-based pipes for stdin, stdout, and stderr.Stream-based pipes enable the developer to control the process (input) and recordthe resulting output. For example, UNIX shell scripts can be invoked from within aSmalltalk application.

The UNIXReadPipeStream and UNIXWritePipeStream classes support a subset of thestream protocol. Instances of UNIXReadPipeStream are answered by a UNIXProcessfor stdout and stderr streams, and instances of UNIXWritePipeStream are answeredfor input streams.

UNIX environmentThis subsection describes a conceptual model of the UNIX environment.

In UNIX, an array of strings called the environment is available to each process.The format of these strings is aKey=aValue. The environment is often used to storeuser configuration information. For example, the PATH environment variabledefines the search path used to locate executables.

The UNIXEnvironment class provides access to the shell environment from withinSmalltalk. A subset of the Dictionary protocol is supported by the UNIXEnvironmentclass. Through this protocol the environment can be queried and modified.

There are two intended uses for the UNIXEnvironment class:1. To enable Smalltalk applications to configure themselves based on available

environment information.2. To provide the UNIXProcess (described in “UNIX process” on page 427) with a

configurable environment that can be based on the current environment orcompletely defined.

Method specificationFollowing are UNIXEnvironment methods and usage examples.

© Copyright IBM Corp. 1994, 2000 425

Page 440: IBM Smalltalk: Programmer's Reference

UNIXEnvironment class methodscurrent

Answers the current environment for Smalltalk. This is equivalent totyping env at a UNIX shell prompt.

getenv:Gets the environment string association with the specified string. Answersnil if none. This directly maps to the C function getenv().

new Answers a new instance of the receiver. The new environment is empty.

putenv:Adds the specified string (in the form, aKey=aValue) to the currentenvironment. This directly maps to the C function putenv().

startUpEnvironmentAnswers the start-up environment for the user process. This provides asnapshot of the environment in which Smalltalk is running.

UNIXEnvironment methodsat: Answers the object of the receiver that is associated with an object

equivalent to the specified key. Answers nil if the receiver does not containan object equivalent to the key.

at:ifAbsent:Answers the object of the receiver that is associated with an objectequivalent to the specified key. If an equivalent key is not found, answersthe result of evaluating the specified zero argument block. Returns fail ifthe key is not found and if the block is not a zero-argument block.

at:put: Associates the specified key with the specified value, in the receiver.Answers the value currently associated with aKey (or nil if absent). If thereceiver does not contain the specified key, it creates a new entry in thereceiver for that key.

envAt:Answers the value at the specified key in the receiver in the formaKey=aValue. If the key is missing, it generates an error.

envAt:ifAbsent:Answers the value at the specified key in the receiver in the formaKey=aValue. If an equivalent key is not found, answers the result ofevaluating the specified zero argument block.

envStringAt:ifAbsent:Answers the key-value pair in the receiver, indicated by the specified key.If an equivalent key is not found, answers the result of evaluating thespecified zero argument block.

keys Answers the environment keys in the receiver.

Usage exampleThis section contains examples using the UNIXEnvironment class. Evaluate each ofthe expressions by highlighting them and selecting Display from the Edit menu.

The UNIXEnvironment class retains a copy of the environment that was initiallyavailable. This is useful when the current environment has been changed andaccess to the original environment is required."Retrieve the user's start up environment."UNIXEnvironment startUpEnvironment

426 IBM Smalltalk: Programmer’s Reference

Page 441: IBM Smalltalk: Programmer's Reference

In most situations, processes created from within Smalltalk use the currentenvironment. The current environment can be accessed using the current method."Retrieve the current environment."UNIXEnvironment current

If a custom environment is desired, a new UNIXEnvironment can be created anddefined."Create a new environment and set some key-value pairs."| env |env := UNIXEnvironment new.env at: 'TEST' put: '123';

at: 'FRED' put: 'HELLO'.env

Accessing the environment information is accomplished using the at: method."Query the value of a particular environment variable from the user'sstart up environment."UNIXEnvironment startUpEnvironment at: 'HOME'

The keys method answers all of the keys in an instance of UNIXEnvironment. Thismethod is useful when checking a users configuration."Retrieve the names of all environment variables from the user'sstart up environment."UNIXEnvironment startUpEnvironment keys

If you are more familiar with the C language, you might want to use the getenv:message to access the current environment instead of querying the currentenvironment and using the at: message. The messages getnev and at: arefunctionally equivalent for operations on the current environment."Query the Smalltalk AIX process environment with a specific key.Equivalent to C function."UNIXEnvironment getenv: 'HOME'

"Query an environment using an instance of UNIXEnvironment."UNIXEnvironment current at: 'HOME'

Using the putenv: message is similar to the getenv: message except it is used to set avalue instead of query it. The messages putenv and at:put: are functionallyequivalent for operations on the current environment."Set a key-value pair in the Smalltalk UNIX process environment.Equivalent to C function."UNIXEnvironment putenv: 'TEST=1234'

"Set a key-value pair for an instance of UNIXEnvironment."UNIXEnvironment current at: 'TEST' put: '1234'.

UNIX processThis subsection describes a conceptual model of the UNIX process.

The C language process model is used by the UNIXProcess class. Each process isdefined as having an input stream (stdin), an output stream (stdout), and an errorstream (stderr). The streams made available by a UNIXProcess are defined whenthey are created.

There are three stages in the life of a UNIXProcess:

Chapter 14. Inter-process communication 427

Page 442: IBM Smalltalk: Programmer's Reference

1. Creation of an instance. This includes definition of the environment to be used,the arguments to be passed to the process, and a Boolean flag for theinput/output/error streams.

2. Reading or writing data on the input/output/error streams (blocking ornon-blocking).

3. Termination, either forced or automatic (blocking or non-blocking).

Through the UNIXProcess class, operating system processes can be controlled fromwithin Smalltalk.

Three file descriptors, stdin, stdout, and stderr, are available through the Clanguage. Direct access to these file descriptors is possible for each instance of theUNIXProcess class. While directly accessing the file descriptors is possible, astream-based abstraction is the preferred method of interaction.

An instance of the UNIXWritePipeStream class is used to access stdin whileinstances of UNIXReadPipeStream are used to access stdout and stderr. TheUNIXWritePipeStream class and UNIXReadPipeStream class (described in the sectionentitled “UNIX pipe stream” on page 431) support a subset of the stream protocol.An instance of UNIXProcess responds to the messages stdin, stdout, and stderr byanswering a UNIXPipeStream associated with the operating system’s stdin, stdoutor stderr pipe, respectively. If there is no corresponding UNIX pipe (if it was notrequested when the UNIXProcess was created), then nil is answered.

Note: Many UNIX processes that have stdin defined will not terminate unlessstdin has been closed. Sending the message close to the UNIXWritePipeStreamrepresenting stdin closes the pipe and allows the process to end if it isblocked on input.

Method specificationUNIXProcess methods and usage examples are described in the following section.

UNIXProcess class methodsendAsyncIO

Ends the background Smalltalk process handling asynchronous I/O.

execute:Creates a process to execute the specified string using the C shell in thecurrent environment. Starts the process running and answers the process. Ifan error occurs starting the process, answers nil.

execute:input:output:error:environment:Creates a process to execute the specified string using the C shell and thegiven environment. Starts the process running and answers the process. Ifan error occurs starting the process, answers nil. If any of the I/Oparameters are not nil, initializes the appropriate stdin, stdout, and stderrpipes.

shell: Invokes a C shell that executes the specified string in the currentenvironment. Answers the stdout contents and stderr contentsconcatenated. If an error occurs starting the process, generates a walkback.

startAsyncIOStarts a background Smalltalk process to grab I/O for the activeUNIXProcess and moves it between Smalltalk and the operating system.

428 IBM Smalltalk: Programmer’s Reference

Page 443: IBM Smalltalk: Programmer's Reference

system:Invokes a C shell that executes the specified string in the currentenvironment. Answers the integer exitCode of the process. If an error occursstarting the process, answers nil. If the UNIX primitive for completionchecking fails, generates a walkback.

UNIXProcess methodsclosePipe:

Closes the specified pipe. Generates a walkback if the pipe is not valid.

completeObsolete protocol retained for compatibility. It should be replaced withisComplete

exitCodeAnswers an integer representing the receiver’s exitCode. If the process hasnot completed, answers nil. This is operating-system dependent.

fillPipe:Flushes all data in the pipe from the operating system process associatedwith the receiver to the Smalltalk UNIXReadPipeStream. Generates awalkback if the specifed pipe stream is not an instance ofUNIXReadPipeStream or is not a valid UNIXPipeStream.

id Obsolete protocol retained for compatibility. Should be replaced with pid.

isCompleteAnswers true if the receiver process has completed, answers false if not. Ifthe UNIX primitive for completion checking fails, generates a walkback.

kill Kills the receiver process. Try using the SIGTERM signal first. If theprocess does not die within 5 seconds, sends the SIGKILL signal. Thismethod blocks until the process dies. Answers the receiver.

nextFrom:Answers the next available character from the receiver’s stdout. If the readwould block, answers nil. On any other error answers a character with avalue of zero.

nextPut:on:Writes a character to the receiver’s stdin pipe, specified by on:. Generates awalkback if the pipe is not valid. Answers the character.

pid Answers the integer representing the process id of the receiver’s operatingsystem process. If there is no corresponding operating system process,answers nil.

run Obsolete protocol retained for compatibility. Theexecute:input:output:error:environment: message encompasses this behavior.

stderr Answers a UNIXReadPipeStream representing the receiver’s stderr pipe, ornil if the pipe is undefined.

stdin Answers a UNIXWritePipeStream representing the receiver’s stdin pipe, ornil if the pipe is undefined.

stdout Answers a UNIXReadPipeStream representing the receiver’s stdout pipe, ornil if the pipe is undefined.

waitForCompletionEnsures the receiver has finished the last operation. Answers the exitCodeof the process. This is a blocking operation. If the stdin pipe has not beenclosed, the operation may block indefinitely.

Chapter 14. Inter-process communication 429

Page 444: IBM Smalltalk: Programmer's Reference

Usage exampleThis section contains examples using the UNIXProcess class. Evaluate each of theexpressions by highlighting them and selecting Display from the Edit menu.

One common use for a UNIXProcess is to invoke shell commands from withinSmalltalk and capture the output."Display on the Transcript the result of a shell command."Transcript show: (UNIXProcess shell: 'ls -al')

To invoke a command and not capture the output, the system message is used."Perform a shell command and direct output to the start up terminal"UNIXProcess system: 'env'

In some situations the shell: and system: messages do not provide sufficient controlover the process. The following example shows the three stages of a UNIXProcess:creation, the reading and writing of data, and termination."Connect user defined streams to the UNIX process stdin, stdoutand stderr."| process output input result |

process := UNIXProcess "Create the process."execute: 'cat'input: trueoutput: trueerror: nilenvironment: UNIXEnvironment current.

input := process stdin.output := process stdout.input

nextPutAll: 'This is input sent into standard in';close.

process waitForCompletion. "Wait for process to terminate."output contents

Using the stream interface, it is possible to interact with a process. Future input tothe process can be determined by the currently available output or state of theprocess."It is not necessary to provide all input immediately."| process output input result |process := UNIXProcess "Create the process."

execute: 'cat'input: trueoutput: trueerror: nilenvironment: UNIXEnvironment current.

input := process stdin.output := process stdout.input

nextPutAll: 'This'; "Perform read/writes of data."flush.

process isComplete ifTrue: [self error: 'Process should not be complete'].input

nextPutAll: ' is input sent into standard in';close.

process waitForCompletion. "Wait for process to terminate."output contents

The following code is an example method for an application. The method makesuse of the UNIXProcess class to mail a message to a collection of recipients with agiven subject. A method similar to this could be used to interface to the UNIX mailfacilities from within Smalltalk.

430 IBM Smalltalk: Programmer’s Reference

Page 445: IBM Smalltalk: Programmer's Reference

Note: Highlighting the following example code and selecting Display will notwork. It is a method and requires parameters."Send mail and ignore the reply."mail2: recips subject: subject msg: string| process args env |args:= '/usr/ucb/mail'.recips do: [:person | args := args, ' ', person].env := UNIXEnvironment current.

process := UNIXProcessexecute: argsinput: trueoutput: trueerror: nilenvironment: env.

process stdinnextPutAll: 's ',subject; cr;nextPutAll: string; cr;close.

process waitForCompletion.|process exitCode

UNIX pipe streamThis subsection describes a conceptual model of the UNIX pipe stream.

In the C language, three file descriptors are made available to processes: stdin,stdout, and stderr. The stdin file descriptor is used to provide input to the process,while stdout and stderr are for output and error output respectively. The Smalltalkinterface to these pipe handles is either an instance of UNIXWritePipeStream orUNIXReadPipeStream.

Both the UNIXWritePipeStream and UNIXReadPipeStream classes respond to a subsetof the stream protocol. The pipe stream interface permits modification of theposition in the stream. This means that a UNIXReadPipeStream can be reset andre-read; similarly, a UNIXWritePipeStream can be reset and the same input flushed asecond time.

Instances of UNIXWritePipeStream and UNIXReadPipeStreams should never becreated directly. They should be requested when the process is created through theexecute:input:output:error:environment: message supported by UNIXProcess.

UNIX read pipe stream method specificationUNIXReadPipeStream methods are described in the following section.

UNIXReadPipeStream class methodsfor: Answers a new, initialized instance of a UNIXReadPipeStream for the

specified process.

UNIXReadPipeStream methodsatEnd Answers a Boolean that is true if the receiver cannot access any more

objects, otherwise answers false.

blocking:Sets a Boolean that indicates whether or not the receiver will block on I/Ooperations. Answers the receiver.

close Closes the receiver’s associated UNIX pipe. If any unread information is

Chapter 14. Inter-process communication 431

Page 446: IBM Smalltalk: Programmer's Reference

available from the operating system, this is transferred to the receiver.Closes the operating system pipe. The receiver is no longer valid for filloperations. Answers the receiver.

contentsAnswers the current contents of the receiver as a String.

copyFrom:to:Answers the subcollection of the collection over which the receiver isstreaming, from the first specified index to the last specified index. If thereceiver is blocking, enough data is read to satisfy the request, or untilatEnd is true. If the receiver is non-blocking, then it uses only currentlyavailable data.

do: Evaluates the specified block once for each element in the receiver, fromthe element after the current position to the end. If the receiver is blocking,data is read until atEnd is true. If the receiver is non-blocking then it usesonly currently available data.

fill Guarantees that any pending data from the receiver’s UNIX process hasbeen flushed to the pipe stream. Answers the receiver.

isBlockingAnswers true if the receiver has been set to block on I/O, otherwiseanswers false.

isBytesAnswers true if the receiver handles I/O data as bytes, otherwise answersfalse.

isBytes:If flag is true, sets the receiver’s I/O data type to bytes. If flag is false, setsthe I/O data type to characters. Answers the receiver.

isCharactersAnswers true if the receiver answers I/O data as characters.

isCharacters:If flag is true, sets the receiver’s I/O data type to characters. If flag is false,sets the I/O data type to bytes. Answers the receiver.

isEmptyAnswers true if the receiver pipe stream currently contains no elements,otherwise answers false.

lineDelimiterReturns the line delimiter of the receiver.

lineDelimiter:Sets the line delimiter of the receiver.

next Answers the next character accessible by the receiver and advances thereceiver’s position. Answers nil if the read would block. Reports an error ifno data is available to be read.

next: Answers the next specified integer number of items from the receiver,returned in a collection of the same type as the collection being streamedover. If the receiver’s state is such that there are fewer than the specifiednumber of integer elements between its current position and the end of thestream, the operation fails, and the receiver is left in a state such that itanswers true to the atEnd message.

432 IBM Smalltalk: Programmer’s Reference

Page 447: IBM Smalltalk: Programmer's Reference

nextLineAnswers the elements between the current position and the nextlineDelimiter.

nextMatchFor:Answers true if the next element which is accessible by the receiver isequal to the target, otherwise answers false.

peek Answers the next object in the receiver stream without advancing thereceiver’s position. If the receiver is positioned at the end, answers nil.

peekFor:Answers true if the next object to be accessed in the receiver stream equalsthe specified byte or character, otherwise answers false. Only advances thereceiver’s position if the answers is true.

positionAnswers the current position of the receiver.

position:Sets the current position of the receiver to the specified integer. If theposition is out of bounds, sets the position to the closest valid position.

reset Positions the receiver to the beginning of the collection being streamedover. Answers the receiver.

setToEndSets the receiver’s position reference to be the size of the underlyingcontents. Answers the receiver.

size Answers the number of elements in the receiver.

skip: Increments the position of the receiver by the specified integer. Fails if theargument is not a kind of integer. Answers the receiver.

skipTo:Advances the receiver’s position beyond the next occurrence of thespecified object, or if none, to the end of stream. Answers true if the objectoccurred, otherwise answers false.

Note: skipTo: is a blocking operation.

skipToAll:Advances the receiver’s position beyond the next occurrence of theelements of the sequential collection, or if none, to the end of stream.Answers true if the elements of the sequential collection occurred,otherwise answers false. Non-blocking streams operate on the currentlyavailable data.

upTo: Answers the collection of objects from the receiver starting with the nextaccessible object and up to but not including the specified object. Sets theposition beyond the object. If the object is not present, answers theremaining elements of the stream. Non-blocking streams operate on thecurrently available data.

upToAll:Answers the collection of objects from the receiver starting with the nextaccessible object and up to but not including the specified sequentialcollection. Sets the position beyond the sequential collection. If thesequential collection is not present, answers the remaining elements of thestream. Non-blocking streams operate on the currently available data.

Chapter 14. Inter-process communication 433

Page 448: IBM Smalltalk: Programmer's Reference

upToEndAnswers the subcollection of the collection over which the receiver isstreaming, from the current position to the end of the accessible elements.Non-blocking streams operate on the currently available data.

UNIX write pipe stream method specificationUNIXWritePipeStream methods are described in the following section.

UNIXWritePipeStream class methodsfor: Answers a new, initialized instance of a UNIXWriteReadPipeStream for the

specified process.

UNIXWritePipeStream methodsatEnd Answers a Boolean that is true if the receiver cannot access any more

objects, otherwise answers false.

blocking:Sets a Boolean that indicates whether or not the receiver will block on I/Ooperations. Answers the receiver.

close Closes the receiver’s associated UNIX pipe. If any unwritten informationremains in the receiver, it is flushed to the operating system before thepipe is closed. The operating system pipe is closed, and the receiver is nolonger valid for flush or write operations. Answers the receiver.

contentsAnswers the current contents of the receiver as a String.

cr Writes a logical carriage return to the receiver.

Note: Currently, all write operations are blocking.

flush Guarantees that all available data in the receiver is sent to the operatingsystem pipe. This is a blocking operation. Answers the receiver.

isBlockingAnswers true if the receiver has been set to block on I/O, otherwiseanswers false.

isBytesAnswers true if the receiver handles I/O data as bytes, otherwise answersfalse.

isBytes:If flag is true, sets the receiver’s I/O data type to bytes. If flag is false, setsthe I/O data type to characters. Answers the receiver.

isCharactersAnswers true if the receiver handles I/O data as characters.

isCharacters:If flag is true, sets the receiver’s I/O data type to characters. If flag is false,sets the I/O data type to bytes. Answers the receiver.

isEmptyAnswers true if the receiver pipe stream currently contains no elements,otherwise answers false.

lineDelimiterReturns the line delimiter of the receiver.

434 IBM Smalltalk: Programmer’s Reference

Page 449: IBM Smalltalk: Programmer's Reference

lineDelimiter:Sets the line delimiter of the receiver to be the specified string.

next:put:Answers the specified object. Puts the object to the receiver’s pipe thenumber of times specified by next:. Fails if next: does not specify an integer.

nextPut:Writes a byte or a character to the receiver’s pipe. Answers the receiver.

nextPutAll:Writes the specified sequential collection to the receiver’s pipe. Answersthe sequential collection.

positionAnswers the current position of the receiver.

position:Sets the current position of the receiver to the specified integer. If theposition is out of bounds, sets the position to the closest valid position.

reset Positions the receiver to the beginning of the collection being streamedover. Answers the receiver.

setToEndSets the receiver’s position reference to be the size of the underlyingcontents. Answers the receiver.

size Answers the number of elements in the receiver.

skip: Increments the position of the receiver by the specified integer.

space Writes a space character to the receiver’s pipe.

tab Writes a tab character to the receiver’s pipe.

Chapter 14. Inter-process communication 435

Page 450: IBM Smalltalk: Programmer's Reference

436 IBM Smalltalk: Programmer’s Reference

Page 451: IBM Smalltalk: Programmer's Reference

Chapter 15. Object Linking and Embedding (OLE)

This chapter describes how to use the OLE application framework to buildOLE-enabled client applications.

First, what is OLE? This is the definition from Inside OLE (Second Edition) byKraig Brockschmidt of Microsoft:

OLE is a unified environment of object-based services with the capability ofboth customizing those services and arbitrarily extending the architecturethrough custom services, with the overall purpose of enabling rich integrationbetween components.

OLE is Microsoft’s entry into the world of object-oriented computing. At the lowestlevel, object-based services are provided by C++ classes. These classes are calledinterfaces. Interfaces can be defined in any language but are most easily defined inC++. When one component needs to talk to another, it queries for a well-knowninterface. If the query succeeds, an instance of the interface is returned.Functionality is accessed using the methods of the interface. Access to the privatestate of the instance is not allowed.

To ensure binary compatibility and language independence in OLE, interfaces arewell known and strictly defined. The fact that interfaces resemble C++ classes isincidental. Inheritance is not supported and methods are used in the same waythat jump tables to functions are used in standard C.

Microsoft has defined a client/server environment for Windows where a client isdefined as the user of a service and a server is defined as the provider. It is usefulto partition OLE functionality in terms of client/server to focus on how OLE isused. For example, OLE provides custom control services (more commonly knownas OCXs). An OCX client is any application that uses the OCX. An OCX serverimplements the OCX.

OLE programming is complex, error-prone, and time-consuming. To program OLE,it is necessary to implement and query many interfaces during the lifetime of theprogram. Because interfaces come from other applications, their behavior may ormay not conform to the interface specification. In many cases, the specification isvague, making it necessary to determine behavior by experimentation.

The problem is further compounded by the fact that when writing an interface,much of the implementation can be easily and trivially defaulted, yet must bepresent for the interface to work. This leads to increased code bulk and complexity.The fact that there are multiple interfaces that are often tightly coupled leads todesign confusion, which is often resolved by trial and error by the less-experiencedOLE programmer.

To overcome the complexity of OLE, development environments normally providea higher-level OLE application framework:

Visual C++Microsoft provides the Microsoft Foundation Classes (MFC), a C++ classlibrary, that comes with Visual C++. The MFC hierarchy encapsulates OLE

© Copyright IBM Corp. 1994, 2000 437

Page 452: IBM Smalltalk: Programmer's Reference

(and Windows) in a C++ class library. Using MFC, you can access most ofOLE without using low-level OLE interfaces.

Visual BasicExtensions to the Visual Basic widgets and the usual syntax of Visual Basicexpose OLE.

SmalltalkThe OLE application framework provides high-level support for writingOLE clients in Smalltalk.

The framework provides high-level abstractions for the OLE containerconcepts, thereby keeping the low-level OLE interfaces transparent to you.Using this framework, you can write OLE container applications thatsupport embedding, linking, in-place activation, drag/drop, and structuredstorage. The framework supports writing OLE automation controllers,whereby third-party automation servers (such as Microsoft Word orMicrosoft Excel) can be programmed from Smalltalk. In addition, you caneasily and quickly incorporate arbitrary, off-the-shelf OCXs into theSmalltalk image and materialize them as Common Widgets.

OLE concepts and definitionsBefore building an OLE-enabled application, it is helpful to become familiar withthe following concepts and definitions.

OLE clientAn OLE client is an application that accesses and uses the functionalityand content of a OLE server application. The communication between anOLE client and an OLE server is through OLE object interfaces. VisualAgeclients can connect to OLE servers regardless of the server’simplementation language.

OLE serverAn OLE server is the provider of a component and its constituent objects.You can implement OLE servers as DLLs or as complete applicationsoperating in an execuatable.

Compound documentA compound document is an application that results in the seamlessintegration of data of different formats, such as spreadsheets, sound clips,text, and bitmaps. A compound document is an OLE client that integratesdata and functionality from a variety of OLE servers. End users perceivethey are using a single application that provides all the function of therespective servers.

OLE containerAn OLE container is an OLE client that consumes compound-documentobjects, OCXs, or both. OLE containers typically provide:v Storage for the contained OLE objectsv A place in their user interface for the OLE objects to display their

contentsv Access to the editing facilities of the server for the OLE objects.

Embedded OLE objectsAn OLE object is embedded in its container when its data is physicallystored with the container. As a result, the OLE object becomes a physicalpart of its container.

438 IBM Smalltalk: Programmer’s Reference

Page 453: IBM Smalltalk: Programmer's Reference

Linked OLE objectsAn OLE object is linked to its container when its data continues tophysically reside where it was initially created. Only a reference (that is, alink) to the object and the appropriate presentation data are maintained bythe container.

ActivationActivation is the process of making an OLE server active on the contentsof one of its embedded or linked OLE objects that are in a container. Acontainer does not directly reference or modify the content of its containedOLE objects, so the respective servers are activated to provide facilities soyou can edit and manipulate the contained content.

Verb OLE servers are activated by invoking an action on them; the action iscalled a verb. The most common verb is the edit verb, which activates theserver in a state for editing the contents of the embedded or linked object.OLE servers always designate one verb as the primary verb, which is mostoften the edit verb. However, a sound or video object may have play as itsprimary verb and edit as a secondary verb. Many OLE document serverssupport more than one verb.

A container typically displays an OLE object’s verbs as commands on oneof its own menus. When you select a verb, the container passes it to theserver for execution. When the server receives a verb, it may open as usualin its own window to allow you to edit the OLE object, or it may attemptto interact with the user directly inside the container’s window. The latteris called in-place activation.

In-place activationOLE objects that are embedded in a container application can be edited(that is, activated) in place, which means that all maintenance of the objecttakes place within the container. When an OLE object is activated in place,the menu bar for the container becomes a mixture of the current containermenus and the menus provided by the server. In addition, real estate inthe container’s windows is negotiated for any of the tool bars and floatingpalettes that the server provides for editing the object.

Since the content of a linked OLE object is not stored with the container,linked objects cannot be activated in place; they are activated in thewindows of their server.

OLE automation clientAn OLE automation client is an application that accesses functionalityprovided by third-party applications. OLE automation is a standard thatallows communication between applications. For example, a program canquery and set the current text selection in a Microsoft Word documentthrough OLE automation.

OLE automation serverAn OLE automation server makes functionality available by exposing OLEobjects. These objects have properties and methods. An OLE property is avalue that an application can get and set. An OLE method is amulti-parameter function that is called by an automation client andimplemented by an automation server.

OLE custom control (OCX)An OCX is a custom Windows control that is built with OLE technologies.Unlike a Windows control, an OCX may or may not have a visualrepresentation. OCXs build on almost all the base OLE technologies. Forexample, an OCX uses:

Chapter 15. Object Linking and Embedding (OLE) 439

Page 454: IBM Smalltalk: Programmer's Reference

v In-place activation for its content display in a client application’s userinterface

v The server side of OLE automation for control of its properties andbehavior

v The client side of OLE automation for event notification from the serverto the client.

PropertiesA property is a data attribute (or a variable) of an OLE automation objector an OCX that is retrieved or modified by a container. Properties of anOLE automation or OCX object are identified by both a unique name and aunique numeric value.

Ambient propertiesAmbient properties are attributes of an OCX container that are suppliedon request to any of its embedded OCXs. These properties define theenvironment (or ambiance) for all OCXs used in an application, forexample, default colors and fonts. OCXs typically initialize their statethrough ambient-property requests to the container. However, containersmay explicitly override an OCX property that was obtained from itsambient property.

Event An event is a notification that an OCX sends to its container when the usertriggers an event in that OCX, for example, a mouse-click on the OCX. AnOCX uses events to transform a user’s action into a precise trigger on itscontainer, which in turn picks up the event and executes some code.

DISPIDEach method or property of an OLE automation or OCX object has aunique name and a unique DISPID (a 32-bit number). A DISPID is thepreferred way to access a method or property because it reduces expensivestring lookup operations and is independent of the national language usedto define the names.

LicensingLicensing is a mechanism that OCX vendors use to restrict the use of theirOCX in container applications. Licensed OCXs provide a key that acontainer must use to activate the OCX at run time.

OLE classesThe OLE application framework consists of the following classes:

OleMainWindowOleMainWindow is a subclass of CwMainWindow. It extends the functionality of amain window to support menu-bar negotiation when an object is activated inplace. You must use an OleMainWindow instead of CwMainWindow in anyapplication that embeds or links OLE objects or uses OCXs.

When an embedded OLE object is activated in place, the menu bar for thecontainer becomes a mixture of the container’s current menus and the menusprovided by the server. Menu-bar items are divided into these groups:v Filev Editv Containerv Objectv Windowv Help

440 IBM Smalltalk: Programmer’s Reference

Page 455: IBM Smalltalk: Programmer's Reference

When an object is activated in place, the container provides these groups:v Filev Containerv Window

The server provides these groups:v Editv Objectv Help

A container provides the OleMainWindow with the pull-down menus for each ofthe groups it is responsible for. For example, a container might specify its in-placemenu-bar groups as follows:anOleMainWindow

fileMenuGroup: (Array with: fileMenuCascade);containerMenuGroup: (Array with: optionsMenuCascade with: featuresMenuCascade);windowMenuGroup: (Array with: windowMenuCascade)

Hence, when an embedded OLE object is activated in place, a merged menu bar isbuilt and managed by the OleMainWindow—first using the menus specified by thecontainer, and then querying the server for its menu groups. In addition, real estatein the container’s OleMainWindow is negotiated for any tool bars and floatingpalettes that the server provides for editing the object. When the embedded objectis deactivated, the original menu bar of the OleMainWindow is restored along withany window areas used by the server for tool bars and so on.

OlePrimitiveOlePrimitive is a subclass of CwPrimitive. It defines common behavior to widgetsthat provide sites for OLE embedded, linked, or OCX objects. Applications that useOlePrimitive widgets must use OleMainWindow in their runtime widget hierarchyinstead of CwMainWindow.

OleClientThe OleClient class is a subclass of OlePrimitive. It allows OLE objects from otherapplications to be embedded or linked into an IBM Smalltalk or VisualAgeapplication. An OleClient contains the OLE object and allows that object to behavelike other Common Widgets.

With OleClient, you can do the following:v Create a placeholder in the container’s user interface to contain an embedded or

linked OLE object—the OLE object that appears within the OleClient is created atrun time

v Insert embedded or linked OLE objects directly from their server into a containerv Create embedded or linked OLE objects from a server-generated filev Create embedded or linked OLE objects from the clipboard or from dragging or

dropping between other OLE-enabled third-party applicationsv Display embedded or linked OLE objects as iconsv Activate an embedded OLE object in place if in-place activation is supported by

its serverv Within the container’s user interface, allow for resizing and movement of an

embedded or linked OLE object.

Chapter 15. Object Linking and Embedding (OLE) 441

Page 456: IBM Smalltalk: Programmer's Reference

OleControlThe OleControl is a subclass of OlePrimitive. It allows you to insert OCXs and usethem in an IBM Smalltalk or VisualAge application. An OleControl widget containsan OCX and allows that object to behave like any other CwPrimitive.

With OleControl, you can do the following:v Create a placeholder in the container’s user interface to contain an OCXv Set properties and the control function of the contained OCXv Use the Common Widgets event-handler mechanism to trap and process events

generated by the contained OCXv Provide hooks that allow the OCX access to specific properties of the

application’s user interface components, for example, access to an application’sambient properties

v Use licensed OCXs within an application

OleAutomationObjectAn OleAutomationObject provides a programming interface to OLE automationobjects exposed by an OLE server. OLE automation objects contain data(properties) and the functions (methods) used to perform an action with the object.For example, Microsoft Excel handles all the operations and data associated with arange of cells in a spreadsheet. With OleAutomationObject, you can do thefollowing:v Create an instance of OleAutomationObject that references an OLE automation

server object through a name, through a server file, or from an existingembedded or linked OleClient object

v Set or retrieve properties of an OLE automation server objectv Invoke methods on an OLE automation server object.

OleFileAn OleFile enables you to transparently persist embedded or linked OLE objectsinto files. An OleFile works with an OleClient or OleControl widget to performpersistence operations on their contained OLE objects. Items stored into an OleFileare identified by a unique name that you provide when the object is saved.

Using instances of OleFile, you also can associate arbitrary data attributes with astored OLE object. These attributes are referenced for storage and retrieval byusing the same name the object was stored under. You can use this feature, forexample, to store various attributes of the OleClient widget containing the OLEobject, such as, its position, width, and height.

There is an additional facility in OleFile to store and retrieve a set of data attributesthat may be global to all the OLE objects stored within the file.

Building an OLE document containerAn OLE document container is an application that supports embedding or linkingobjects from other OLE-enabled applications. The document container provides aplace in its user interface for the OLE object to display its contents (or its icon) andoptionally allows that object to be edited by its server. The container may alsoallow embedded or linked OLE objects to be:v Physically moved or resized within its own windowsv Copied to the clipboard for pasting into another application

442 IBM Smalltalk: Programmer’s Reference

Page 457: IBM Smalltalk: Programmer's Reference

v Dragged to another application

In addition, a container may save the data associated with an embedded OLEobject directly into one of its own files.

The steps to create an OLE-enabled application that will contain OLE objects are:1. As part of the initialization of the user-interface widget hierarchy, create an

OleMainWindow and enable its menu groups to support in-place activation ofany descendent OleClient widgets.

2. Implement methods to create OleClient widgets and create the OLE objects thatwill appear within their borders.

3. Implement methods to enable copying, cutting, and pasting OLE objects to andfrom the clipboard.

4. Create and manage a menu containing the OLE object’s verbs.5. Invoke the Links dialog to allow a user to manage the links of any linked OLE

objects.6. Save and restore embedded or linked OLE objects to and from files.

Creating an OLE main windowOLE-enabled applications must use the OleMainWindow class rather thanCwMainWindow. This is because OLE main windows can negotiate with OLEservers for menu-bar space and window real estate for in-place activation of anyOLE object contained in its widget tree. An OleMainWindow is a subclass ofCwMainWindow and, as such, it is created in the same way. The helper methodcreateOleMainWindow: in CwWidget provides typical widget-creation protocol.

For example, a method of an OLE-enabled application that creates anOleMainWindow under a shell window might look like:createMainWindow: shell

"Private - Create and answer the main window for the receiver."|(shell

createOleMainWindow: 'main'argBlock: [:w | w hostName: 'Container']) manageChild

Here, the hostName resource is set even though it is often only used bynon-in-place-activated OLE servers. In the case of non-in-place activation, thehostName may be displayed on the label of an OLE server’s Close or Exit menuitems. For example, given the hostName above, the label of an activated OLEserver’s normal termination menu item might read Exit to Container instead ofsimply Exit, as it would when the server application is explicitly launched. Themenu bar of an OleMainWindow is partitioned into groups to facilitate thenegotiation for menu-bar space during in-place activation. The groups are:v Filev Editv Objectv Containerv Windowv Help

Each group contains one or more pull-down menus (CwCascadeButton widgets).During in-place activation, the container is asked to populate the File, Container,and Window groups with pull-down menus appropriate to those categories of

Chapter 15. Object Linking and Embedding (OLE) 443

Page 458: IBM Smalltalk: Programmer's Reference

function. After the container populates its groups, the server is asked to fill in theEdit, Object, and Help groups with pull-down menus appropriate for its editingoperations.

A container’s menu-bar negotiations with an OLE server are handled automaticallyby OleMainWindow. As a result, all you need do to facilitate these negotiations isprovide the pull-down menus for any of the three groups it is interested in.OleMainWindow has the following instance methods for each designated menugroup.

File fileMenuGroup:

ContainercontainerMenuGroup:

WindowwindowMenuGroup:

Each method takes an Array containing CwRowColumn widgets representing themenus for the group.

For example, the createMenuBar: method of an OLE container might have fivepull-down menus defined for its normal operation and specify three of them foruse when any contained OLE object is activated in place:createMenuBar: mainWindow

"Private - Create and answer the menu bar for the receiver."| menu children |menu := mainWindow

createSimpleMenuBar: 'bar'argBlock: [:w |

wbuttons: #('File' 'Edit' 'Container' 'Window' 'Help');buttonMnemonics: #($F $E $C $W $H)].

children := menu children.

mainWindowfileMenuGroup: (Array with: (children at: 1));containerMenuGroup: (Array with: (children at: 3));windowMenuGroup: (Array with: (children at: 4)).

menu manageChild.|menu

During in-place activation, all other negotiations for window real estate (forexample, tool-bar and status-bar space) between an OLE container and an OLEserver are transparently handled by the OleMainWindow class. The menu groupcannot be changed while an OLE client is active in place.

Creating OLE clientsAn OleClient widget provides an OLE container the place to put embedded orlinked OLE objects. An OleClient is a primitive widget, thus conforms to allstandard management of widget geometry. An OleClient widget contains aconnection to an embedded or linked OLE object and transparently manages alllow-level OLE interaction with that object. The contained OLE object renders itscontent on the OleClient widget, which may be configured to allow the user toresize its area or move it within its enclosing window.

OleClient widgets are created and managed like other primitive widgets. However,there are several techniques for creating and connecting an embedded or linkedOLE object to an OleClient widget.

444 IBM Smalltalk: Programmer’s Reference

Page 459: IBM Smalltalk: Programmer's Reference

Some techniques create and connect an embedded or linked OLE object at thesame time as the OleClient widget is created. These include creating an OLE objectby its registered name or from one of its server files.

Other techniques create and connect the OLE object after the widget has beencreated but before it is managed in the widget tree. These include creating an OLEobject from the following:v An invocation of the Insert Object dialogv The clipboard through the Paste Special dialogv The clipboard without going through the Paste Special dialogv A drag and drop operation that uses the framework described in “Chapter 9.

Drag and Drop” on page 263.

Creating by nameTo create an OLE object and connect it with an OleClient widget, the OLE object’sserver must be registered in the system registry, which is often called the“registration database”. One of the attributes of the registration is theprogrammatic identifier, or ProgId, which identifies the registered OLE object. TheProgId of a registered OLE object is the name used for the clientName resource ofan OleClient.

Since OLE clients are created as child widgets of non-primitive widgets (that is,any CwComposite), there is an additional widget-creation convenience methodimplemented in CwWidget called createOleClient:argBlock:. Hence, knowing an OLEobject’s ProgId, an OLE client is simply created and connected to the OLE object.

For example, an embedded Microsoft Word document is created using:| client |

client := compositecreateOleClient: 'client'argBlock: [:w |

wx: 50;y: 50;width: 200;height: 200;clientType: XmEMBEDDED;clientName: 'Word.Document.6'].

client manageChild.

Here, the clientType resource is set to XmEMBEDDED and specifically requests thatthe OLE object named ‘Word.Document.6’ be embedded into the new OleClient.This code fragment creates an OleClient widget that contains an empty embeddedMicrosoft Word document. Double-clicking anywhere on the OleClient widgetcauses Microsoft Word to be activated in place and ready for editing the embeddeddocument.

Creating from a fileCreating an OleClient from an OLE object server’s data file is similar to creating byname. To create from a file, the file must already be created by the OLE server.

An embedded OLE object can be created from an existing Microsoft Worddocument file using:| client |

client := compositecreateOleClient: 'client'argBlock: [:w |

wx: 50;

Chapter 15. Object Linking and Embedding (OLE) 445

Page 460: IBM Smalltalk: Programmer's Reference

y: 50;width: 200;height: 200;clientType: XmEMBEDDED;sourcePath: 'c:\docs\sample.doc'].

client manageChild.

The OleClient is created to be linked to the same document file by changing theclientType resource to XmLINKED. For example, an OleClient is created to be linkedto a Microsoft Word document file using:| client |

client := compositecreateOleClient: 'client'argBlock: [:w |

wx: 50;y: 50;width: 200;height: 200;clientType: XmLINKED;sourcePath: 'c:\docs\sample.doc'].

client manageChild.

The embedded and linked cases look the same to the user. However, in the linkedcase, when the user double-clicks on the OleClient, Microsoft Word opens in itsown windows for editing the linked document; it does not activate in place in thecontainer. Furthermore, since the OleClient is linked to the file, other users canseparately edit the file and modify its contents. However, an OleClient can beexplicitly updated to reflect third-party changes in the linked OLE object’s contentby sending the OleClient the updateFromLink message.

Creating from the Insert Object dialogMany containers let their users insert registered OLE objects into the application.To support this, the OleClient widget provides access to the standard OLE InsertObject dialog. This dialog can be invoked from an existing OleClient through itspromptInsertObject: method.

Applications typically offer access to this dialog through one of their menu items.In fact, the OLE user-interface guidelines suggest offering an Insert Object item oneither an Edit or Insert pull-down menu. Before the Insert Object dialog can beinvoked, an OleClient widget must already exist and must not be connected to anOLE object. For example, an Insert Object menu item callback might look like:menuEditInsertObject

"Private - Process the Edit menu Insert item."| client result |

446 IBM Smalltalk: Programmer’s Reference

Page 461: IBM Smalltalk: Programmer's Reference

client := compositecreateOleClient: 'client'argBlock: [:w |

wx: 20;y: 40;width: 200;height: 200].

clientmappedWhenManaged: false;manageChild.

result := client promptInsertObject: XmANY.result == nil ifTrue: [|client destroyWidget]. "Dialog canceled"result

ifTrue: [client mappedWhenManaged: true.|self].

ifFalse: [CwMessagePrompter warn:('The server application, source file, or item cannot be found.\','Make sure the application is properly installed, and that it \','has not been deleted, moved or renamed.') addLineDelimiters].

In this example, the OleClient is first created with an initial position and size. TheOleClient widget is then managed. It is not, however, made visible to you usingmappedWhenManged: false until the embedded or linked OLE object is created andconnected to the widget. The parameter to promptInsertObject: specifies what kindof OLE object can be inserted in the widget. If XmANY is specified, for example,you can select the Create from File option in the dialog and then optionally selectLink.

For each resource value designated below, you can take the designated action withthe inserted OLE object:XmANY

Can be embedded or linkedXmLINKED

Must be linkedXmEMBEDDED

Must be embedded

If promptInsertObject: answers true, an OLE object was created and connected to theOleClient widget, which can then be mapped with the message clientmappedWhenManaged: true.

If promptInsertObject: answers nil, you canceled the dialog. However, if it answersfalse, the creation of the OLE object failed.

If you insert an object from a file, whether it is linked or not, the widget displaysthe contents of that OLE object. However, if the OLE object is inserted asembedded, there is nothing to display, and the OLE object is immediately activatedto let you enter some initial content.

Note: An OleClient can be queried to determine whether it is embedded or linkedby sending isEmbedded or isLinked.

Creating from the Paste Special dialogWhen an OLE object is copied to the clipboard, its server renders the object inmany different formats, many of which are required by OLE for interoperabilitywith other OLE-enabled applications.

Chapter 15. Object Linking and Embedding (OLE) 447

Page 462: IBM Smalltalk: Programmer's Reference

The OLE system provides a standard dialog called Paste Special, which allows youto select which object format to paste into their application. An OleClient widgetprovides access to the Paste Special dialog through its promptPasteSpecial: instancemethod.

As with the Insert Object dialog, applications typically offer access to the PasteSpecial dialog through one of their menu items. Again, the OLE user interfaceguidelines suggest offering a Paste Special item on the Edit pull-down menu.Before the Paste Special dialog can be invoked, an OleClient widget must alreadyexist and must not be connected to an OLE object. For example, a Paste Specialmenu item callback might look like:menuEditPasteSpecial

"Private - Process the Edit menu Paste Special item."| client |client := composite

createOleClient: 'client'argBlock: [:w |

wx: 20;y: 40;width: 200;height: 200].

clientmappedWhenManaged: false;manageChild.

(client promptPasteSpecial: XmANY) == trueifFalse: [|client destroyWidget].

client mappedWhenManaged: true

In this example as in the one before it, the OleClient is first created with an initialposition and size. The OleClient widget is then managed but not made visible toyou until the OLE object is created and connected to the widget. The parameter topromptPasteSpecial: takes the same values as promptInsertObject:. If XmANY isspecified, for example, you can select the Paste Link option in the dialog to createa linked OLE object.

If promptPasteSpecial: answers true, an OLE object was created and connected to theOleClient widget. The widget can then be mapped and the OLE object madevisible.

If promptPasteSpecial: answers nil, you canceled the dialog. However, if it answersfalse, the creation of the OLE object failed.

OLE servers render a variety of formats on the clipboard when one of their objectsis copied. With the Paste Special dialog, you can select for embedding one of the

448 IBM Smalltalk: Programmer’s Reference

Page 463: IBM Smalltalk: Programmer's Reference

non-object renderings, such as a metafile or bitmap. In this case, the image of therendering appears in the OleClient widget when it is mapped, but it you cannotactivated it. This is known as static embedding. The instance methodisStaticEmbedding is available to query an OleClient to see whether it has a staticembedding. For example, if a container application disallows static embedding, itcould test using:((client promptPasteSpecial: XmANY) x= true or: [client isStaticEmbedding])

ifTrue: [|client destroyWidget].

Enabling clipboard operationsOLE containers often allow any embedded or linked OLE object to be copied to thesystem clipboard for pasting into another application. To support this activity, theOleClient class provides a special clipboard format rendering that manages theunderlying OLE formats required to make this work.

This format is OLE object and its rendering is obtained from an OleClient throughits instance method oleObjectDescriptor. This special OLE object clipboard renderingis copied to the clipboard using the standard Common Graphics clipboardoperations on a CgDisplay object:v clipboardStartCopy:clipLabel:itemIdReturn:v clipboardCopy:itemId:formatName:buffer:privateId:v clipboardEndCopy:itemId:

For more information, refer to the Common Graphics discussion in “Chapter 6.Common Graphics” on page 79.

As an example, consider the following callback method for the Copy menu item:menuEditCopy

"Private - Process the Edit menu Copy item."| widget display window itemIdHolder |(widget := self shell focusWidget) isOleClient

ifFalse: [|self].display := self shell display.

window := self shell window.itemIdHolder := ReturnParameter new.(display

clipboardStartCopy: windowclipLabel: self shell titleitemIdReturn: itemIdHolder) = ClipboardSuccess

ifFalse: [|false].

displayclipboardCopy: windowitemId: itemIdHolder valueformatName: 'Ole Object'buffer: widget oleObjectDescriptorprivateId: 0.

|(display clipboardEndCopy: window itemId: itemIdHolder value) = ClipboardSuccess

This example first finds the widget that currently has focus in the shell’s widgettree. It then queries that widget, using isOleClient, to determine whether it is anOleClient widget. If it is, the remainder of the method uses standard clipboardprotocol on the shell’s CgDisplay to copy the special OLE clipboard formatrendering.

Conversely, performing a direct paste operation of an OLE object from theclipboard requires getting the OLE object format rendering from the clipboard andgiving it to an OleClient widget to create and connect to the referenced OLE object.

Chapter 15. Object Linking and Embedding (OLE) 449

Page 464: IBM Smalltalk: Programmer's Reference

The paste operation uses the standard CgDisplay protocols for retrieving formatrenderings from the clipboard:v clipboardStartRetrieve:v clipboardRetrieve:formatName:bufferReturn:privateIdReturn:v clipboardEndRetrieve:

For example, the Paste menu item of the Edit menu might look like:menuEditPaste

"Private - Process the Edit menu Paste item."| display window bufferHolder result |display := self shell display.window := self shell window.display clipboardStartRetrieve: window.

result := (displayclipboardRetrieve: windowformatName: 'Ole Object'bufferReturn: (bufferHolder := ReturnParameter new)

privateIdReturn: ReturnParameter null) == ClipboardSuccess.

display clipboardEndRetrieve: window.result ifFalse: [|self].|self paste: bufferHolder value

Here, the value returned from the bufferHolder (a ReturnParameter) is an instance ofOleObjectDescriptor that contains all the data required by an OleClient to recreatethe OLE object that was copied to the clipboard. The paste: method is similar tomenuEditInsertObject: and menuEditPasteSpecial: described above, except that insteadof invoking the dialogs to create and connect the OLE object, the OleClient is askedto do it from the OleObjectDescriptor:paste: oleObjectDescriptor

"Private - Paste the OLE object into the receiver."| client |oleObjectDescriptor == nil

ifTrue: [|self]. "Nothing to paste"

client := compositecreateOleClient: counter printStringargBlock: [:w |

wx: 50;y: 50;width: 200;height: 200].

clientmappedWhenManaged: false;manageChild;pasteFromOleObjectDescriptor: oleObjectDescriptor;mappedWhenManaged: true

Here, the OleClient does all the work of creating and connecting the OLE objectthrough its instance method pasteFromOleObjectDescriptor:.

Note: The OLE object format and its rendering are also used for drag and dropoperations on OleClient widgets. The OleClient method oleObjectDescriptor isused to obtain the source OLE object format rendering for a drag operation,and the OleClient method pasteFromOleObjectDescriptor: is used to create andconnect an OLE object described in a OLE object rendering obtained from adrop operation.

The isConnected instance method is used to determine whether an OleClientis connected to its embedded or linked OLE object.

450 IBM Smalltalk: Programmer’s Reference

Page 465: IBM Smalltalk: Programmer's Reference

Creating an object verb menuVerbs are actions that a container can ask an OLE object to perform. The names ofthe verbs that an OLE object can execute are registered with the object in thesystem registry. All OLE objects have one verb designated as the primary verb,which in most cases is Edit. Other common verbs are Open, Show, Hide, and Play.

When an OLE object is activated in its container by double-clicking on theOleClient widget, it is the primary verb that is invoked on the OLE object.Therefore, if the Edit verb is the primary verb, on activation, the server opens forediting on the OLE object. Verbs can also be invoked programmatically through thedoVerb: method of OleClient. The parameter to this method is the name of the verbto execute. For example, a contained OLE object can be activated for editing usinganOleClient doVerb: 'Edit'.

The doVerb: method can also take as a parameter a constant representing the mostcommon verbs that most OLE objects support. For example, the edit verb couldalso be invoked using anOleClient doVerb: XmVERBPRIMARY.

The standard parameter values for the OLE doVerb: include the following:XmVERBPRIMARY

Open the OLE object for editingXmVERBSHOW

Show the OLE objectXmVERBOPEN

Open the OLE object for editing in a separate windowXmVERBHIDE

Hide the OLE objectXmVERBUIACTIVATE

Activate the UI for the OLE objectXmVERBINPLACEACTIVATE

Open the OLE object for editing in placeXmVERBDISCARDUNDOSTATE

Close the OLE object and discard the undo stateXmVERBPROPERTIES

Request the OLE object properties dialog

The OLE user interface guidelines suggest that a container provide access to anobject’s verbs from a cascade menu off its Edit menu. The container mustdynamically change the contents of the cascade menu depending on whichOleClient widget has the current focus. The guidelines also suggest that the label ofthe cascade menu change to reflect the name of the object that the verbs apply to.

To help build a dynamic verb menu, the OleClient class provides these instancemethods:

Chapter 15. Object Linking and Embedding (OLE) 451

Page 466: IBM Smalltalk: Programmer's Reference

clientUserNameAnswers a String representing the type of contained OLE object

verbs Answers a collection of strings that are the names of the verbs supportedby the contained OLE object

These methods provide sufficient information to build the dynamic verb menus ofa container application. As an example, suppose the Edit menu of an application iscreated as a simple pull-down menu using the following code:createEditMenu: menuBar

"Private - Create and answer the Edit menu for the receiver."| types |types := OrderedCollection new.types

add: XmPUSHBUTTON;add: XmPUSHBUTTON;add: XmPUSHBUTTON;add: XmPUSHBUTTON;add: XmPUSHBUTTON;add: XmSEPARATOR;add: XmPUSHBUTTON;add: XmPUSHBUTTON;add: XmCASCADEBUTTON.

editMenu := menuBarcreateSimplePulldownMenu: 'edit'argBlock: [ :w |

wbuttons: #('Cut' 'Copy' 'Paste' 'Paste Special...'

'Delete Object' '' 'Insert Object...' 'Links...' 'Object');buttonType: types;buttonMnemonics: #();postFromButton: 1].

editMenuaddCallback: XmNsimpleCallbackreceiver: [:w :clientData :callData |

| selectors |selectors := #(menuEditCut menuEditCopy menuEditPastemenuEditPasteSpecial menuEditDeleteObject menuEditInsertObjectmenuEditLinks menuEditObject).self perform: (selectors at: clientData + 1)]

selector: #value:value:value:clientData: nil.

editMenuaddCallback: XmNmapCallbackreceiver: [:w :clientData :callData |

| widget buttons |buttons := editMenu children.widget := self shell focusWidget.(buttons at: 1) sensitive: widget isOleClient. "Cut"...(buttons at: 9)

sensitive: self enableVerbs. "Object"]selector: #value:value:value:clientData: nil.

|editMenu

In this example, the last item on the menu is a cascade button that is used toattach the verb menu to. The verb menu must be disabled if no OleClient widgethas focus. Hence, the XmNmapCallback callback calls the enableVerbs method tobuild the verb menu if appropriate. The enableVerbs method first checks for theexistence of an OleClient with focus and, if it finds one, proceeds to build the verbmenu:

452 IBM Smalltalk: Programmer’s Reference

Page 467: IBM Smalltalk: Programmer's Reference

enableVerbs"Private - Answer true if the selected embedded object's verbsare to be enabled."| widget |widget := self shell focusWidget."Widget with focus is the selected item."(widget isOleClient not or: [widget isStaticEmbedding])

ifTrue: [(editMenu children at: 9) labelString: 'Object'.|false].

"An embedded or linked OLE object is selected, so add verb menu to edit menu."self addObjectMenu: widget clientUserName

verbs: widget verbs.|true

The cascading verb menu is built in the addObject:verbs: method as follows:addObjectMenu: objectType verbs: verbNames

"Private - Add an object menu for object with type name StringobjectType containing the verb names in the verbNames Array."| types labels verbCount objectMenu |labels := OrderedCollection new: (verbCount := verbNames size) + 2.

types := OrderedCollection new: labels size.1 to: verbCount do: [ :i |

labels add: (verbNames at: i).types add: XmPUSHBUTTON].

labels add: 'separator'; add: 'Convert'.types add: XmSEPARATOR; add: XmPUSHBUTTON.(editMenu children at: 9) labelString: (objectType, ' Object').

objectMenu := editMenucreateSimplePulldownMenu: 'object'argBlock: [ :w |

wbuttons: labels asArray;buttonType: types asArray;postFromButton: 8].

objectMenuaddCallback: XmNsimpleCallbackreceiver: [:w :clientData :callData |

| widget |widget := self shell focusWidget.(widget isOleClient and: [verbCount > 0])

ifTrue: [clientData >= verbCountifTrue: [self menuEditConvert]

ifFalse:[widget doVerb: (verbNames at: clientData + 1)]]]

selector: #value:value:value:clientData: nil.

Notice in this example that one additional menu item, Convert, is attached to thebottom of the verb menu. This item provides access to the standard OLE Convertdialog, which allows you to change the display aspect of the OLE object from its

Chapter 15. Object Linking and Embedding (OLE) 453

Page 468: IBM Smalltalk: Programmer's Reference

content display to its icon display and conversely.

This dialog is easily invoked on an OleClient widget through itspromptConvertObject method. For example:menuEditConvert

"Private - Process the Edit menu Convert item."| widget |(widget := self shell focusWidget) isOleClient

ifFalse: [|self].widget promptConvertObject == true

ifTrue: [changed := true]

The promptConvertObject method answers true if the display aspect of the OLEobject changed. If it did, the OleClient widget’s display was already refreshed toreflect the new aspect.

Invoking the Links dialogIf an OLE container contains linked OLE objects, it should let you edit and modifythose links. OLE provides a standard Links dialog, which lists all the linked OLEobjects in the container. You can:v Update a link.v Change a link to a different file.v Open a linked source file for editing.v Break a link.

The standard Links dialog is invoked on an OleMainWindow becauseOleMainWindow knows about the linked OLE clients in its widget tree. You use the

454 IBM Smalltalk: Programmer’s Reference

Page 469: IBM Smalltalk: Programmer's Reference

OleMainWindow instance method promptEditLinks to open the Links dialog. Forexample, an action method for a Links menu item might simply be the following:menuEditLinks

"Private - Process the Edit menu Links item."self mainWindow promptEditLinks

Upon return from promptEditLinks, all requested link edits have been completed,and any link changes that effect the OLE object’s display have also been made.

Note: If the Links dialog is used to break a link to an OLE object, the linked objectautomatically reverts to a static embedding. The display of the OLE object isstill visible on its OleClient widget, but it can no longer be activated.

Saving and retrieving an OLE clientAn OLE container may be designed to produce documents that consist of nativedata and a variety of OLE objects from third-party applications such as MicrosoftWord or Excel. This type of container often persists into a file (perhaps along withits own native data) the data content (or a link to it) of its contained OLE objects.At some later time, it reconstructs the document, both native data and containedOLE object data, from the same file.

A file that supports the storage of both native data and OLE object data issometimes called a compound file. The OleFile class supports this kind ofcompound-document storage requirement.

An OleFile works seamlessly with an OleClient in the storage and retrieval of itscontained OLE object’s data. An OleFile can store multiple OLE clients and, hence,it requires that each one be given a unique name when put into the file. OLE filesalso allow arbitrary application data to be stored with the OleClient in the file.These attributes of application data are stored in the OleFile under the same nameas the OLE object they are associated with. Finally, an OleFile permits one global,unnamed set of application data attributes to be stored in the file.

Saving an OLE clientGiven a fully qualified path name string, an OleFile can create and open acompound file for storage through its create: class method. Once opened, an OLEobject can be stored using the saveWidget:named: instance method. For example, allthe embedded or linked OLE objects in an application can be saved using:saveWidgetsTo: filepath

"Save the applications data to an OleFile specified by the filepath String."| file widgets |(file := OleFile create: filePath) == nil

ifTrue: [|false].widgets := self mainWindow oleWidgets.widgets do: [ :widget |

file saveWidget: widget named: widget name].file close

Once an OleFile is created, all OleClient widgets in the application are obtainedfrom the OleMainWindow through its oleWidgets method. This example assumes thatwhen each OleClient widget is created, it is given a unique name which it uses asthe unique OleFile storage name.

Note: An OleFile must be closed with its close method before any OLE object datais committed to the file.

Chapter 15. Object Linking and Embedding (OLE) 455

Page 470: IBM Smalltalk: Programmer's Reference

Retrieving an OLE clientAn OleFile can be opened, through its open: class method, on an existing file aslong as the file was originally created as an OleFile. If it was not, the open: fails. AnOLE object’s data is retrieved from an OleFile into an existing OleClient widget. ThestorageNames instance method of OleFile can be used to obtain all the storage namesfrom the file so that the OleClient widgets can be created with the same names theywere saved under. Given the storage names, each OleClient can be restored fromthe OleFile using its restoreWidget:named: instance method. For example, the OLEobjects saved in the above example can be restored using:restoreWidgetsFrom: filePath

"Restore the widgets from the file named by the filePath String."| file names client |(file := OleFile open: filePath) == nil ifTrue: [|false].names := file storageNames.names do: [:name |

client := compositecreateOleClient: nameargBlock: nil.

clientmappedWhenManaged: false;manageChild.

file restoreWidget: client named: name.client mappedWhenManaged: true].file close.

In this example, the OleClient widgets are created with default size and position.The following section describes saving additional attributes of the widgets in thefile.

Saving and restoring data attributes: An arbitrary, named data set can also bestored in an OleFile. This permits, for example, data attributes of an OleClient to bestored in the file under the same name as the OleClient. The data set to be savedmust be contained in a ByteArray, which can be filled in a variety of ways,including by using the Swapper tool. The OleFile instance methodsaveAttributes:named: saves a ByteArray of data to the file. For example, thesaveWidgetTo: method above can be enhanced to save each widget’s position andsize:saveWidgetsTo: filepath

"Save the applications data to an OleFile specified by the filepath String."| file widgets data |fileName := filepath.(file := OleFile create: fileName) == nil

ifTrue: [|false].widgets := self mainWindow oleWidgets.data := ByteArray new: 16.widgets do: [ :widget |

dataint32At: 0 put: widget x;int32At: 4 put: widget y;int32At: 8 put: widget width;int32At: 12 put: widget height;

filesaveWidget: widget named: widget name;saveAttributes: data named: widget name].

file close

Similarly, named data attributes can be restored from an OleFile through the use ofthe restoreAttributesNamed: method, which answers a new ByteArray containing thesaved data. Hence, the example method restoreWidgetsFrom: can be rewritten as:

456 IBM Smalltalk: Programmer’s Reference

Page 471: IBM Smalltalk: Programmer's Reference

restoreWidgetsFrom: filePath"Restore the widgets from the file named by the filePath String."| file names client data |(file := OleFile open: filePath) == nil ifTrue: [|false].names := file storageNames.names do: [:name |

data := file restoreAttributesNamed: name.

client := compositecreateOleClient: nameargBlock: [:w |

wx: data int32At: 0;

y: data int32At: 4;width: data int32At: 8;height: data int32At: 12].

clientmappedWhenManaged: false;manageChild.

file restoreWidget: client named: name.client mappedWhenManaged: true].file close.

Additional methods of OleFile can be used to save and restore unnamed data setsto a file. The methods, which also work with byte arrays, are saveAttributes: andrestoreAttributes.

Note: For numeric data, it is often simpler to use ByteArray accessors (such as,int32At: and int32At:put:) rather than the Swapper tool to fill byte arrays foruse with an OleFile.

Using OLE automationOLE automation allows an application to expose its function for programmatic useby another application. An application that makes its function available is called anOLE automation server. An application that uses that function is called an OLEautomation controller (or client).

OLE automation provides the mechanisms for servers to group their function intoobjects, called automation objects, which can then be exposed and used in astandard way. Automation objects provide access to their function throughmethods and access to their attributes or variables through properties (equivalentto accessor methods for instance variables in Smalltalk). An OLE automation serverexposes its objects for use by registering them in the system registry. If anautomation server provides multiple objects, each one must be registeredseparately.

Objects exposed by an OLE automation server can be accessed in Smalltalkthrough the OleAutomationObject class. Each automation object provided by aserver is accessed through an instance of OleAutomationObject. Methods of anOleAutomationObject let you invoke methods and get or set properties of theautomation object.

The steps for creating an OLE automation controller are as follows:1. Create an OleAutomationObject.2. Invoke methods on the OleAutomationObject.3. Get and set properties of the OleAutomationObject.4. Release the OleAutomationObject when it is no longer needed.

Chapter 15. Object Linking and Embedding (OLE) 457

Page 472: IBM Smalltalk: Programmer's Reference

Creating OLE Automation ObjectsThese are the ways to obtain OleAutomationObjects:v Create them directly using their ProgId, or client name, from the system registry.v Request them from another OleAutomationObject.v Request them from an existing OleClient that contains an embedded or linked

OLE object.v Request them from an existing OleControl (see “Using OLE custom controls

(OCXs)” on page 460).

You use the class method createObject: to instantiate an OleAutomationObject using aProgId from the system registry. For example, Word Basic, the only OLEautomation object exposed by Microsoft Word, has a ProgId of ‘Word.Basic’, so aninstance of that object is created using:| wordbasic |

wordbasic := OleAutomationObject createObject: 'Word.basic'

Unlike Microsoft Word, many OLE automation servers provide a number ofautomation objects organized as networks of interrelated objects. As such, one OLEautomation object may reference another. The references to other automationobjects are maintained as properties of the object. Values of an OLE automationobject’s properties are obtained by their name or DISPID. Support for propertyaccess by an OleAutomationObject is through its propertyAt: instance method, and,hence, additional OLE automation objects are obtained through this method. Forexample, the top-level application object of Microsoft Excel is accessed using:| excel application |

excel := OleAutomationObject createObject: 'Excel.Sheet'.application := excel propertyAt: 'Application'.

Many, but not all, OLE document servers also provide OLE automation objects. AnOleClient, through its automationObject instance method, may answer theautomation object of its embedded or linked OLE object. For example, if aMicrosoft Word object is embedded in a container, its Word Basic automation objectis obtained using:| word wordDispatch wordApplication wordBasic |

word := mainWindowcreateOleClient: 'word'argBlock: [:w |

wclientType: XmEMBEDDED;clientName: 'Word.Document'].

word isConnected ifFalse: [word destroyWidget. |nil].

word manageChild.wordDispatch := word automationObject.wordApplication := wordDispatch propertyAt: 'Application'.wordBasic := wordApplication propertyAt: 'WordBasic'.

Invoking methods of OLE automation objectsMethods of OLE automation objects are invoked by their unique name or DISPID.An OleAutomationObject has instance methods that are used to call a method of anOLE automation object. The methods are invoke:withArguments: andinvoke:withArguments:returnType:.

Both methods take as a first parameter the name (or DISPID) of the method toinvoke, and as a second parameter an array of parameters to be passed to themethod.

458 IBM Smalltalk: Programmer’s Reference

Page 473: IBM Smalltalk: Programmer's Reference

The invoke:withArguments: returns the result of the OLE method sent, or nil if therewas an error.

The value returned from invoke:withArguments:returnType: depends on the value ofthe returnType: parameter, as described below. A false value returnType: is requiredbecause some automation servers, such as Microsoft Word, have methods that failunless their return values are not requested. The values of returnType include thefollowing:true Answers the return value of the OLE methodfalse Ignores the return value of the OLE method

Note: If an error is indicated with a nil return from one of the OLE automationobjects invoke methods, a String describing the error may be obtained bysending the lastErrorString message to the OleAutomationObject.

Smalltalk objects returned from an OleAutomationObject invoke method areconverted from their OLE types to equivalent Smalltalk types. Likewise, Smalltalkobjects passed as parameters to an invoke method are converted to their OLEequivalent types based on their Smalltalk class. These conversions are supportedonly for the simple Smalltalk objects listed below. The Smalltalk classes supportedfor automatic conversion to and from OLE types include the following:v Integerv Floatv Stringv Booleanv OleAutomationObject

Note: If a parameter to one of the invoke methods cannot be represented in one ofthe supported types named above, an initialized instance of OSVariantargmay be used. Likewise, a return value of an invoke method is either one ofthe supported types or an instance of OSVariantarg.

As an example of using the invoke methods on an OleAutomationObject, considerthe following code fragment that opens Microsoft Word, inserts some text, movesthe text insertion point, and selects the text:| wordBasic text |

wordBasic := OleAutomationObject createObject: 'Word.basic'.text := ' A small amount text for Word.'.wordBasic

invoke: 'FileNew' withArguments: #();invoke: 'CharRight' withArguments: #(1);invoke: 'Insert' withArguments: (Array with: text) returnType: false;invoke: 'ExtendSelection' withArguments: #() returnType: false;invoke: 'CharLeft' withArguments: (Array with: text size).

Getting and setting propertiesProperties of OLE automation objects are also accessed by their unique name orDISPID. The OleAutomationObject class has these property-accessor instancemethods:propertyAt:

Returns the value of a named propertypropertyAt:put:

Sets the value of a named property

These methods function like the invoke methods with respect to parameters andreturn values.

Chapter 15. Object Linking and Embedding (OLE) 459

Page 474: IBM Smalltalk: Programmer's Reference

As an example of using the property methods on an OleAutomationObject, considerthe following code fragment that opens Microsoft Excel, makes it visible, changesthe default file path, and opens a file:| excel application workBooks |

excel := OleAutomationObject createObject: 'Excel.Sheet'."Get the root Excel Application object."application := excel propertyAt: 'Application'."Make Excel visible."application propertyAt: 'Visible' put: true."Set the default file path."application propertyAt: 'DefaultFilePath' put: 'c:\budget\'."Get the Excel Workbooks object."workBooks := application propertyAt: 'Workbooks'."Open an existing Excel file (.XLS)."workBooks invoke: 'Open' withArguments: #('budget96.xls').

...application invoke: 'Quit' withArguments: #()

Releasing an OLE automation objectEach instance of an OleAutomationObject has some operating system resourcesassociated with it that must be freed when they are no longer required. Hence,when an OLE automation controller is finished using these objects, it must releasethose resources. The OleAutomationObject instance method releaseObject performsthis function. For example, in the previous example the three Microsoft Excel OLEautomation objects should be released immediately after the Quit method isinvoked:...application invoke: 'Quit' withArguments: #()

workBook releaseObject.application releaseObject.excel releaseObject.

Note: After the releaseObject message is sent, the OleAutomationObject is no longerconnected to the OLE automation server and, as such, it cannot be used. Toconnect back to the same server, a new instance of OleAutomationObject mustbe created. After a releaseObject message is sent, it is good practice to assignnil values to all Smalltalk variables that were referencing theOleAutomationObject.

Using OLE custom controls (OCXs)An OLE custom control (OCX) is an embedded OLE object that is activated inplace. Unlike OLE objects, however, OCXs are manipulated programmatically bytheir containers through standard OLE automation protocols. OCXs are most oftenimplemented as DLLs, which are directly loaded into the address space of theircontainer.

An OCX:v Has an OLE automation element with properties that are retrieved and

modified, and methods that are invokedv Obtains information from its container to initialize its own state; that is, it

gathers the ambient properties from its containerv Notifies its container, through events, when a user action causes its state to

change or a function to be performed.

Essentially, an OCX is an in-place-activated OLE object. On the other hand, anOCX container is a standard OLE container that supports visual editing.

460 IBM Smalltalk: Programmer’s Reference

Page 475: IBM Smalltalk: Programmer's Reference

An OCX container:v Provides in its user interface the site for the OCX’s user interface.

Note: Some OCXs may not have a user interface component; it is not arequirement.

v Sets properties and makes action requests, through OLE automation, of an OCXv Provides an ambient-properties handler (callback) that responds to

ambient-property requests from an OCXv Provides a set of event handlers (callbacks) that respond to event notifications

from an OCX.

The steps to create an OLE container that contains OCXs are:1. As part of the initialization for the user-interface widget hierarchy, create an

OleMainWindow.2. Implement methods to create OleControl widgets and the OCX objects that are

to appear within their borders.3. Implement the ambient-property handler.4. Use OLE automation aspects of an OCX to set or get properties and invoke

methods on the OCX.5. Implement the event handler callbacks.

Creating the OLE main windowSince applications using OCXs are OLE containers, they must also use theOleMainWindow class rather than CwMainWindow. Even though OCXs do not usemenus or do not require additional window space for status bars and so on, theystill require OleMainWindow to support in-place activation of the contained OCXÆsuser interface. As in “Creating an OLE main window” on page 443, anOleMainWindow is simply created using:createMainWindow: shell

"Private - Create and answer the main window for the receiver."|(shell

createOleMainWindow: 'main'argBlock: [:w | w hostName: 'Container']) manageChild

Since OCXs do not use menus, no menu groups need be registered with theOleMainWindow (unless of course, there are OleClient widgets used for embeddedor linked OLE objects in the same application).

Creating OCXsAn OleControl widget provides an OLE container the place to put OCXs. OLEcontrols are primitive widgets and, as such, they conform to all standardwidget-geometry management. An OleControl widget contains the connections toan OCX and transparently manages all low-level OLE interaction with that object.In addition, an OleControl widget provides an OLE automation interface for itscontained OCX to be used to set and get OCX properties and to invoke OCXmethods.

OleControl widgets are created and managed like other primitive widgets. UnlikeOleClient widgets, however, the only way to create and connect an OCX to anOleControl widget is through its registered name. This is the same as the creationof OLE clients using the clientName resource, which is based on the OCX’sregistered programmatic identifier, or ProgId.

Chapter 15. Object Linking and Embedding (OLE) 461

Page 476: IBM Smalltalk: Programmer's Reference

Since OLE controls are also created as child widgets of any non-primitive widget(that is, any CwComposite), there is an additional widget-creation conveniencemethod implemented in CwWidget, called createOleControl:argBlock:. The creationblock passed to this method must not only specify the clientName resource (throughthe clientName: method) but also the ambient-property handler, or callback, to beused by the contained OCX. This ambient-property handler is specified throughthe OleControl instance methods ambientPropertyReceiver: andambientPropertySelector:.

The ambient-property handler must be specified when the OleControl widget iscreated, so that the OCX has access to the container’s properties during itsinitialization. As an example, consider a container that uses a track bar OCX that iscreated using:createTrackBar: workWindow

"Private - Create a track bar control."trackBar := workWindow

createOleControl: 'the control'argBlock: [:w |

wclientName: 'TRACKBAR.TrackbarCtrl.1';ambientPropertyReceiver: self;ambientPropertySelector: #dispidAmbientPropertyAt:].

trackBar manageChild.

Implementing an ambient-property handlerAmbient properties are used by a container to give an OCX information about itssurroundings, such as the background color of a form, the current font, or thelocale ID of the container’s user interface.

Each ambient property is identified by a unique DISPID, which an OCX uses tospecify which ambient property it wants from its container. To support theintegration of OCXs with containers, OLE defines a set of standardambient-property DISPIDs. This set is encoded into the Smalltalk pool dictionaryPlatformConstants as follows:

Ambient Property DISPID Class Specifies

DispidAmbientBackcolor Integer The color of the interior of an OCX (inRGB values)

DispidAmbientDisplayname String the name the OCX should display foritself in error messages

DispidAmbientDisplayasdefault Boolean Whether a button OCX should drawitself with a thicker frame (forbutton-like OCXs only)

DispidAmbientForecolor Integer The color of the display of text andgraphics in an OCX (in RGB values)

DispidAmbientLocaleid Integer The ID of the UI locale

DispidAmbientMessagereflect Boolean Whether the container wants to receiveMS Windows messages

DispidAmbientSupportsmnemonics Boolean Whether the container processesmnemonics

DispidAmbientShowgrabhandles Boolean Whether the OCX should show grabhandles when in-place activated

DispidAmbientShowhatching Boolean Whether an OCX should show a hatchborder when in-place activated

462 IBM Smalltalk: Programmer’s Reference

Page 477: IBM Smalltalk: Programmer's Reference

DispidAmbientScaleunits String The name of the units by the container

DispidAmbientTextalign Integer How text should be aligned in an OCX:0 General (numbers to the right,

text to the left)1 Left2 Center3 Right4 Fully justified

DispidAmbientUsermode Boolean Whether the container is in designmode (false) or run mode (true)

DispidAmbientUidead Boolean Whether the container is in a mode inwhich OCXs should ignore user input

Ambient-property handlers are implemented as methods that take a singleparameter, which is the DISPID of the ambient property being requested by theOCX. OCXs may not request all possible ambient properties but only those theyare interested in. Likewise, a container may not necessarily be able to respond toall ambient property requests. The ambient property handler answers the value ofthe requested property if it can; otherwise, it answers a nil value to inform theOCX that the property is not available. For example, the ambient-property-handlermethod dispidAmbientPropertyAt: in the above example might be implemented asfollows:dispidAmbientPropertyAt: dispid

"Private - Handle ambient properties."DispidAmbientShowgrabhandles == dispid ifTrue: [|false].DispidAmbientShowhatching == dispid ifTrue: [|false].DispidAmbientLocaleid == dispid ifTrue: [|LocaleUserDefault].DispidAmbientUidead == dispid ifTrue: [|false].DispidAmbientUsermode == dispid ifTrue: [|false].|nil

Here, the constant LocaleUserDefault comes from the pool dictionaryPlatformConstants.

Note: A class that implements OLE-container behavior should declarePlatformConstants as pool dictionaries.

Using automation aspects of an OCXOCXs are also OLE automation objects; that is, they have properties that can be setand retrieved, and they have functions that can be invoked on behalf of theircontainers.

To support its OLE automation aspects, the OleControl class has the sameautomation protocols as the OleAutomationObject class, namely:v propertyAt:v propertyAt:put:v invoke:withArguments:v invoke:withArguments:returnType:

Since complex OCXs are often composed of many distinct objects, some of thesemethods may themselves return OLE automation objects.

The properties that an OCX defines are characteristic of the OCX. Thesecharacteristics can include the font used, the background color, or the caption.Since so many of these characteristics are common to so many OCXs, OLE has

Chapter 15. Object Linking and Embedding (OLE) 463

Page 478: IBM Smalltalk: Programmer's Reference

defined a set of standard property DISPIDs for them. A set of constants for theseDISPIDs is also defined in the PlatformConstants pool dictionary. (See the StandardProperty DISIDs in the table below.)

As an example of setting properties, the following code fragment initializes thetrack bar OCX created in the previous example:trackBar

propertyAt: 'SliderStyle' put: 0 "Enable selection range";propertyAt: 'SelectionStart' put: 1;propertyAt: DispidEnabled put: true;propertyAt: 'SelectionEnd' put: 100;invoke: 'SetTicFrequency' withArguments: (Array with: 1 with: 5)

Standard Property DISPID Class Specifies

DispidBackcolor Integer The color of the interior of the OCX (in RGBvalues)

DispidBackstyle Integer Whether an OCX is transparent (0) or opaque(1)

DispidForecolor Integer The color of the display of text and graphics inan OCX (in RGB values)

DispidEnabled Boolean Whether the OCX can receive the focus

DispidText String The string to be displayed in a text box, listbox, or combo box

DispidCaption String The string to be displayed in, or next to, theOCX

DispidRefresh None Force repainting the OCX synchronously if theOCX has a window, otherwise asynchronously

DispidDoclick None Simulate the button being clicked by the user(for button-like OCXs)

DispidAboutbox None Pop up a modal About dialog for the OCX

Note: The font property DISPID DispidFont is not supported. Instead, use thefontList: instance method of OleControl to set a font into an OCX.

Implementing event handlersEvery OCX has a set of event notifications that it can send to its container. OCXevents encompass both event and callback notions of Common Widgets. That is,OCX events can be fine-grained (such as mouse-clicks or key-presses), or they canbe notifications of some higher-level action (such as a Cancel button beingselected). The events that a particular OCX support are normally described in theOCX’s type library or in the documentation that is shipped with it. Each event thatis supported by an OCX is identified by a unique name and a unique DISPID.

An OCX container must register a method for each OCX event it will handle. Thename of the event, the selector of the event-handler method, and the object thatreceives the notification are registered with an OleControl through itsaddOleEventHandler:receiver:selector: instance method. For example, the track barOCX sends an event called ‘Change’ whenever the user moves its slider. Thehandler for this event is registered using:trackBar

addOleEventHandler: 'Change'receiver: self selector: #updateValue.

464 IBM Smalltalk: Programmer’s Reference

Page 479: IBM Smalltalk: Programmer's Reference

Here, the ‘Change’ event passes no parameters to the event handler, so itsimplementation must request the current ‘Value’ property from the OCX. Forexample:updateValue

"Update the track bar's label with the current value of the track bar."self updateTrackLabel: (trackBar propertyAt: 'Value')

Many OCX events pass one or more parameters to their container along with theevent notification. Therefore, the event-handler method selectors mustaccommodate the required number of parameters. For example, an OCX’smouse-down event passes four parameters to its container’s event handler:v The mouse button that was pressedv The state of the shift keyv The mouse pointer X locationv The mouse pointer Y location.

Hence, a handler for this event is registered for the track bar OCX using:trackBar

addOleEventHandler: 'MouseDown'receiver: self selector: #eventMouseDown:shift:x:y:.

where the implementation of this event handler is:eventMouseDown: button shift: shift x: nX y: nY

"Private - Processes the OLE Track bar MouseDown event."...

An OLE event handler is deregistered from an OleControl through its instancemethod removeOleEventHandler:receiver:selector:.

There is a set of predefined OLE event names and DISPIDs for the base mouse andkeyboard events that are used by most OCXs. These predefined events overlap theCommon Widgets event masks that are inherited by OleControl. As a convenience,OleControl registers handlers for the corresponding OLE predefined events andautomatically reroutes them through the Common Widgets event-handlermechanism. For example, the mouse-down OLE event handler registered in theprevious example can be rewritten to use a Common Widgets event handler:trackBar

addEventHandler: ButtonPressMaskreceiver: selfselector: #value:clientData:callData:clientData: nil.

OleControl registers OLE event handlers for these predefined events:v KeyDownv KeyUpv MouseDownv MouseMovev MouseUp

If a container registers for one of the predefined OLE events usingaddOleEventHandler:receiver:selector:, its handler supersedes the OleControl widget’sregistered predefined event.

PredefinedOLE eventname

DISPID User action Parameters(in order)

Description

Chapter 15. Object Linking and Embedding (OLE) 465

Page 480: IBM Smalltalk: Programmer's Reference

Click DispidClick Presses and releasesa mouse buttonover the OCX. Forsome OCXs, theevent is sent whenthe value of theOCX changes.

None

DblClick DispidDblclick Double-clicks in theOCX

None

KeyDown DispidKeydown Presses a key whenthe OCX has focus

Key CodeShift

The key code forthe key pressed Abit mask detailingthe state of theCtrl, shift, andAlt keys

KeyUp Releases a keywhen the OCX hasfocus

Key CodeShift

See KeyDown

MouseDown DispidMousedown Presses a mousebutton while overan OCX

Button ShiftX Y

A bit maskidentifying whichbutton is down Abit mask detailingthe state of theCtrl, shift, andAlt keys Thecurrent X locationof the mouse Thecurrent Y locationof the mouse

MouseMove DispidMousemove Moves the mouseover an OCX

Button ShiftX Y

See MouseDown

MouseUp DispidMouseup Releases the mousebutton over an OCX

Button ShiftX Y

See MouseDown

Wrapping OCXs with extended widgetsThe Common Widgets Extended Widgets framework can be used to wrapper anOleControl so it can be used in a more familiar way. That is, Smalltalk accesssorsare used to wrap the OleControl property messages (propertyAt: and propertyAt:put:)and invoke message (invoke:withArguments:), and the Common Widgets callbackstyle is used for all the OLE events of interest.

For a reference on building Extended Widgets, see the “Chapter 8. ExtendedWidgets” on page 233. The main approach is to:1. Make a subclass CwExtentedPrimitive.2. Create an instance of OleControl in the Extended Widgets

createPrimaryWidget:parent:argBlock: method and register an ambient-propertyhandler. For example:createPrimaryWidget: theName parent: parent argBlock: argBlock

"Private - Create and answer the basic widget that is the rootof the widget hierarchy for the receiver's widget system."

|self parentcreateOleControl: 'the control'argBlock: [:w | w

466 IBM Smalltalk: Programmer’s Reference

Page 481: IBM Smalltalk: Programmer's Reference

clientName: 'TRACKBAR.TrackbarCtrl.1';ambientPropertyReceiver: self;ambientPropertySelector: #dispidAmbientPropertyAt:].

3. Register OLE event handlers and associate them with Common Widgetscallbacks in the initializeAfterCreate method. For example:initializeAfterCreate

"Private - Perform any widget-specific post-create initialization."super initializeAfterCreate.self primaryWidget

addOleEventHandler: 'Change'receiver: selfselector: #callValueChangedCallback

4. Implement widget-specific methods, such as:clearSelection

"Clears the slider's selection range."|self primaryWidget

invoke: 'ClearSelection'withArguments: #()

5. Implement accessors for resources, such as:lineSize: resourceValue

"Set the value of the XmNlineSize resource.Resource type: IntegerDefault setting: 10Resource access: CSGDescription: Specifies the line size. This is the amount

that the slider moves when receiving a key press."self primaryWidget propertyAt: 'LineSize' put: resourceValue

lineSize"Answer the value of the XmNlineSize resource.Resource type: IntegerDefault setting: 10Resource access: CSGDescription: Specifies the line size. This is the amount

that the slider moves when receiving a key press."self primaryWidget propertyAt: 'LineSize'

Using licensed OCXsMany commercially available OCXs limit developer usage through licensing. Withlicensing, an OCX fails creation unless it is provided with the correct license key.The vendor of the OCX provides the license key in a file. The license must beobtained from the license file at development time and then cached for use duringthe runtime creation of the OCX.

To support the use of licensed OCXs, the OleControl class has the class methodgetLicenseKey:, which is used at development time to obtain the license key. Thismethod takes as a parameter the ProgId of the OCX and answers a stringrepresenting the license key. The license key is then cached in the Smalltalk image(for example, in a class variable of an Extended Widgets wrapper of the OCX) andused in the subsequent creation of the OleControl widget.

For example, if the track bar OCX is licensed, its license key is obtained using thefollowing code:getLicenseKey

"Answer a string that can be used to license the receiver,or nil if either the OCX does not require licensingor the OCX does support licensing but cannot be propagated."LicenseKey := OleControl getLicenseKey: 'TRACKBAR.TrackbarCtrl.1'

LicenseKey is a class variable of the Extended Widgets class.

Chapter 15. Object Linking and Embedding (OLE) 467

Page 482: IBM Smalltalk: Programmer's Reference

Then the createPrimaryWidget:parent:argBlock: method is changed to be as follows:createPrimaryWidget: theName parent: parent argBlock: argBlock

"Private - Create and answer the basic widget that is the rootof the widget hierarchy for the receiver's widget system."

|self parentcreateOleControl: 'the control'argBlock: [:w | w

clientName: 'TRACKBAR.TrackbarCtrl.1';licenseKey: LicenseKey;ambientPropertyReceiver: self;ambientPropertySelector: #dispidAmbientPropertyAt:].

Note: The licenseKey: method must be used in the create block of the OleControl.

468 IBM Smalltalk: Programmer’s Reference

Page 483: IBM Smalltalk: Programmer's Reference

Appendix A. Widget resources and callbacks

This appendix provides a detailed listing of the resources and callbacks for eachclass in the Common Widgets subsystem.

Only set resource methods are shown for each class. Get methods use the sameformat without the colon. Create/Set/Get (CSG) access designation and defaultvalue are listed for each resource and call. For more on resource designation, see“Resources” on page 141.

Call list set methods are also shown, even though the callbacks are usually addedusing addCallback:receiver:selector:clientData:, and are not using a callback list setmethod. These methods end in “Callback:”.

Resource methods in this font indicate an overridden default value.

Table 60. CwArrowButton resource and callback methods

activateCallback: C OrderedCollection new Specifies a list of callbacks that is called whenthe ArrowButton is activated.

CallData type is CwAnyCallbackData.

armCallback: C OrderedCollection new Specifies a list of callbacks that is called whenthe receiver is armed.

CallData type is CwAnyCallbackData.

arrowDirection: CSG XmARROWUP Sets the arrow direction.

disarmCallback: C OrderedCollection new Specifies a list of callbacks that is called whenthe receiver is disarmed.

CallData type is CwAnyCallbackData.

CwArrowButton also inherits resource and callback methods from CwPrimitive, CwBasicWidget and CwWidget. Consultthe resource tables of these classes for more information.

Table 61. CwBasicWidget resource and callback methods

CwBasicWidget inherits resource and callback methods from classCwWidget. Consult the resource tables of this classfor more information.

Table 62. CwBulletinBoard resource and callback methods

autoUnmanage: CG true Controls whether or not BulletinBoard isautomatically unmanaged after a button isactivated.

buttonFontList: CSG dynamic Specifies the font list used for BulletinBoard’sbutton children (PushButtons, ToggleButtons).

cancelButton: SG nil Specifies the widget that is the Cancel button.

defaultButton: SG nil Specifies the widget that is the defaultbutton.

defaultPosition: CSG nil Controls whether or not BulletinBoard isautomatically positioned by its parent.

dialogStyle: CSG dynamic Indicates the dialog style associated withBulletinBoard.

© Copyright IBM Corp. 1994, 2000 469

Page 484: IBM Smalltalk: Programmer's Reference

Table 62. CwBulletinBoard resource and callback methods (continued)

dialogTitle: CSG nil Specifies the dialog title.

labelFontList: CSG dynamic Specifies the font list used for BulletinBoard’sLabel children (Labels).

mapCallback: C OrderedCollection new Specifies the list of callbacks that is calledonly when the parent of the BulletinBoard isa DialogShell. In this case, this callback list isinvoked when the BulletinBoard widget ismanaged.

CallData type is CwAnyCallbackData.

marginHeight: CSG 10 Specifies the minimum spacing in pixelsbetween the top or bottom edge ofBulletinBoard and any child widget.

marginWidth: CSG 10 Specifies the minimum spacing in pixelsbetween the left or right edge ofBulletinBoard and any child widget.

noResize: CSG false Controls whether or not resize controls areincluded in the window manager framearound the dialog.

resizePolicy: CSG XmRESIZEANY Controls the policy for resizing BulletinBoardwidgets.

textFontList: CSG dynamic Specifies the font list used for BulletinBoard’sText children.

unmapCallback: CSG OrderedCollection new Specifies the list of callbacks that is calledonly when the parent of the BulletinBoard isa DialogShell. In this case, this callback list isinvoked when the BulletinBoard widget isunmapped.

CallData type is CwAnyCallbackData.

CwBulletinBoard also inherits resource and callback methods from CwComposite, CwBasicWidget and CwWidget.Consult the resource tables of these classes for more information.

Table 63. CwCascadeButton resource and callback methods

cascadingCallback: C OrderedCollection new Specifies the list of callbacks that is calledjust prior to the mapping of the submenuassociated with CascadeButton.

CallData type is CwAnyCallbackData.

marginBottom: CSG dynamic Overrides default value from CwLabel.

marginLeft: CSG dynamic Overrides default value from CwLabel.

marginRight: CSG dynamic Overrides default value from CwLabel.

marginTop: CSG dynamic Overrides default value from CwLabel.

subMenuD: CSG nil Specifies the widget ID for the PulldownMenuPane to be associated with thisCascadeButton. The cascade button and itsassociated pulldown menu must have thesame (or common) parent.

traversalOn: CSG true Overrides default value from CwLabel.

CwCascadeButton also inherits resource and callback methods from CwLabel, CwPrimitive, CwBasicWidget, andCwWidget. Consult the resource tables of these classes for more information.

470 IBM Smalltalk: Programmer’s Reference

Page 485: IBM Smalltalk: Programmer's Reference

Table 64. CwComboBox resource and callback methods

activateCallback: C OrderedCollection new Specifies the list of callbacks that is calledwhen the user press

CallData type is CwAnyCallbackData.

comboBoxType: CG XmDROPDOWN Specifies the style of combo box.

editable: CSG false Indicates whether the user can edit the textstring when set to true.

focusCallback: C OrderedCollection new Specifies the list of callbacks that is calledbefore Text has accepted input focus.

CallData type is CwAnyCallbackData.

fontList: CSG dynamic Specifies the font list to be used forCwComboBox.

itemCount G 0 Specifies the total number of items in the list.

items: CSG nil An array of Strings that are to be displayedas the list items.

losingFocusCallback: C OrderedCollection new Specifies the list of callbacks that is calledbefore Text loses input focus.

CallData type is CwAnyCallbackData.

maxLength: CG dynamic Specifies the maximum length of the textstring that can be entered into text from thekeyboard.

modifyVerifyCallback: C OrderedCollection new Specifies the list of callbacks that is calledbefore text is deleted from or inserted intoText.

CallData type is CwTextVerifyCallbackData.

navigationType: CSG XmTABGROUP Overrides default value from CwPrimitive

popdownCallback: C OrderedCollection new Specifies the list of callbacks that is calledwhen the item list disappears.

CallData type is CwAnyCallbackData

popupCallback: C OrderedCollection new Specifies the list of callbacks that is calledwhen the item list appears.

CallData type is CwAnyCallbackData.

selectedItems CSG nil An array of 0 or 1 Strings that represents theitem currently selected.

singleSelectionCallback: C OrderedCollection new Specifies the list of callbacks that is calledwhen the user confirms a change to thecombo box value.

CallData type is CwComboBoxCallbackData.

valueChangedCallback: C OrderedCollection new Specifies the list of callbacks that is calledafter text is deleted from or inserted intoText.

CallData type is CwAnyCallbackData.

verifyBell: CSG true Specifies whether the bell should soundwhen the verification returns withoutcontinuing the action.

Appendix A. Widget resources and callbacks 471

Page 486: IBM Smalltalk: Programmer's Reference

Table 64. CwComboBox resource and callback methods (continued)

visibleItemCount: CG 5 Specifies the number of items that can fit inthe visible space of the list work area.

CwComboBox also inherits resorce and callback methods from CwPrimitive, CwBasicWidget, and CwWidget. Consultthe resource tables of these classes for more information.

Table 65. CwComposite resource and callback methods

backgroundColor: CSG dynamic Specifies the background drawing color.

exposeCallback: C OrderedCollection new Specifies the list of callbacks that iscalled when widget receives an exposureevent.

CallData type isCwDrawingCallbackData.

focusCallback: C OrderedCollection new Specifies the list of callbacks that iscalled after a widget has accepted inputfocus.

CallData type is CwAnyCallbackData.

foregroundColor: CSG dynamic Specifies the foreground drawing color.

helpCallback: C OrderedCollection new Specifies the list of callbacks that iscalled when the help key sequence ispressed.

CallData type is CwAnyCallbackData.

interceptExposeCallback: C OrderedCollection new Specifies the list of callbacks that iscalled when any area of the receiver orits children is exposed.

CallData type isCwDrawingCallbackData.

losingFocusCallback: C OrderedCollection new Specifies the list of callbacks that iscalled after widget loses input focus.

CallData type isCwDrawingCallbackData.

navigationType: CSG XmTABGROUP Specifies the value of theXmNnavigationType resource.

strictClipping: CG self parent strictClipping Some platforms show a dramatic speedimprovement in the time to drawwindows containing many widgets ifthey are not required to ensure certainclipping constraints.

traversalOn: CSG true Specifies if traversal is activated for thiswidget.

CwComposite also inherits resource and callback methods from CwBasicWidget and CwWidget. Consult the resourcetables of these classes for more information.

Table 66. CwCompositeBox resource and callback methods

cancelLabelString: CSG ‘Cancel’ Specifies the string label for the cancelbutton.

helpLabelString: CSG ‘Help’ Specifies the string label for the help button.

472 IBM Smalltalk: Programmer’s Reference

Page 487: IBM Smalltalk: Programmer's Reference

Table 66. CwCompositeBox resource and callback methods (continued)

minimizeButtons: CSG false Sets the buttons to the width of the widestbutton and height of the tallest button iffalse.

okCallback: C OrderedCollection new Specifies the list of callbacks that is calledwhen the user clicks on the OK Button.

CallData type is CwAnyCallbackData.

okLabelString: CSG ‘OK’ Specifies the string label for the OK button.

CwCompositeBox also inherits resource and callback methods from CwBulletinBoard, CwComposite, CwBasicWidget, andCwWidget. Consult the resource tables of these classes for more information.

Table 67. CwDialogShell resource and callback methods

mwmInputMode: CSG -1 Specifies the input mode flag.

CwDialogShell also inherits resource and callback methods from CwTransientShell, CwWMShell, CwShell,CwBasicWidget, and CwWidget. Consult the resource tables of these classes for more information.

Table 68. CwDrawingArea resource and callback methods

inputCallback: C OrderedCollection new Specifies the list of callbacks that is calledwhen the DrawingArea processes a keyboardor mouse event (key or button, up or down).

CallData type is CwDrawingCallbackData.

marginHeight: CSG 10 Specifies the minimum spacing in pixelsbetween the top or bottom edge ofDrawingArea and any child widget.

marginWidth: CSG 10 Specifies the minimum spacing in pixelsbetween the left or right edge ofDrawingArea and any child widget.

resizePolicy: CSG XmRESIZEANY Specifies the resize policy for the widget.

CwDrawingArea also inherits resource and callback methods from CwComposite, CwBasicWidget, and CwWidget.Consult the resource tables of these classes for more information.

Table 69. CwDrawnButton resource and callback methods

activateCallback: C OrderedCollection new Specifies the list of callbacks that is calledwhen the widget is selected.

CallData type is CwDrawingCallbackData.

armCallback: C OrderedCollection new Specifies the list of callbacks that is calledwhen the receiver is armed.

CallData type is CwAnyCallbackData.

disarmCallback: C OrderedCollection new Specifies the list of callbacks that is calledwhen the receiver is disarmed.

CallData type is CwAnyCallbackData.

exposeCallback: C OrderedCollection new Specifies the list of callbacks that is calledwhen the widget receives an exposure event.

CallData type is CwAnyCallbackData.

labelString: CSG ‘‘ Overrides default value from CwLabel.

Appendix A. Widget resources and callbacks 473

Page 488: IBM Smalltalk: Programmer's Reference

Table 69. CwDrawnButton resource and callback methods (continued)

focusCallback: C OrderedCollection new Specifies the list of callbacks that is calledafter widget has accepted input focus.

CallData type is CwAnyCallbackData.

losingFocusCallback: C OrderedCollection new Specifies the list of callbacks that is calledafter widget loses input focus.

CallData type is CwAnyCallbackData.

pushButtonEnabled: CSG false Enables or disables the three-dimensionalshadow drawing as in PushButton.

traversalOn: CSG true Overrides default value from CwLabel.

CwDrawnButton also inherits resource and callback methods from CwLabel, CwPrimitive, CwBasicWidget, andCwWidget. Consult the resource tables of these classes for more information.

Table 70. CwForm resource and callback methods

fractionBase: CSG 100 Specifies the denominator used in calculatingthe relative position of a child widget usingXmATTACHPOSITION constraints.

horizontalSpacing: CSG 0 Specifies the offset for right and leftattachments.

marginHeight: CSG 0 Overrides default value from CwBulletinBoard

marginWidth: CSG 0 Overrides default value from CwBulletinBoard

rubberPositioning: CSG false Indicates the default attachment for a child ofthe Form.

verticalSpacing: CSG 0 Specifies the offset for top and bottomattachments.

CwForm also inherits resource and callback methods from CwBulletinBoard, CwComposite, CwBasicWidget, andCwWidget. Consult the resource tables of these classes for more information.

Table 71. CwFrame resource and callback methods

fontList: CSG dynamic Specifies the font of the text used in thewidget.

labelString: CSG ‘‘ Specifies a text string that is the title of thereceiver.

marginHeight: CSG 0 Specifies the padding space on the top andbottom sides between the child of Frame andthe Frame’s shadow drawing.

marginWidth: CSG 0 Specifies the padding space on the left andright sides between the child of Frame andthe Frame’s shadow drawing.

shadowType: CSG XmSHADOWDEFAULT Describes the drawing style for Frame.

CwFrame also inherits resource and callback methods from CwComposite, CwBasicWidget, and CwWidget. Consult theresource tables of these classes for more information.

Table 72. CwLabel resource and callback methods

accelerator: C nil Specifies the accelerator on a button widgetin a menu, which activates a visible orinvisible button from the keyboard.

474 IBM Smalltalk: Programmer’s Reference

Page 489: IBM Smalltalk: Programmer's Reference

Table 72. CwLabel resource and callback methods (continued)

acceleratorText: CSG ‘‘ Specifies the text displayed for theaccelerator.

alignment: CSG XmALIGNMENTCENTER Specifies the label alignment for text orpixmap.

fontList: CSG dynamic Specifies the font of the text used in thewidget.

labelIcon: CSG XmUNSPECIFIEDICON Specifies the icon when XmNlabelType isXmICON.

labelInsensitiveIcon: CSG XmUNSPECIFIEDICON Specifies an icon used as the button face ifXmNlabelType is XmICON and the button isinsensitive.

labelInsensitivePixmap: CSG XmUNSPECIFIEDPIXMAP Specifies a pixmap used as the button face ifXmNlabelType is XmPIXMAP and the buttonis insensitive.

labelPixmap: CSG XmUNSPECIFIEDPIXMAP Specifies the pixmap when XmNlabelType isXmPIXMAP.

labelString: CSG dynamic Specifies the label string when theXmNlabelType is XmSTRING. If labelString isnot explicitly set, the widget’s name is usedby default.

labelType: CSG XmSTRING Specifies the label type.

marginBottom: CSG 0 Specifies the amount of spacing that is to beleft, after the bottom margin(XmNmarginHeight) of the widget, butbefore the label is drawn.

marginHeight: CSG 2 Specifies the amount of space between thebottom edge of the top shadow and the label,and the top edge of the bottom shadow andthe label.

marginLeft: CSG 0 Specifies the amount of spacing that is to beleft, after the left margin (XmNmarginWidth)of the widget, but before the label is drawn.

marginRight: CSG 0 Specifies the amount of spacing that is to beleft, after the right margin(XmNmarginWidth) of the widget, but beforethe label is drawn.

marginTop: CSG 0 Specifies the amount of spacing that is to beleft, after the top margin (XmNmarginHeight)of the widget, but before the label is drawn.

marginWidth: CSG 2 Specifies the amount of space between theright edge of the left shadow and the label,and the left edge of the right shadow and thelabel.

mnemonic: CSG nil Provides the user with alternative means forselecting a button.

recomputeSize: CSG true Specifies a Boolean value that indicateswhether or not the widget always attempts tobe big enough to contain the label.

traversalOn: CSG false Overrides default value form CwPrimitive

CwLabel also inherits resource and callback methods from CwPrimitive, CwBasicWidget, and CwWidget. Consult theresource tables of these classes for more information.

Appendix A. Widget resources and callbacks 475

Page 490: IBM Smalltalk: Programmer's Reference

Table 73. CwList resource and callback methods

borderwidth: CSG 1 Overrides a default value fromCwWidget.

browseSelectionCallback: C OrderedCollection new Specifies a list of callbacks that iscalled when an item is selected in thebrowse selection mode.

CallData type is CwListCallbackData.

defaultActionCallback: C OrderedCollection new Specifies a list of callbacks that iscalled when an item is double clicked.

CallData type is CwListCallbackData.

extendedSelectionCallback: C OrderedCollection new Specifies a list of callbacks that iscalled when items are selected usingthe extended selection mode.

CallData type is CwListCallbackData.

fontList: CSG dynamic Specifies the font list associated withthe list items.

itemCount CSG 0 Specifies the total number of items.

items: CSG nil An array of Strings that are to bedisplayed as the list items.

multipleSelectionCallback: C OrderedCollection new Specifies a list of callbacks that iscalled when an item is selected inmultiple selection mode.

CallData type is CwListCallbackData.

navigationType: CSG XmTABGROUP Overrides default value fromCwPrimitive.

scrollHorizontal: CG dynamic Indicates that a horizontal scroll bar isdesired for this list. Ignored onplatforms where the feature is notconfigurable.

selectedItemCount CSG 0 Specifies the number of strings in theselected items list.

selectedItems: CSG nil An array of Strings that represents thelist items that are currently selected,either by the user or the application.

selectionPolicy: CSG XmBROWSEELECT Defines the interpretation of theselection action.

singleSelectionCallback: C OrderedCollection new Specifies a list of callbacks that iscalled when an item is selected insingle selection mode.

CallData type is CwListCallbackData.

topItemPosition: CSG 1 Specifies the position of the item thatis the first visible item in the list.

visibleItemCount: CSG 1 Specifies the number of items that canfit in the visible space of the Listwork area.

CwList also inherits resource and callback methods from CwPrimitive, CwBasicWidget, and CwWidget. Consult theresource tables of these classes for more information.

476 IBM Smalltalk: Programmer’s Reference

Page 491: IBM Smalltalk: Programmer's Reference

Table 74. CwMainWindow resource and callback methods

menuBar: CSG 1 Specifies the widget to be laid out as theMenuBar.

CwMainWindow also inherits resource and callback methods from CwScrolledWindow, CwComposite, CwBasicWidget,and CwWidget. Consult the resource tables of these classes for more information.

Table 75. CwMessageBox resource and callback methods

cancelCallback: C OrderedCollection new Specifies the list of callbacks that iscalled when the user clicks on thecancel button.

CallData type isCwAnyCallbackData.

defaultButtonType: CSG XmDIALOGOKBUTTON Specifies the default PushButton.

dialogType: CSG XmDIALOGMESSAGE Specifies the type of MessageBoxdialog, which determines thedefault message symbol.

messageAlignment: CSG XmALIGNMENTBEGINNING Controls the alignment of themessage Label.

messageString: CSG nil Specifies the string to be used asthe message.

symbolIcon: CSG dynamic Specifies the icon to be used as themessage symbol.

symbolPixmap: CSG dynamic Specifies the pixmap label to beused as the message symbol.

CwMessageBox also inherits resource and callback methods from CwCompositeBox, CwBulletinBoard, CwComposite,CwBasicWidget, and CwWidget. Consult the resource tables of these classes for more information.

Table 76. CwOverrideShell resource and callback methods

CwOverrideShell inherits resource and callback methods from CwShell, CwBasicWidget, and CwWidget . Consult theresource tables of these classes for more information.

Table 77. CwPrimitive resource and callback methods

backgroundColor: CSG dynamic Specifies the background drawing color.

foregroundColor: CSG dynamic Specifies the foreground drawing color.

helpCallback: C OrderCollection new Specifies the list of callbacks that is calledwhen the help key sequence is pressed.

CallData type is CwAnyCallbackData.

highlightThickness: CSG dynamic Specifies the size of the highlightingrectangle.

navigationType: CSG XmNONE Controls whether the Widget is a navigationgroup.

shadowThickness: CSG dynamic Specifies the size of the drawn bordershadow.

traversalOn: CSG true Specifies if traversal is activated for thiswidget.

CwPrimitive also inherits resource and callback methods from CwBasicWidget and CwWidget. Consult the resourcetables of these classes for more information.

Appendix A. Widget resources and callbacks 477

Page 492: IBM Smalltalk: Programmer's Reference

Table 78. CwPushButton resource and callback methods

activateCallback: C OrderedCollection new Specifies the list of callbacks that is calledwhen PushButton is activated.

CallData type is CwAnyCallbackData.

armCallback: C OrderedCollection new Specifies the list of callbacks that is calledwhen the receiver is armed.

CallData type is CwAnyCallbackData.

disarmCallback: C OrderedCollection new Specifies the list of callbacks that is calledwhen the receiver is disarmed.

CallData type is CwAnyCallbackData.

marginBottom: CSG dynamic Overrides default value from CwLabel.

marginLeft: CSG dynamic Overrides default value from CwLabel.

marginRight: CSG dynamic Overrides default value from CwLabel.

marginTop: CSG dynamic Overrides default value from CwLabel.

showAsDefault: CSG 0 Specifies a shadow thickness for a secondshadow to be drawn around the PushButtonto visualy mark it as a default button.

traversalOn: CSG true Overrides default value from CwLabel.

CwPushButton also inherits resource and callback methods from CwLabel, CwPrimitive, CwBasicWidget, and CwWidget.Consult the resource tables of these classes for more information.

Table 79. CwRowColumn resource and callback methods

adjustLast: CSG true Extends the last row of children tothe bottom edge of RowColumn(when XmOrientation isXmHORIZONTAL) or extends thelast column to the right edge ofRowColumn (when XmOrientation isXmVERTICAL).

buttonMnemonics: C nil Used with the simple menu creationroutines.

buttons: C nil Used with the simple menu creationroutines.

buttonSet: C -1 Used with the simple menu creationroutines.

buttonType: C nil Used with the simple menu creationroutines.

entryAlignment: CSG XmALIGNMENTBEGINNING Specifies the alignment type forCwLabel children whenXmNisAligned is enabled.

entryBorder: CSG 0 Imposes a uniform border widthupon all RowColumn’s children.

entryCallback: C OrderedCollection new Disables the activation callbacks forall ToggleButton, PushButton, andCascadeButton widgets containedwithin the RowColumn widget.

478 IBM Smalltalk: Programmer’s Reference

Page 493: IBM Smalltalk: Programmer's Reference

Table 79. CwRowColumn resource and callback methods (continued)

entryClass: CSG dynamic Specifies the only widget class thatcan be added to the RowColumnwidget; this resource is meaningfulonly when the XmNisHomogeneousresource is set to true.

isAligned: CSG true Specifies text alignment for each itemwithin the RowColumn widget; thisapplies only to items that are asubclass of CwLabel, and on someplatforms, applies only to instances ofCwLabel.

isHomogeneous: CSG dynamic Indicates if the RowColumn widgetshould enforce exact homogeneityamong the items it contains; if true,only the widgets that are of the classindicated by XmNentryClass areallowed as children of theRowColumn widget.

labelString: C nil A text string that displays the label tothe left of the selection area whenXmNrowColumnType is set toXmMENUOPTION.

mapCallback: C OrderedCollection new Specifies a widget-specific callbackfunction that is invoked when thewindow associated with theRowColumn widget is about to bemapped.

CallData type is CwAnyCallbackData.

marginHeight: CSG dynamic Specifies the amount of spacebetween the top edge of theRowColumn widget and the first itemin each column, and the bottom edgeof the RowColumn widget and thelast item in each column.

marginWidth: CSG 3 Specifies the amount of spacebetween the left edge of theRowColumn widget and the first itemin each row, and the right edge of theRowColumn widget and the last itemin each row.

menuHelpWidget: CSG nil Specifies the widget for theCascadeButton, which is treated asthe Help widget ifXmNrowColumnType is set toXmMENUBAR.

menuHistory: CSG nil Specifies the widget of the last menuentry to be activated.

mnemonic: CSG nil Specifies a keyboard shortcut for themenu item. This resource is usedwhen XmNrowColumnType is set toXmMENUOPTION.

Appendix A. Widget resources and callbacks 479

Page 494: IBM Smalltalk: Programmer's Reference

Table 79. CwRowColumn resource and callback methods (continued)

numColumns: CSG 1 Specifies the number of minordimension extensions that are madeto accommodate the entries; thisattribute is only meaningful whenXmNpacking is set toXmPACKCOLUMN.

optionLabel: C nil Used with the simple menu creationroutines.

orientation: CSG dynamic Determines whether RowColumnlayouts are row major or columnmajor.

packing: CSG dynamic Specifies how to pack the itemscontained within a RowColumnwidget.

postFromButton: C nil Used with the simple menu creationroutines.

radioAlwaysOne: CSG true When set to true, forces the activeToggleButton to be automaticallyselected after having been unselected(if no other toggle was activated).

radioBehavior: CSG false Specifies a Boolean value that whentrue, indicates that the RowColumnwidget should enforce aRadioBox-type behavior on all of itschildren that are ToggleButtons.

resizeHeight: CSG true When set to true, requests a newheight if necessary.

resizeWidth: CSG true When set to true, requests a newwidth if necessary.

rowColumnType: CSG XmWORKAREA Specifies the type of RowColumnwidget which is to be created.

simpleCallback: C OrderedCollection new Used with the simple menu creationroutines.

CallData type is integer.

spacing: CSG dynamic Specifies the horizontal and verticalspacing between items containedwithin the RowColumn widget.

subMenuId: CSG nil Specifies the widget for the PulldownMenuPane to be associated with anOptionMenu. The cascade button andits associated pulldown menu musthave the same (or common) parent.

unmapCallback: C OrderedCollection new Specifies a list of callbacks that iscalled after the window associatedwith the RowColumn widget hasbeen unmapped.

CallData type is CwAnyCallbackData.

CwRowColumn also inherits resource and callback methods from CwComposite, CwBasicWidget, and CwWidget.Consult the resource tables of these classes for more information.

480 IBM Smalltalk: Programmer’s Reference

Page 495: IBM Smalltalk: Programmer's Reference

Table 80. CwScale resource and callback methods

decimalPoints: CSG 0 Specifies the number of decimal points toshift the slider value when displaying it.

dragCallback: C OrderedCollection new Specifies the list of callbacks that is calledwhen the slider position changes as the slideris being dragged.

CallData type is CwValueCallbackData.

fontList: CSG dynamic Specifies the font list to use for the title textstring specified by XmNtitleString.

maximum: CSG 100 Specifies the slider’s maximum value. Setmaximum before minimum to avoid warningon x.

minimum: CSG 0 Specifies the slider’s minimum value. Setmaximum before minimum to avoid warningon x.

navigationType: CSG XmNONE Overrides default value from CwComposite.

orientation: CSG XmVERTICAL Displays Scale vertically or horizontally.

processingDirection: CSG XmMAXONTOP Specifies whether the value forXmNmaximum is on the right or left side ofXmNminimum for horizontal Scales or aboveor below XmNminimum for vertical Scales.

showValue: CSG false Specifies if a label for the current slider valueshould be displayed next to the slider.

titleString: CSG nil Specifies the title text string to appear in thescale widget window.

traversalOn: CSG true When set to true, specifies the Scale’s slider isto have traversal on.

value: CSG 0 Specifies the slider’s current position alongthe scale, between minimum and maximum.

valueChangedCallback: C OrderedCollection new Specifies the list of callbacks that is calledwhen the value of the slider has changed.

CallData type is CwValueCallbackData.

CwScale also inherits resource and callback methods from CwComposite, CwBasicWidget, and CwWidget. Consult theresource tables of these classes for more information.

Table 81. CwScrollBar resource and callback methods

decrementCallback: C OrderedCollection new Specifies the list of callbacks that is calledwhen an arrow is selected decreasing theslider value by one increment.

CallData type is CwValueCallbackData.

dragCallback: C OrderedCollection new Specifies the list of callbacks that is called oneach incremental change of position when theslider is being dragged.

CallData type is CwValueCallbackData.

increment: CSG 1 Specifies the amount to move the slider whenthe corresponding arrow is selected.

Appendix A. Widget resources and callbacks 481

Page 496: IBM Smalltalk: Programmer's Reference

Table 81. CwScrollBar resource and callback methods (continued)

incrementCallback: C OrderedCollection new Specifies the list of callbacks that is calledwhen an arrow is selected increasing theslider value by one increment.

CallData type is CwValueCallbackData.

maximum: CSG 0 Specifies the slider’s maximum value. Setmaximum before minimum to avoid warningon x.

minimum: CSG 0 Specifies the slider’s minimum value. Setmaximum before minimum to avoid warningon x.

navigationType: CSG XmTABGROUP Overrides default value from CwPrimitive.

orientation: CSG XmVERTICAL Specifies whether the ScrollBar is displayedvertically or horizontally.

pageDecrementCallback: C OrderedCollection new Specifies the list of callbacks that is calledwhen the slider area is selected and the slidervalue is decreased by one page increment.

CallData type is CwValueCallbackData.

pageIncrement: CSG 10 Specifies the amount to move the slider whenselection occurs on the slide area.

pageIncrementCallback: C OrderedCollection new Specifies the list of callbacks that is calledwhen the slider area is selected and the slidervalue is increased by one page increment.

CallData type is CwValueCallbackData.

processingDirection: CSG XmMAXONBOTTOM Specifies whether the value forXmNmaximum should be on the right or leftside of XmNminimum for horizontalScrollBars or above or below XmNminimumfor vertical ScrollBars.

sliderSize: CSG 0 Specifies the size of the slider between thevalues of 0 and maximum - minimum.

toBottomCallback: C OrderedCollection new Specifies the list of callbacks that is calledwhen the user moves the slider to the bottomof the scroll bar.

CallData type is CwValueCallbackData.

toTopCallback: C OrderedCollection new Specifies the list of callbacks that is calledwhen the user moves the slider to the top ofthe scroll bar.

CallData type is CwValueCallbackData.

value: CSG 0 Specifies the slider’s position betweenminimum and maximum.

482 IBM Smalltalk: Programmer’s Reference

Page 497: IBM Smalltalk: Programmer's Reference

Table 81. CwScrollBar resource and callback methods (continued)

valueChangedCallback: C OrderedCollection new Specifies the list of callbacks that is calledwhen the slider is released while beingdragged; this is in place ofXmNincrementCallback,XmNdecrementCallback,XmNpageIncrementCallback, orXmNpageDecrementCallback when they donot have any callbacks attached.

CallData type is CwValueCallbackData.

CwScrollBar also inherits resource and callback methods from CwPrimitive, CwBasicWidget, and CwWidget. Consultthe resource tables of these classes for more information.

Table 82. CwScrolledWindow resource and callback methods

clipBackgroundColor: CSG dynamic Specifies the background color for theclip area.

clipBackgroundPixmap: CSG nil Specifies a pixmap for tiling thebackground of the clip area.

horizontalScrollBar: CSG nil Specifies the widget that is thehorizontal ScrollBar.

scrollBarDisplayPolicy: CSG XmSTATIC Controls the automatic placement ofthe ScrollBars.

scrollingPolicy: CSG XmAPPLICATIONDEFINED Performs automatic scrolling of thework area with no applicationinteraction.

verticalScrollBar: CSG nil Specifies the widget ID of the verticalScrollBar.

visualPolicy: CS XmVARIABLE Grows the ScrolledWindow to matchthe size of the work area, or it can beused as a static viewport onto alarger data space.

workWindow: CSG nil Specifies the widget ID of theviewing area.

CwScrolledWindow also inherits resource and callback methods from CwComposite, CwBasicWidget, and CwWidget.Consult the resource tables of these classes for more information.

Table 83. CwSelectionBox resource and callback methods

applyCallback: C OrderedCollection new Specifies the list of callbacks that is calledwhen the user clicks on the Apply button.

CallData type is CwAnyCallbackData.

applyLabelString: CSG ‘Apply’ Specifies the string label for the Applybutton.

cancelCallback: C OrderedCollection new Specifies the list of callbacks that is calledwhen the user clicks on the Cancel button.

CallData type is CwAnyCallbackData.

dialogType: CG dynamic Determines the set of SelectionBox childrenwidgets that are created and managed atinitialization.

listItemCount G 0 Specifies the items in the SelectionBox list.

Appendix A. Widget resources and callbacks 483

Page 498: IBM Smalltalk: Programmer's Reference

Table 83. CwSelectionBox resource and callback methods (continued)

listItems: CSG nil Specifies the items in the SelectionBox list.

listLabelString: CSG nil Specifies the string label to appear above theSelectionBox list containing the selectionitems.

listVisibleItemCount: CSG 8 Specifies the number of items displayed inthe SelectionBox list.

mustMatch: CSG false Specifies whether the selection widget shouldcheck if the user’s selection in the text editfield has an exact match in the SelectionBoxlist when the OK button is activated.

noMatchCallback: C OrderedCollection new Specifies the list of callbacks that is calledwhen the user makes a selection from the textedit field that does not have an exact matchwith any of the items in the list box.

CallData type is CwAnyCallbackData.

selectionLabelString: CSG ‘Selection’ Specifies the string label for the selection textedit field.

textColumns: CSG 20 Specifies the initial width of the text windowmeasured in character spaces.

textString: CSG nil Specifies the text in the text edit selectionfield.

CwSelectionBox also inherits resource and callback methods from CwCompositeBox, CwBulletinBoard, CwComposite,CwBasicWidget, and CwWidget. Consult the resource tables of these classes for more information.

Table 84. CwSeparator resource and callback methods

margin: CSG 0 Specifies the space on the left and right sidesbetween the border of the Separator and theline drawn for horizontal orientation.

orientation: CSG XmHORIZONTAL Displays Separator vertically or horizontally.

separatorType: CSG XmSHADOWETCHEDIN Specifies the type of line drawing to be donein the Separator widget.

traversalOn: CSG false Overrides default value from CwPrimitive.

CwSeparator also inherits resource and callback methods from CwPrimitive, CwBasicWidget, and CwWidget. Consultthe resource tables of these classes for more information.

Table 85. CwShell resource and callback methods

allowShellResize: CG false Specifies that if this resource is false, then theShell widget instance will returnXtGeometryNo to all geometry requests fromits children.

borderWidth: CSG 1 Overrides the default value from CwWidget.

popdownCallback: C OrderedCollection new Specifies a list of callbacks that is called whenthe widget instance is popped down bypopdown.

CallData type is CwAnyCallbackData.

484 IBM Smalltalk: Programmer’s Reference

Page 499: IBM Smalltalk: Programmer's Reference

Table 85. CwShell resource and callback methods (continued)

popupCallback: C OrderedCollection new Specifies a list of callbacks that is called whenthe widget instance is popped up by popup.

CallData type is CwAnyCallbackData.

strictClipping: CG CwWidget strictClipping Some platforms show a dramatic speedimprovement in the time to draw windowscontaining many widgets if they are notrequired to ensure certain clippingconstraints.

CwShell also inherits resource and callback methods from CwBasicWidget and CwWidget. Consult the resource tablesof these classes for more information.

Table 86. CwText resource and callback methods

activateCallback: C OrderedCollection new Specifies the list of callbacks that iscalled when the user presses thedefault action key.

CallData type is CwAnyCallbackData.

alignment: CG XmALIGNMENTBEGINNING Specifies the text alignment when thetext widget has an editMode ofXmSINGLENEEDIT.

borderWidth: CSG 1 Overrides default value from CwWidget

columns: CSG 20 Specifies the initial width of the textwindow measured in character spaces.

cursorPosition: CSG 0 Indicates the position in the text wherethe current insert cursor is to belocated.

doubleClickSelect: CSG true Indicates that the widget should notperform double-click selectionprocessing. Ignored on platformswhere the feature is not configurable.

editable: CSG true Indicates whether the user can edit thetext string.

editMode: CG XmSINGLELINEEDIT Specifies whether the widget supportssingle line or multi line editing of text.

focusCallback: C OrderedCollection new Specifies the list of callbacks that iscalled before Text has accepted inputfocus.

CallData type is CwAnyCallbackData.

fontList: CSG dynamic Specifies the font list to be used forText.

losingFocusCallback: C OrderedCollection new Specifies the list of callbacks that iscalled before Text loses input focus.

CallData type is CwAnyCallbackData.

marginHeight: CSG dynamic Specifies the distance between the topedge of the window and the text, andbetween the bottom edge of thewindow and the text.

Appendix A. Widget resources and callbacks 485

Page 500: IBM Smalltalk: Programmer's Reference

Table 86. CwText resource and callback methods (continued)

marginWidth: CSG dynamic Specifies the distance between the leftedge of the window and the text, andbetween the right edge of the windowand the text.

maxLength: CSG dynamic Specifies the maximum length of thetext string that can be entered into textfrom the keyboard.

modifyVerifyCallback: C OrderedCollection new Specifies the list of callbacks that iscalled before text is deleted from orinserted into Text.

CallData type isCWTextVerifyCallbackData.

navigationType: CSG XmTABGROUP Overrides default value from CsPrimitive.

rows: CSG 1 Specifies the initial height of the textwindow measured in characterheights.

scrollHorizontal: CG true Adds a ScrollBar that enables the userto scroll horizontally through textwhen set to true.

scrollVertical: CSG true Adds a ScrollBar that enables the userto scroll vertically through text whenset to true.

tabSpacing: CSG 8 Indicates the tab stop spacing.

topCharacter: CSG 0 Displays the position of text at the topof the window.

value: CSG ‘‘ Specifies the displayed text String.

valueChangedCallback: C OrderedCollection new Specifies the list of callbacks that iscalled after text is deleted from orinserted into Text.

CallData type is CwAnyCallbackData.

verifyBell: CSG true Specifies whether the bell shouldsound when the verification returnswithout continuing the action.

wordWrap: CSG false Indicates that lines are to be broken atword breaks.

CwText also inherits resource and callback methods from CwPrimitive, CwBasicWidget, and CwWidget. Consult theresource tables of these classes for more information.

Table 87. CwToggleButton resource and callback methods

armCallback: C OrderedCollection new Specifies the list of callbacks that is calledwhen the receiver is armed.

CallData type is CwAnyCallbackData.

disarmCallback: C OrderedCollection new Specifies the list of callbacks that is calledwhen the receiver is disarmed.

indicatorOn: CSG true Specifies that a toggle indicator is drawn tothe left of the toggle text or pixmap when setto true.

CallData type is CwAnyCallbackData.

486 IBM Smalltalk: Programmer’s Reference

Page 501: IBM Smalltalk: Programmer's Reference

Table 87. CwToggleButton resource and callback methods (continued)

indicatorType: CSG XmNOFMANY Specifies if the indicator is a 1-of or N-ofindicator.

marginBottom: CSG dynamic Overrides default value from CwLabel.

marginLeft: CSG dynamic Overrides default value from CwLabel.

marginRight: CSG dynamic Overrides default value from CwLabel.

marginTop: CSG dynamic Overrides default value from CwLabel.

set: CSG false Displays the button in its selected state if setto true.

traversalOn: CSG true Overrides default value from CwLabel.

valueChangedCallback: C OrderedCollection new Specifies the list of callbacks that is calledwhen the ToggleButton value is changed.

CallData type isCwToggleButtonCallbackData.

CwToggleButton also inherits resource and callback methods from CwLabel, CwPrimitive, CwBasicWidget, andCwWidget. Consult the resource tables of these classes for more information.

Table 88. CwTopLevelShell resource and callback methods

iconic: CSG false When set to true, specifies that theapplication will attempt to start as an icononce it is realized.

screen: CSG dynamic Specifies the screen on which the widgetinstance resides.

CwTopLevelShell also inherits resource and callback methods from CwWMShell, CwShell, CwBasicWidget, andCwWidget. Consult the resource tables of these classes for more information.

Table 89. CwTransientShell resource and callback methods

CwTransientShell inherits resource and callback methods from CwWMShell, CwShell, CwBasicWidget, and CwWidget.Consult the resource tables of these classes for more information.

Table 90. CwWidget resource and callback methods

ancestorSensitive G dynamic Specifies whether the immediate parent of thewidget will react to input events.

borderWidth: CSG 1 Specifies the width of the border thatsurrounds the widget’s window on all foursides.

bottomAttachment: CSG XmATTACHNONE Specifies attachment of the bottom side of thechild. This resource is only valid if thewidget’s parent is a CwForm.

bottomOffset: CSG 0 Specifies the constant offset between thebottom side of the child and the object towhich it is attached. This resource is onlyvalid if the widget’s parent is a CwForm.

bottomPosition: CSG 0 Determines the relative position of thebottom side of the child. This resource is onlyvalid if the widget’s parent is a CwForm.

bottomWidget: CSG nil Specifies the widget to which the bottom sideof the child is attached. This resource is onlyvalid if the widget’s parent is a CwForm.

Appendix A. Widget resources and callbacks 487

Page 502: IBM Smalltalk: Programmer's Reference

Table 90. CwWidget resource and callback methods (continued)

depth G CgWindow default depth Specifies the number of bits that can be usedfor each pixel in the widget’s window.

destroyCallback: C OrderedCollection new Specifies a list of callbacks that is called whenthe widget is destroyed.

CallData type is CwAnyCallbackData.

dragDetectCallback: C OrderedCollection new Specifies a list of callbacks that is called whenthe user performs a mouse movement that isthe cue for the application to initiate dragand drop processing.

height: CSG dynamic Specifies the height of the widget’s windowin pixels, not including the border area.

leftAttachment: CSG XmATTACHNONE Specifies attachment of the left side of thechild. This resource is only valid if thewidget’s parent is a CwForm.

leftOffset: CSG 0 Specifies the constant offset between the leftside of the child and the object to which it isattached. This resource is only valid if thewidget’s parent is a CwForm.

leftPosition: CSG 0 Determines the relative position of the leftside of the child. This resource is only valid ifthe widget’s parent is a CwForm.

leftWidget: CSG nil Specifies the widget to which the left side ofthe child is attached. This resource is onlyvalid if the widget’s parent is a CwForm.

mappedWhenManaged: CSG true Maps the widget (makes visible) as soon as itis both realized and managed, if set to true.

resizable: CSG true This Boolean resource specifies whether ornot a child’s request for a new size is(conditionally) granted by the Form.

resizeCallback: C OrderedCollection new Specifies the list of callbacks that is calledwhen the widget is resized. This resource isonly valid if the widget’s parent is aCwForm.

CallData type is CwAnyCallbackData.

rightAttachment: CSG XmATTACHNONE Specifies attachment of the right side of thechild. This resource is only valid if thewidget’s parent is a CwForm.

rightOffset: CSG 0 Specifies the constant offset between the rightside of the child and the object to which it isattached. This resource is only valid if thewidget’s parent is a CwForm.

rightPosition: CSG 0 Determines the relative position of the rightside of the child. This resource is only valid ifthe widget’s parent is a CwForm.

rightWidget: CSG nil Specifies the widget to which the right sideof the child is attached. This resource is onlyvalid if the widget’s parent is a CwForm.

sensitive: CSG true Determines whether a widget will react toinput events.

488 IBM Smalltalk: Programmer’s Reference

Page 503: IBM Smalltalk: Programmer's Reference

Table 90. CwWidget resource and callback methods (continued)

topAttachment: CSG XmATTACHNONE Specifies attachment of the top side of thechild. This resource is only valid if thewidget’s parent is a CwForm.

topOffset: CSG 0 Specifies the constant offset between the topside of the child and the object to which it isattached. This resource is only valid if thewidget’s parent is a CwForm.

topPosition: CSG 0 Determines the relative position of the topside of the child. This resource is only valid ifthe widget’s parent is a CwForm.

topWidget: CSG nil Specifies the widget to which the top side ofthe child is attached. This resource is onlyvalid if the widget’s parent is a CwForm.

userData: CSG nil Allows the user-defined application to attachany necessary specific data to the widget.

width: CSG dynamic Specifies the width of the widget’s windowin pixels, not including the border area.

x: CSG 0 Specifies the x-coordinate of the widget’supper left-hand corner (excluding the border)in relation to its parent widget. Note that themethods x: and y: in CwBasicWidget on XMotif will not cause the widget to be moved.This is in accordance with the Motifspecification. In order to set the x,y resourcesand move the widget, you should usemethod moveWidget:y:.

y: CSG 0 Specifies the y-coordinate of the widget’supper left-hand corner (excluding the border)in relation to its parent widget. Note that themethods x: and y: in CwBasicWidget on XMotif will not cause the widget to be moved.This is in accordance with the Motifspecification. In order to set the x,y resourcesand move the widget, you should usemethod moveWidget:y:.

CwWidget is a subclass of Object.

Table 91. CwWMShell resource and callback methods

autoRaise: CG true Specifies effects on keyboard focus andstacking order when the receiver or any of itsdescendents are selected with the mouse.

dbcsInput: CG false Specifies that the platform-dependent DBCSshell style will be enabled.

focusCallback: C OrderedCollection new Specifies the list of callbacks that is calledwhen the shell gains or loses keyboard focus.

CallData type is CwAnyCallbackData.

icon: CSG XmUNSPECIFIEDICON Specifies an icon that could be used by thewindow manager as the application’s icon.

iconifyCallback: C OrderedCollection new Specifies the list of callbacks that is calledwhen the shell is iconified or deiconified.

CallData type is CwAnyCallbackData.

Appendix A. Widget resources and callbacks 489

Page 504: IBM Smalltalk: Programmer's Reference

Table 91. CwWMShell resource and callback methods (continued)

iconMask: CSG XmUNSPECIFIEDPIXMAP Specifies a bitmap that could be used by thewindow manager as the application’s iconmask.

iconPixmap: CSG XmUNSPECIFIEDPIXMAP Specifies a bitmap that could be used by thewindow manager as the application’s icon.

mwmDecorations: CG -1 Includes the decoration flags describing thespecific decorations to add or remove fromthe window manager frame.

title: CSG dynamic Specifies the application name to bedisplayed by the window manager. If title isnot explicitly set, the widget’s name is usedby default.

windowCloseCallback: C OrderedCollection new Specifies the list of callbacks that is calledwhen the shell is about to be closed by thewindow manager.

CallData type isCwConfirmationCallbackData.

CwWMShell also inherits resource and callback methods from CwShell, CwBasicWidget, and CwWidget. Consult theresource tables of these classes for more information.

490 IBM Smalltalk: Programmer’s Reference

Page 505: IBM Smalltalk: Programmer's Reference

Appendix B. Extended widgets resources and callbacks

This appendix provides a detailed listing of the resources and callbacks for eachclass in the Extended Widgets subsystem. Note that only the set resource methodsare shown in each table, unless a resource only has a get method. Get methodshave the same name without the colon. Create/Set/Get (CSG) access designationand default value are listed for each resource and callback.

Callback list set methods are shown, even though callbacks are usually addedusing addCallback:receiver:selector:clientData:, and not using a callback list setmethod. These methods end in ″Callback:″.

The example Table 1. CwArrowButton resource and callback methods in “Appendix A.Widget resources and callbacks” on page 469 shows how to use the tables in thisappendix.

Table 92. CwExtendedComposite resource and callback methods

backgroundColor: CSG dynamic A CgRGBColor that specifies the backgrounddrawing color. Note: The particular aspects ofthe widget’s appearance that are affected bychanging this resource depend onplatform-specific styles and capabilities andvary from platform to platform.

foregroundColor: CSG dynamic A CgRGBColor that specifies the foregrounddrawing color. Note: The particular aspects ofthe widget’s appearance that are affected bychanging this resource depend onplatform-specific styles and capabilities andvary from platform to platform.

navigationType: CSG XmNONE Controls whether the widget is a navigationgroup. Allowed values are as follows:XmNONE Indicates that the widget is not anavigationgroup. XmTABGROUP Indicatesthat the widget is included automatically inkeyboard navigation.

traversalOn: CSG true Specifies if traversal is activated for thiswidget. Note: On some platforms, a widgetthat cannot be reached through keyboardtraversal will not take focus under anyconditions, for example, even when it isclicked on with the mouse.

CwExtendedComposite also inherits resource and callback methods from CwExtendedPrimitive, CwExtendedWidget, andCwWidget.

Table 93. CwExtendedPrimitive resource and callback methods

backgroundColor: CSG dynamic A CgRGBColor that specifies the backgrounddrawing color. Note: The particular aspects ofthe widget’s appearance that are affected bychanging this resource are dependent onplatform-specific styles and capabilities andvary from platform to platform.

© Copyright IBM Corp. 1994, 2000 491

Page 506: IBM Smalltalk: Programmer's Reference

Table 93. CwExtendedPrimitive resource and callback methods (continued)

foregroundColor: CSG dynamic A CgRGBColor that specifies the foregrounddrawing color. Note: The particular aspects ofthe widget’s appearance that are affected bychanging this resource are dependent onplatform-specific styles and capabilities andvary from platform to platform.

navigationType: CSG XmNONE Controls whether the widget is a navigationgroup. Allowed values are as follows:XmNONE Indicates that the widget is not anavigationgroup. XmTABGROUP Indicatesthat the widget is included automatically inkeyboard navigation.

traversalOn: CSG true Specifies if traversal is activated for thiswidget. Note: On some platforms, a widgetthat is not reachable through keyboardtraversal will not take focus under anyconditions for example, even when it isclicked on with the mouse.

CwExtendedPrimitive also inherits resource and callback methods from CwExtendedComposite, CwExtendedWidget, andCwWidget.

Table 94. EwContainerList resource and callback methods

applicationDrawnBack-ground:

CSG false Specifies whether the application wants thedrawBackgroundCallback to be triggeredwhen an item’s background needs to bedrawn. If this value is false, then the widgetwill draw the normal default backgroundfor each selected and nonselected item.

drawBackground- Callback: C OrderedCollection new Specifies the list of callbacks that is calledwhen an item’s background needs to bedrawn. The callback reason isXmCRDRAWBACKGROUND. TheapplicationDrawnBackground resource mustbe true for this callback to be activated.CallData type isEwIconListDrawBackgroundCallbackData.

fontList: CSG CwFontList default Specifies the font list associated with the listitems.

itemHeight: CSG 34 Specifies the height list items in pixels. Thisincludes the margin height on the top andbottom of the item and two pixels foremphasis. If the resource is nil, each item isindividually sized to its preferred heightplus twice the margin height plus two pixelsfor emphasis.

items: CSG OrderedCollection new A collection that represents hierarchy rootitems in the list.

492 IBM Smalltalk: Programmer’s Reference

Page 507: IBM Smalltalk: Programmer's Reference

Table 94. EwContainerList resource and callback methods (continued)

visualInfoCallback: C OrderedCollection new Specifies the list of callbacks that is calledwhen an item’s icon, label and isInUseindicator are needed. The callback reason isXmCRVISUALINFO. The application musthook this callback and set the calldata iconto the CgIcon (or other renderable object) tobe displayed as the icon for the item incalldata item. It must also set the calldatalabel to the String (or other renderableobject) to be displayed as the label for theitem. No other resources might be set whileinside this callback nor might anynonresource API be invoked. Calldata typeis EwIconVisualInfoCallbackData.

EwContainerList also inherits resource and callback methods from EwContainerList, EwLinearList, EwList, EwScrollable,CwExtendedPrimitive, CwExtendedWidget, and CwWidget.

Table 95. EwDrawnList resource and callback methods

applicationDrawnStates: CSG XmDRAWNONE Describes that visual states will be customdrawn by the application in thedisplayCallback. Any visual states notspecified in this resource are drawn by theEwDrawnList. The integer represents thebitwise inclusive OR of one or more of thefollowing values: XmDRAWNONE,XmDRAWSELECTION,XmDRAWCURSORED

displayCallback: C OrderedCollection new Specifies the list of callbacks that is calledwhen an item is to be drawn. The callbackreason is XmCRLISTITEMDISPLAY. If thiscallback is not hooked, the list will appearempty when displayed. Calldata type isEwDrawnListDrawCallbackData.

itemHeight: CSG 16 Specifies the height in pixels of items in thelist. Note: This resource is ignored if themeasureCallback is hooked.

items: CSG OrderedCollection new A collection that represents the items in thelist. Usually the item list is copied form theapplication via asOrderedCollection.However, the use of an Interval for the itemlist is optimized so that a copy andconversion is not made until an editoperation is requested.

itemWidth: CSG 500 Specifies the width in pixels of items in thelist. Note: This resource is only used to setthe scrolling interval for the horizontal scrollbar. It is ignored if the scrollHorizontalresource is false.

Appendix B. Extended widgets resources and callbacks 493

Page 508: IBM Smalltalk: Programmer's Reference

Table 95. EwDrawnList resource and callback methods (continued)

measureCallback: C OrderedCollection new Specifies the list of callbacks that is called inorder to obtain the height of an item. Theapplication specifies the height by setting theheight field of the calldata to the Integer pixelheight of the item. If this callback is nothooked, the itemHeight resource is used asthe height of all items. No other resourcesmight be set while inside this callback normight any nonresource API be invoked. Thecallback reason isXmCRLISTITEMMEASURE. Calldata type isEwDrawnListDrawCallbackData.

EwDrawnList also inherits resource and callback methods from EwDrawnList, EwLinearList, EwList, EwScrollable,CwExtendedPrimitive, CwExtendedWidget, and CwWidget.

Table 96. EwFlowedIconList resource and callback methods

itemHeight: CSG 34 Specifies the height of each list item in pixels.This includes the margin height on the topand bottom of the item and two pixels foremphasis. Unlike other extended list widgets,the value of this resource might not be nil.That is, all items must have the same height.This height is used in laying out the itemsinto vertical columns.

itemWidth: CSG 80 Specifies the width of each list item in pixels.This includes the two pixels for emphasis.Unlike other extended list widgets, the valueof this resource might not be nil. That is, allitems must have the same width. This widthis used in laying out the items into horizontalrows.

EwFlowedIconList also inherits resource and callback methods from EwFlowedIconList, EwIconList, EwContainerList,EwLinearList, EwList, EwScrollable, CwExtendedPrimitive, CwExtendedWidget, and CwWidget.

Table 97. EwIconArea resource and callback methods

applicationDrawnBack-ground:

CSG false Specifies whether the application wants thedrawBackgroundCallback to be triggeredwhen an item’s background needs to bedrawn. If this value is false, then the widgetwill draw the default background for eachselected and nonselected item.

beginEditCallback: C OrderedCollection new Specifies the list of callbacks that is calledwhen an item is about to be edited. Thecallback reason is XmCRBEGINEDIT. Forediting to occur, the application must setcalldata doit flag to true. It might alsoreplace the editPolicy in the calldata with acustom edit policy appropriate for the itembeing edited. Calldata type isEwBeginEditCallbackData.

494 IBM Smalltalk: Programmer’s Reference

Page 509: IBM Smalltalk: Programmer's Reference

Table 97. EwIconArea resource and callback methods (continued)

drawBackground- Callback: C OrderedCollection new Specifies the list of callbacks that is calledwhen an item’s background needs to bedrawn. The callback reason isXmCRDRAWBACKGROUND. TheapplicationDrawnBackground resource mustbe true for this callback to be activated.Calldata type is EwIcon-ListdrawBackgroundCallbackData.

endEditCallback: C OrderedCollection new Specifies the list of callbacks that is calledwhen an item is done being edited. Thecallback reason is XmCRENDEDIT. Thiscallback is activated whenever editing endson an item or whenever the value changesduring an edit. The application must hookthis callback and use the calldata.brnewValue to update the value of theapplication objects. Calldata type isEwEndEditCallbackData.

fontList: CSG CwFontList default Specifies the font list associated with the listitems.

innerMargin: CSG 2 Specifies the margin width to be usedbetween each item’s icon and its label.

items: CSG OrderedCollection new A collection that represents the itemsin thelist.

labelOrientation: CSG XmRIGHT Specifies the orientation of each item’s labelwith respect to its icon. Allowed values areas follows: XmRIGHT The label is to theright of the icon. XmBOTTOM The label isbelow each icon.

selectedItems: CSG OrderedCollection new A collection that represents currently selecteditems, either by the user or the application.

selectionPolicy: CSG XmBROWSESELECT Defines the interpretation of the selectionaction. Allowed values are as follows:XmSINGLESELECT Allows only singleselections. XmMULTIPLESELECT Allowsmultiple selections. XmEXTENDEDSELECTAllows extended selections.XmBROWSESELECT Allows drag andbrowse functionality.XmREADONLYSELECT Allows navigation,but no selection or callbacks.

visualInfoCallback: C OrderedCollection new Specifies the list of callbacks that is calledwhen an item’s icon, label and isInUseindicator are needed. The callback reason isXmCRVISUALINFO. The application musthook this callback and set the calldata iconto the CgIcon (or other renderable object) tobe displayed as the icon for the item incalldata item. It must also set the calldatalabel to the String (or other renderableobject) to be displayed as the label for theitem. No other resources might be set whileinside this callback nor might anynonresource API be invoked. Calldata type isEwIconVisualInfoCallbackData.

Appendix B. Extended widgets resources and callbacks 495

Page 510: IBM Smalltalk: Programmer's Reference

Table 97. EwIconArea resource and callback methods (continued)

EwIconArea also inherits resource and callback methods from EwIconArea, EwList, EwScrollable, CwExtendedPrimitive,CwExtendedWidget, and CwWidget.

Table 98. EwIconList resource and callback methods

beginEditCallback: C OrderedCollection new Specifies the list of callbacks that is calledwhen an item is about to be edited. Thecallback reason is XmCRBEGINEDIT. Forediting to occur, the application must setcalldata doit: to true. It might also replace theeditPolicy in the calldata with a custom editpolicy appropriate for the item being edited.Calldata type is EwBeginEditCallbackData.

emphasisPolicy: CSG XmSEPARATE Specifies whether to draw the icon and labelemphasis as a single rectangle(XmTOGETHER) or as two separaterectangles (XmSEPARATE).

endEditCallback: C OrderedCollection new Specifies the list of callbacks that is calledwhen an item is done being edited. Thecallback reason is XmCRENDEDIT. Thiscallback is activated whenever editing endson an item or whenever the value changesduring an edit. The application must hookthis callback and use the calldata newValueto update the value of the application objects.Calldata type is EwEndEditCallbackData.

innerMargin: CSG 2 Specifies the margin width to be usedbetween each item’s icon and its label.

itemWidth: CSG 1 Specifies the width of list items the in pixels.The value of this resource will be increased ifany items are encountered in the list with awidth exceeding the resource value. Thisresource is used to set the scrolling intervalfor the horizontal scroll bar. It is ignored ifthe scrollHorizontal resource is false.

labelOrientation: CSG XmRIGHT Specifies the orientation of each item’s labelwith respect to its icon. Allowed values are asfollows: XmRIGHT The label is to the right ofthe icon. XmBOTTOM The label is beloweach icon.

visualInfoCallback: C OrderedCollection new Specifies the list of callbacks that is calledwhen an item’s icon, label and isInUseindicator are needed. The callback reason isXmCRVISUALINFO. The application musthook this callback and set the calldata icon tothe CgIcon (or other renderable object) to bedisplayed as the icon for the item in calldataitem. It must also set the calldata label to theString (or other renderable object) to bedisplayed as the label for the item. No otherresources might be set while inside thiscallback nor might any nonresource API beinvoked. Calldata type isEwIconVisualInfoCallbackData.

EwIconList also inherits resource and callback methods from ExIconList, EwContainerList, EwLinearlist, EwList,EwScrollable, CwExtendedWidget, and CwWidget.

496 IBM Smalltalk: Programmer’s Reference

Page 511: IBM Smalltalk: Programmer's Reference

Table 99. EwIconTree resource and callback methods

childrenCallback: C OrderedCollection new Specifies the list of callbacks that iscalled when an item’s list of children isneeded. The callback reason isXmCRCHILDREN. The application mustset the calldata children to the Collectionof children objects of the item in calldataitem. Calldata type isEwChildrenCallbackData.

expandCollapse- Callback: C OrderedCollection new Specifies the list of callbacks that iscalled when an item is expanded orcollapsed. The callback reason isXmCREXPAND or XmCRCOLLAPSE.Calldata type is EwListCallbackData.

hierarchyPolicy: CSG EwHierarchyPolicy new An instance or subclass ofEwHierarchyPolicy that defines how todisplay and manage the hierarchy.

itemCount G 0 Specifies the total number of items. Thisnumber might not match the itemsresource because this number is the sizeof the expanded hierarchy. It isautomatically updated by the listwhenever an element is added to ordeleted from the list.

items: CSG OrderedCollection new A collection that represents hierarchyroot items in the list.

EwIconTree also inherits resource and callback methods from EwIconTree, EwIconList, EwContainerList, EwLinearList,EwList, EwScrollable, CwExtendedWidget, and CwWidget.

Table 100. EwLinearList resource and callback methods

items: CSG OrderedCollection new The collection of items to be displayed.

SelectedItemCount G 0 Specifies the number of objects in the selecteditem list.

selectedItems: CSG OrderedCollection new The collection of items that are currentlyselected, either by the user or the application.

topItemPosition: CSG 1 Specifies the integer position of the item thatis the first visible item in the list. Setting thisresource is equivalent to calling the setPos:function. The position of the first item in thelist is 1; the position of the second item is 2;and so on. A position of 0 specifies the lastitem in the list.

visibleItemCount G dynamic Represents the number of items that can fit inthe visible space of the list. Until the list isrealized, the answer is 0.

EwLinearList also inherits resource and callback methods from these classes: EwLinearList, EwList, EwScrollable,CwExtendedPrimitive, CwExtendedWidget, and CwWidget.

Appendix B. Extended widgets resources and callbacks 497

|

Page 512: IBM Smalltalk: Programmer's Reference

Table 101. EwList resource and callback methods

backgroundColor: CSG dynamic A CgRGBColor that specifies thebackground drawing color. changingthis resource depend onplatform-specific styles and capabilitiesand vary from platform to platform.

browseSelectionCallback: C OrderedCollection new Specifies the list of callbacks that iscalled when an item is selected in thebrowse selection mode. The callbackreason is XmCRBROWSESELECT.Calldata type isEwListSelectionCallbackData.

defaultActionCallback: C OrderedCollection new Specifies the list of callbacks that iscalled when an item is double clicked.The callback reason isXmCRDEFAULTACTION. Calldata typeis EwListSelectionCallbackData.

extendedSelectionCallback: C OrderedCollection new Specifies the list of callbacks that iscalled when items are selected using theextended selection mode. The callbackreason is XmCREXTENDEDSELECT.Calldata type isEwListSelectionCallbackData.

foregroundColor: CSG dynamic A CgRGBColor that specifies theforeground drawing color. Note: Theparticular aspects of the widget’sappearance that are affected bychanging this resource depend onplatform-specific styles and capabilitiesand vary from platform to platform.

itemCount G 0 The total number of items. This numbermatches the items resource. It isautomatically updated by the listwhenever an element is added to ordeleted from the list.

items: CSG OrderedCollection new The collection of items to be displayed.

modifyVerifyCallback: C OrderedCollection new Specifies the list of callbacks that iscalled when the selection is about to bechanged. The application might ″undo″the selection change by setting the doitfield of the calldata to false. Calldatatype is CwConfirmationCallbackData.

multipleSelection- Callback: C OrderedCollection new Specifies the list of callbacks that iscalled when an item is selected inmultiple selection mode. The callbackreason is XmCRMULTIPLESELECT.Calldata type isEwListSelectionCallbackData.

498 IBM Smalltalk: Programmer’s Reference

Page 513: IBM Smalltalk: Programmer's Reference

Table 101. EwList resource and callback methods (continued)

scrollHorizontal: CG true Specifies whether a horizontal scroll barshould be used for the list. Thisresource will only have an effect if thewidget is created using thecreateScrolledWidget:- parent:argBlock:or createScrolledManagedWidget:-parent:argBlock: message. Thehorizontal scroll bar will always bepresent, even when the window islarger than the item width.

selectionPolicy: CSG XmBROWSESELECT Defines the interpretation of theselection action. Valid values are:XmSINGLESELECT Allows only singleselections. XmMULTIPLESELECTAllows multiple selections.XmEXTENDEDSELECT Allowsextended selections.XmBROWSESELECT Allows drag andbrowse functionality.XmREADONLYSELECT Allowsnavigation, but no selection orcallbacks.

singleSelectionCallback: C OrderedCollection new Specifies the list of callbacks that iscalled when an item is selected in singleselection mode. The callback reason isXmCRSINGLESELECT. Calldata type isEwListSelectionCallbackData.

EwList also inherits resource and callback methods from EwList, EwScrollable, CwExtendedPrimitive,CwExtendedWidget, and CwWidget.

Table 102. EwNotebook resource and callback methods

backgroundColor: CSG dynamic A CgRGBColor that specifies the backgrounddrawing color. Note: The particular aspects ofthe widget’s appearance that are affected bychanging this resource depend onplatform-specific styles and capabilities andvary from platform to platform.

currentPage: CSG dynamic The instance of EwPage that is currently ontop.

fontList: SG CwFontList default Specifies the font list for any text widget inthe notebook.

pageChangeCallback: C OrderedCollection new Specifies the list of callbacks that is called justbefore any switching of pages takes place.This event is triggered when a new page isbeing brought to the top in the receiver. Thecallback reason is XmCRPAGECHANGE.Calldata type is CwPageChangeCallbackData.

EwNotebook also inherits resource and callback methods from EwNotebook, CwExtendedComposite, CwExtendedWidget,and CwWidget.

Appendix B. Extended widgets resources and callbacks 499

Page 514: IBM Smalltalk: Programmer's Reference

Table 103. EwPage resource and callback methods

buttonFontList: CSG nil Defines the font used for button children ofthe page (that is, push buttons and togglebuttons). This resource has no effect and isonly provided for protocol compatiabilitywith CwForm.

cancelButton: SG nil Specifies the widget that is the Cancel button.CwBulletinBoard subclasses, which define aCancel button, set this resource.CwBulletinBoard does not directly provideany behavior for the button. This resourcehas no effect and is only provided forprotocol compatibility with CwForm

defaultButton: SG nil Specifies the widget which is the defaultbutton.CwBulletinBoard subclasses, whichdefine a default button, set this resource.CwBulletinBoard causes this button to beactivated when the return key is pressed.This resource has no effect and is onlyprovided for protocol compatibility withCwForm.

fractionBase: CSG 100 Specifies the denominator used in calculatingthe relative position of a child widget usingXmATTACHPOSITION constraints.

horizontalSpacing: CSG 0 Specifies the offset for right and leftattachments.

labelFontList: CSG nil Defines the font used for label children of thepage. A value of nil specifies that the defaultfont should be used. This resource has noeffect and is only provided for protocolcompatiability with CwForm.

marginHeight: CSG 0 Specifies the minimum spacing in pixelsbetween the top or bottom edge of the pageand any child widget.

marginWidth: CSG 0 Specifies the minimum spacing in pixelsbetween the left or right edge of the pageand any child widget.

pageEnterCallback: C OrderedCollection new Specifies the list of callbacks that is called justbefore a page is to be managed. This happenswhen the receiver is being brought to the topin a parent notebook. The callback reason isXmCRPAGEENTER. Calldata typeisCwAnyCallbackData.

pageLabel: CSG nil Specifies the String to place in the statuslabel. Note: This resource is ignored if thepage is added to an EwWINNotebook.

pageLeaveCallback: C OrderedCollection new Specifies the list of callbacks that is called justbefore a page is to be unmanaged. Thishappens when another page is being broughtto the top in a parent notebook. By settingthe doit field in the callback structure to false,the change to the new page will not takeplace The callback reason isXmCRPAGELEAVE. Calldata typeisCwConfirmationCallbackData.

500 IBM Smalltalk: Programmer’s Reference

Page 515: IBM Smalltalk: Programmer's Reference

Table 103. EwPage resource and callback methods (continued)

resizePolicy: CSG XmRESIZEANY Controls the policy for resizing the page’swidgets. Allowed values are as follows:XmRESIZENONE Fixed size. XmRESIZEANYShrink or grow as needed. XmRESIZEGROWGrow only.

rubberPositioning: CSG false Indicates the default attachment for a child ofthe page. If this resource is set to false, thenthe left and top of the child is by defaultattached to the left and top side of the page.If this resource is set to true, then the child isby default attached to its initial position inthe page.

tabBackgroundColor: CSG nil A CgRGBColor that specifies the color todraw the background of the page’s tab.

tabLabel: CSG nil Specifies the renderable object to draw in thepage’s tab.

tabType: CG XmMAJOR Specifies the type of tab to use for the page.Allowed values are as follows: XmMAJORThese are the primary pages of a notebook.XmMINOR These are essentially children ofthe major page they are added after. Theydisplay only after their parent major page isdisplayed They appear perpendicular to themajor tabs. XmNONE These are major pageswith no tabs. Note: This resource is ignored ifthe page is added to a EwWINNotebook.

textFontList: CSG nil Specifies the font list used for the page’s textchildren. If the buttonFontList resource is notspecified, then this resource is also used forbuttons. If the labelFontList resource is notspecified, then this resource is also used forlabels. This resource has no effect and is onlyprovided for protocol compatibility withCwForm.

verticalSpacing: CSG 0 Specifies the offset for top and bottomattachments.

EwPage also inherits resource and callback methods from EwPage, CwExtendedComposite, CwExtendedWidget, andCwWidget.

Table 104. EwPMNotebook resource and callback methods

backPagePosition: CSG XmBOTTOMRIGHT Specifies where the simulated back pagesappear. Allowed values are as follows:XmBOTTOMRIGHT Back pages are drawnbottom and right. XmTOPRIGHT Back pagesare drawn top and left.

bindingType: CSG XmNONE Determines the style of binding displayedalong the edge of the notebook across majortabs. Allowed values are as follows:XmNONE No binding is drawn. XmSOLID Asolid binding is drawn. XmSPIRAL A spiralpixmap is drawn.

Appendix B. Extended widgets resources and callbacks 501

Page 516: IBM Smalltalk: Programmer's Reference

Table 104. EwPMNotebook resource and callback methods (continued)

foregroundColor: CSG dynamic A CgRGBColor that specifies the foregrounddrawing color. Note: The particular aspects ofthe widget’s appearance that are affected bychanging this resource depend onplatform-specific styles and capabilities andvary from platform to platform.

majorTabHeight: CSG 25 Specifies the height of the notebook’s majortabs in pixels.

majorTabWidth: CSG 50 Specifies the width of the notebook’s majortabs in pixels.

minorTabHeight: CSG 25 Specifies the height of the notebook’s minortabs in pixels.

minorTabWidth: CSG 50 Specifies the width of the notebook’s minortabs in pixels.

orientation: CSG XmHORIZONTAL Specifies on what plane the pages turn. Themajor tabs being opposite the binding.Allowed values are as follows:XmHORIZONTAL Major tabs appear on theright and minor tabs are either on the top orbottom depending on the back page position.XmVERTICAL Major tabs are either on thetop or bottom depending on the back pageposition and minor tabs appear on the right.

pageButtonHeight: CSG 20 Specifies the height of the notebook’s pagebuttons in pixels. A value of 0 means thereare no buttons or page label visible.

pageButtonWidth: CSG 20 Specifies the width of the notebook’s pagebuttons in pixels. A value of 0 means thereare no buttons or page label visible.

EwPMNotebook also inherits resource and callback methods from these classes: EwPMNotebook, EwNotebook,CwExtendedComposite, CwExtendedWidget, and CwWidget.

Table 105. EwScrollable resource and callback methods

EwScrollable does not define any additional resource or callback methods. EwScrollable inherits resource andcallback mehtods from EwScrollable, CwExtendedPrimitive, CwExtendedWidget, and CwWidget.

Table 106. EwSlider resource and callback methods

activeScale: CSG XmTOPORLEFT Specifies which scale is the active scale. Theactive scale indicates the scale to be usedwhen positioning the slider arm. Allowedvalues are as follows: XmTOPORLEFT Top orleft scale, depending on the value of theorientation resource. XmBOTTOMORRIGHTBottom or right scale, depending on the valueof the orientation resource.

bottomOrRightScale-Resolution

CSG 1 Specifies the size of the increments betweenthe minimum and maximum values for thebottom or right scale. For example, aresolution of 2 for a scale with min = 0 andmax = 100 would result in increments 0, 2, 4,6,...,100.

502 IBM Smalltalk: Programmer’s Reference

Page 517: IBM Smalltalk: Programmer's Reference

Table 106. EwSlider resource and callback methods (continued)

bottomOrRightScale-ShaftIncrement:

CSG 1 Specifies the amount to be added to orsubtracted form the current value when theleft mouse button is pressed inside the shaftto the left or right of the slider arm,respectively. The value of this resource mustbe a multiple of thebottomOrRightScaleResolution resource.If theshaft increment is not a multiple of theresolution, it is added to the current value,then rounded to the nearest multiple of theresolution, with the result being a minimummovement of one resolution unit.

bottomOrRightScale-Value:

CSG 0 Specifies the value associated with theslider’s current position along the bottom orright scale, between the minimum andmaximum. If the value is out of range, thecurrent value is set to the current maximumor minimum, whichever is closer. This isequivalent to sending setCurrentValue:notify:with the notify parameter set to true.

bottomOrRightScale-Max:

CSG 0 Specifies the slider’s maximum value for thebottom or right scale. The value of thisresource must be greater than thebottomOrRightScaleMin resource value.

bottomOrRightScale-Min:

CSG 0 Specifies the slider’s minimum value for thebottom or right scale.The value of thisresource must be less than the value of thebottomOrRightScaleMax resource.

buttonStyle: CSG XmBUTTONSNONE Specifies where buttons should be displayedrelative to the shaft. Allowed values are:XmBUTTONSSPLIT One button on either endof the shaft. XmBUTTONSBEGINNING Forvertical sliders, both buttons above shaft; forhorizontal sliders, both buttons to the left ofthe shaft. XmBUTTONSEND For verticalsliders, both buttons below shaft; forhorizontal sliders, both buttons to the right ofthe shaft. XmBUTTONSNONE No buttons.

currentValue: CSG 0 Specifies the value associated with theslider’s current position along the activescale, between the minimum and maximum.

dragCallback: C OrderedCollection new Specifies the list of callbacks that is calledwhen the slider position changes as the armis being dragged. The reason is XmCRDRAG.Calldata type is EwSliderValuesCallbackData

focusCallback: C OrderedCollection new Specifies the list of callbacks that is calledbefore the slider has accepted input focus.The reason is XmCRFOCUS. Calldata type isCwAnyCallbackData.

fontList: CSG dynamic Specifies the font list used for any textwidget.

horizontalMargin: CSG 12 Specifies the number of pixels to be used as amargin between the slider components(scales, shaft, buttons) and the left and rightedges of the widget’s area.

Appendix B. Extended widgets resources and callbacks 503

Page 518: IBM Smalltalk: Programmer's Reference

Table 106. EwSlider resource and callback methods (continued)

losingFocusCallback: C OrderedCollection new Specifies the list of callbacks that is calledbefore the slider loses input focus. The reasonis XmCRLOSINGFOCUS. Calldata type isCwAnyCallbackData.

orientation: CSG XmHORIZONTAL Specifies whether slider should be displayedvertically or horizontally. Allowed values areXmHORIZONTAL and XmVERTICAL.

readOnly: CSG false Specifies whether the slider is being used as aread-only status indicator. If so, the value ofthe ribbonStrip resource is set to true and noslider arm or buttons are displayed.

ribbonStrip: CSG false Specifies whether the area between theminimum and the slider arm should be filled.This is automatically set to true if the valueofthe readOnly resource is set to true.

snapToResolution: CSG true Specifies the current snap policy, whichregulates the positioning of the slider armwhen the mouse button is released afterdragging. The slider’s current value willalways be a multiple of the resolution,regardless of the snap policy. The resourcevalue true means align the slider arm withthe nearest scale value (the nearest multipleof the resolution). The resource value falsemeans do not adjust the position of the sliderarm. The value will still be a factor of theresolution, but the arm might be positionedbetween scale values.

thickness: CSG 16 Specifies the slider shaft thickness in pixels.The size of the slider arm is automaticallyadjusted. Specifying a size of less than 3pixels will result in the value of the resourcebeing set to 3.

topOrLeftScaleMax: CSG 0 Specifies the slider’s maximum value for thetop or left scale.The value of this resourcemust be greater than the value of thetopOrLeftScaleMin resource.

topOrLeftScaleMin: CSG 0 Specifies the slider’s minimum value for thetop or left scale.The value of this resourcemust be less than the value of thetopOrLeftScaleMax resource.

topOrLeftScale-Resolution

CSG 1 Specifies the size of the increments betweenthe minimum and maximum values for thetop or left scale. For example, a resolution of2 for a scale with min = 0 and max = 100would result in increments 0, 2, 4, 6,...,100.

504 IBM Smalltalk: Programmer’s Reference

Page 519: IBM Smalltalk: Programmer's Reference

Table 106. EwSlider resource and callback methods (continued)

topOrLeftScale-ShaftIncrement:

CSG 1 Specifies the amount to be added to orsubtracted form the current value when theleft mouse button is pressed inside the shaftabove or below the slider arm, respectively.The value of this resource must be a multipleof the topOrleftScaleResolution resource.If theshaft increment is not a multiple of theresolution, it is added to the current value,then rounded to the nearest multiple of theresolution, with the result being a minimummovement of one resolution unit.

topOrLeftScaleValue: CSG 0 Specifies the value associated with theslider’s current position along the top or leftscale, between the minimum and maximum.If the value is out of range, the current valueis set to the current maximum or minimum,whichever is closer. This is equivalent tosending setCurrentValue:notify: with thenotify parameter set to true.

valueChangedCallback: C OrderedCollection new Specifies the list of callbacks that is calledwhen the value of the slider has changed.This is called as the result of a button press,arrow key press, or releasing the slider armafter a drag. The reason isXmCRVALUECHANGED. Calldata type isEwSliderValuesCallbackData.

verticalMargin: CSG 12 Specifies the number of pixels to be used as amargin between the slider components(scales, shaft, buttons) and the top andbottom edges of the widget’s area.

EwSlider also inherits resource and callback methods from EwSlider, CwExtendedPrimitive, CwExtendedWidget, andCwWidget.

Table 107. EwSpinButton resource and callback methods

activateCallback: C OrderedCollection new Specifies the list of callbacks that is calledwhen the default action key is pressed. Thecallback reason is XmCRACTIVATE. Calldatatype is CwValueCallbackData.

backgroundColor: CSG dynamic A CgRGBColor that represents thebackground color of the entry field area.

decrementCallback: C OrderedCollection new Specifies the list of callbacks that is calledwhen the spin button value decreases by onestep. This can happen either when the downarrow key is pressed or the down arrowbutton is selected with the mouse. Thecallback reason is XmCRDECREMENT.Calldata type isCwValueChangedCallbackData.

editable CSG true Specifies whether users can edit text in theentry field part of the spin button.

focusCallback: C OrderedCollection new Specifies the list of callbacks that is calledbefore the entry field has accepted inputfocus. The callback reason is XmCRFOCUS.Calldata type is CwAnyCallbackData.

Appendix B. Extended widgets resources and callbacks 505

Page 520: IBM Smalltalk: Programmer's Reference

Table 107. EwSpinButton resource and callback methods (continued)

fontList: CSG dynamic Specifies the font list used for any textwidget.

foregroundColor: CSG dynamic A CgRGBColor that represents thebackground color of the entry field area

increment: CSG 1 Specifies the amount to increase or decrease anumeric spin button when the correspondingarrow is selected. Because button semanticsdesignate whether the increment is added toor subtracted form the current value, allincrement values specified are absolutevalues. If the itemType is XmSBSTRING thisresource is ignored.

incrementCallback: C OrderedCollection new Specifies the list of callbacks that is calledwhen the spin button value increases by onestep. This can happen either when the uparrow key is pressed or the up arrow buttonis selected with the mouse. The callbackreason is XmCRINCREMENT. Calldata typeis CwValueChangedCallbackData.

items: CSG nil A collection of strings that is the list of itemsin a spin button with the itemType resourceset to XmSBSTRING.

itemType: CG XmSBNUMERIC Specifies the type of items in the spin button.Allowed values are XmSBNUMERIC andXmSBSTRING.

losingfocusCallback: C OrderedCollection new Specifies the list of callbacks that is calledbefore the entry field loses input focus. Thecallback reason is XmCRLOSINGFOCUS.Calldata type is CwAnyCallbackData.

maximum: CSG 0 Specifies the spin button’s maximum valuefor spin buttons whith the itemType resourceset to XmSBNUMERIC.

minimum: CSG 0 Specifies the spin button’s minimum valuefor spin buttons whith the itemType resourceset to XmSBNUMERIC.

modifyVerifyCallback: C OrderedCollection new Specifies the list of callbacks that is calledbefore text is deleted form or inserted intothe entry field. The callback reason isXmCRMODIFYINGTEXTVALUE. Calldatatype is CwTextVerifyCallbackData.

value: CSG 0 A String or Integer that represents the currentvalue of the entry field.

valueChangedCallback C OrderedCollection new Specifies the list of callbacks that is calledafter text is deleted form or inserted into theentry field. The callback reason isXmCRVALUECHANGED. Calldata type isCwAnyCallbackData.

wrap: CSG true Specifies whether the spin button shouldcycle or stop upon reaching the end of thecollection for a spin button with an itemTypeof XmSBSTRING, or maximum or minimumvalue for a numeric spin button (itemType isXmSBNUMERIC).

506 IBM Smalltalk: Programmer’s Reference

Page 521: IBM Smalltalk: Programmer's Reference

Table 107. EwSpinButton resource and callback methods (continued)

EwSpinButton also inherits resource and callback methods from EwSpinButton, CwExtendedPrimitive,CwExtendedWidget, and CwWidget.

Table 108. EwTableColumn resource and callback methods

beginEditCallback: C OrderedCollection new Specifies the list of callbacks that is calledwhen an item is about to be edited. Thecallback reason is XmCRBEGINEDIT. Forediting to occur, the application must the setcalldata doit: flag to true. It might alsoreplace the editPolicy in the calldata with acustom edit policy appropriate for the cellbeing edited. Calldata type isEwBeginEditCallbackData.

cellValueCallback: C OrderedCollection new Specifies the list of callbacks that is calledwhen an item’s cell value is needed for thiscolumn. The callback reason isXmCRCELLVALUE. The application musthook this callback and set the calldata valueto the renderable object to appear in the cellspecified in the calldata. Calldata type isEwCellValueCallbackData.

editable: CSG true Specifies whether the cells in this column areeditable. For a cell to be editable, the tablewidget must be editable, the column must beeditable, and the application must hook thebeginEditCallback and set the calldata doitflag to true.

endEditCallback: C OrderedCollection new Specifies the list of callbacks that is calledwhen an item is done being edited. Thecallback reason is XmCRENDEDIT. Thiscallback is activated whenever editing endson a cell or whenever the value changesduring an edit. The application must hookthis callback and use the calldata newValueto set the changed value of the apporpriateapplication objects. Calldata type isEwEndEditCallbackData.

etched: CSG false Specifies whether this column is to be etched.If the table’s visualStyle is XmETCHCELLS,then this resource determines whether allcells in this column are to be drawn asetched. Any other value for the table’svisualStyle causes this resource to be ignored.

heading: CSG nil Any renderable objects (such as a String orCgIcon) that specifies the heading object to bedisplayed at the top of the column. Theheight of the heading row is the maximum ofthe heights of the headings of the columns.

horizontalAlignment: CSG XmALIGNMENT-BEGINNING

Specifies how the cells in this column shouldbe aligned horizontally. Allowed values areXmALIGNMENTBEGINNING,XmALIGNMENTCENTER, andXmALIGNMENTEND.

Appendix B. Extended widgets resources and callbacks 507

Page 522: IBM Smalltalk: Programmer's Reference

Table 108. EwTableColumn resource and callback methods (continued)

horizontalHeading-Alignment:

CSG XmALIGNMENT-BEGINNING

Specifies how the columns heading should bealigned horizontally. Allowed values areXmALIGNMENTBEGINNING,XmALIGNMENTCENTER, andXmALIGNMENTEND.

outerWidth: SG dynamic Specifies the width of the column in pixels.This does include the width of any emphasisor vertical separator.

resizable: CSG false Specifies whether the column is resizable byusers. If true, users can drag the right side ofthe column heading to change the columnwidth.

resizeCallback: C OrderedCollection new Specifies the list of callbacks that is calledwhen the column is resized by users. Thecallback reason is XmCRRESIZE. Calldatatype is CwAnyCallbackData.

showInUse: CSG false Specifies whether in-use emphasis should bedisplayed in the column for each list item.

userData: CSG nil An Object that represents the user data forthe column.

verticalAlignment: CSG XmALIGNMENT-BEGINNING

Specifies how the cells in this column shouldbe aligned vertically. Allowed values areXmALIGNMENTBEGINNING,XmALIGNMENTCENTER, andXmALIGNMENTEND.

verticalSeparator-Thickness:

CSG 1 Specifies the thickness of the line shown tothe right of each cell in the column.

width: CSG 32 Specifies the width of the column in pixels.This does not includes the width of anyemphasis or vertical separator.

EwTableColumn also inherits resource and callback methods from EwTableColumn and Object.

Table 109. EwTableList resource and callback methods

cellBlockSelection-Callback:

C OrderedCollection new Specifies the list of callbacks that is calledwhenever a block of cells is selected in blockselection mode. The reason isXmCRCELLBLOCKSELECT. Calldata type isEwTableListSelectionCallbackData.

cellSingleSelection-Callback:

C OrderedCollection new Specifies the list of callbacks that is calledwhen an item is selected in cell singleselection mode. The reason isXmCRCELLSINGLESELECT. Calldata type isEwTableListSelectionCallbackData.

columnHeading-SelectionCallback:

C OrderedCollection new Specifies the list of callbacks that is calledwhen a column heading, or set of headings,is selected or deselected. The reason isXmCRCOLUMNHEADINGSELECT. Calldatatype is EwColumnHeading-SelectionCallbackData.

columns: CSG #() An Array of EwTableColumns that specifiesthe columns to be used to displayinformation about each item in the table.

508 IBM Smalltalk: Programmer’s Reference

Page 523: IBM Smalltalk: Programmer's Reference

Table 109. EwTableList resource and callback methods (continued)

editable: CSG false Specifies whether the cells in the table areeditable. For a cell to be editable, the tablewidget must be editable, the column must beeditable, and the application must hook thebeginEditCallback and set the calldata doitflag to true.

headingSeparator-Thickness:

CSG 1 Specifies the thickness of the horizontal lineseparating the column headings form the restof the table.

items: CSG OrderedCollection new A collection that represents the items in thelist.

itemWidth G 1 Specifies the width in pixels of items in thelist. The value of this resource will be set tothe sum of the widths of the columns plussome number of pixels per column foremphasis and separator. This resource is usedto set the scrolling interval for the horizontalscroll bar. It is ignored if the scrollHorizontalresource is false.

lockedColumns: CSG 0 Specifies the number of columns to be lockedon the left side of the table. For instance, avalue of 2 means that the first 2 columns inthe table is locked. A column can be lockedonly if its preceding column is also locked.When scrolling, the locked columns remainfixed on the left side and all other columnsscroll under the locked columns. This valuemust be no greater than the total number ofcolumns.

rowSeparators: CSG false Specifies whether the rows are separated by ahorizontal line.

selectableColumns: CSG false Specifies whether users might select columnsby clicking on their headings.

selectedCell G nil Represents a Point whose x component is theindex of the column of the selected cell andwhose y component is the index of the item(row) of the selected cell. If nil, then no cell isselected. Note: This resource is only relevantif the selection policy isXmCELLSINGLESELECT.

selectedCells G nil Represents a Collection of Points, each ofwhose x component is the index of thecolumn of the selected cell and whose ycomponent is the index of the item (row) ofthe selected cell. If empty, then no cell isselected. Note: This resource is only relevantif the selection policy isXmCELLSINGLESELECT orXmCELLEXTENDEDSELECT.

selectedColumns: CSG #() An Array of EwTableColumn that specifiesthe currently selected columns. The columnsgiven must all be members of the columnsresource.

Appendix B. Extended widgets resources and callbacks 509

Page 524: IBM Smalltalk: Programmer's Reference

Table 109. EwTableList resource and callback methods (continued)

selectionPolicy: CSG XmBROWSESELECT Defines the interpretation of the selectionaction. Allowed values are as follows:XmSINGLESELECT Allows only singleselections. XmMULTIPLESELECT Allowsmultiple selections. XmEXTENDEDSELECTAllows extended selections.XmBROWSESELECT Allows drag andbrowse functionality XmREADONLYSELECTAllows navigation, but no selection orcallbacks. XmCELLSINGLESELECT Allowssingle selection of cells. If the widget and thecolumn are editable, then selecting a cellcauses it to be edited.

separatorsToExtremes: CSG false Specifies whether row and column separatorsare to be extended to the extreme right andbottom edges of the table.

visualStyle: CSG XmFLAT Defines how cells are displayed. Allowedvalues are as follows: XmFLAT Looks like alist box. XmETCHROWS Each row is etched.XmETCHCELLS Each cell in an etchedcolumn is individually etched. Note: Settingthe visual style after the widget is displayedcauses the background color to be set to theOS defaults for the visual style given. Thismeans that to override this default, youmight need to set the background coloragain.

EwTableList also inherits resource and callback methods from EwTableList, EwContainerList, EwLinearList, EwList,EwScrollable, CwExtendedPrimitive, CwExtendedWidget, and CwWidget.

Table 110. EwTableTree resource and callback methods

childrenCallback: C OrderedCollection new Specifies the list of callbacks that iscalled when an item’s list of children isneeded. The callback reason isXmCRCHILDREN. The application mustset the calldata children to the collectionof children objects of the item in calldataitem. Calldata type isEwChildrenCallbackData.

expandCollapseCallback: C OrderedCollection new Specifies the list of callbacks that iscalled when an item is expanded orcollapsed. The callback reason isXmCREXPAND or XmCRCOLLAPSE.Calldata type is EwListCallbackData.

hierarchyPolicy: CSG EwHierarchyPolicy new An instance of EwHierarchyPolicy (or asubclass) that defines how to display andmanage the hierarchy.

itemCount G 0 Specifies the total number of items. Thisnumber might not match the itemsresource because this number is the sizeof the expanded hierarchy. It isautomatically updated by the listwhenever an element is added to ordeleted from the list.

510 IBM Smalltalk: Programmer’s Reference

|

Page 525: IBM Smalltalk: Programmer's Reference

Table 110. EwTableTree resource and callback methods (continued)

items: CSG OrderedCollection new A collection that represents hierarchyroot items in the list.

EwTableTree also inherits resource and callback methods from EwTableTree, EwTableList, EwContainerList, EwLinearList,EwList, EwScrollable, CwExtendedPrimitive, CwExtendedWidget, and CwWidget.

Table 111. EwWINNotebook resource and callback methods

tabHeight: CG 25 The height of the page tabs in pixels.

tabsPerRow: CSG 3 The number of pages tables displayed in asingle row.

EwWINNotebook also inherits resource and callback methods from EwWINNotebook, EwNotebook,CwExtendedComposite, CwExtendedWidget, and CwWidget.

Appendix B. Extended widgets resources and callbacks 511

Page 526: IBM Smalltalk: Programmer's Reference

512 IBM Smalltalk: Programmer’s Reference

Page 527: IBM Smalltalk: Programmer's Reference

Appendix C. Drag and drop resources and callbacks

This section provides a detailed listing of the resources and callbacks for each classin the Drag and Drop subsystem. Note that only the set resource methods areshown in each table, unless a resource only has a get method. Get methods havethe same name without the colon. Create/Set/Get (CSG) access designation anddefault value are listed for each resource and callback.

The example Table 1. CwArrowButton resource and callback methods in “Appendix A.Widget resources and callbacks” on page 469 shows how to use the tables in thisappendix.

Table 112. EwDragAndDropAdapter resource and callback methods

dragCancelCallback: C OrderedCollection new Specifies a list of callbacks that is called whenthe a drag has been canceled while thereceiver’s widget is either the source or targetof a drag. The reason isXmCRDRAGCANCEL. Calldata type is asfollows: EwSourceCancelCallbackData for acancel when the widget is the source.EwTargetCancelCallbackData for a cancelwhen the widget is the target.

EwDragAndDropAdapter also inherits resource and callback methods from EwDragAndDropAdapter and Object.

Table 113. EwSourceAdapter resource and callback methods

dragChangeCallback: C OrderedCollection new Specifies a list of callbacks that is called whenthe operation or target has changed during adrag from the receiver’s widget. The reason isXmCRDRAGCHANGE. Calldata type isEwDragChangeCallbackData.

dragCompleteCallback: C OrderedCollection new Specifies a list of callbacks that is called whena drag of items from the receiver’s widgethas completed; that is, the items have beendropped elsewhere. The callback reason isXmCRDRAGCOMPLETE. Calldata type isEwDragCompleteCallbackData.

dragStartCallback: C OrderedCollection new Specifies a list of callbacks that is called whena drag and drop is started in the receiver’swidget. The callback reason isXmCRDRAGSTART. Calldata type isEwDragStartCallbackData.

EwSourceAdapter also inherits resource and callback methods from EwSourceAdapter, EwDragAndDropAdapter andObject.

Table 114. EwTargetAdapter resource and callback methods

dragLeaveCallback: C OrderedCollection new Specifies a list of callbacks that is called whenitems that were being dragged over thereceiver’s widget are dragged away from thereceiver’s widget. The callback reason isXmCRDRAGLEAVE. Calldata type isEwDragLeaveCallbackData.

© Copyright IBM Corp. 1994, 2000 513

Page 528: IBM Smalltalk: Programmer's Reference

Table 114. EwTargetAdapter resource and callback methods (continued)

dragOverCallback: C OrderedCollection new Specifies a list of callbacks that is called whenitems are being dragged over the receiver’swidget. The callback reason isXmCRDRAGOVER. Calldata type isEwDragOverCallbackData.

dropCallback: C OrderedCollection new Specifies a list of callbacks that is called whenitems are dropped on the receiver’s widget.The callback reason is XmCRDROP. Calldatatype isEwDropCallbackData.

EwTargetAdapter also inherits resource and callback methods from EwTargetAdapter, EwDragAndDropAdapter andObject.

EwTargetAdapter also inherits resource and callback methods from EwTargetAdapter(Table 114 on page 513), EwDragAndDropAdapter (Table 112 on page 513) and Object.

514 IBM Smalltalk: Programmer’s Reference

Page 529: IBM Smalltalk: Programmer's Reference

Appendix D. Common graphics platform differences

Parts of the Common Graphics subsystem can behave differently depending onconstraints of the platform (hardware, operating system, and window system). Forexample, Windows provides only four dashed-line styles and does not supportuser-defined dash styles. Where possible, Common Graphics features are mappedto the closest available features on the platform.

The tables below identify the platform constraints of the Common Graphicssubsystem. Blank cells indicate that the corresponding item is fully supported forthe indicated platform

Table 115. Constraints on cursors (CgCursor)

Item DOS/Windows OS/2 PM X/MOTIF

Color cursors Not supported Not supported

Table 116. Constraints on device independent images (CgDeviceIndependentImage)

Item DOS/Windows OS/2 PM X/MOTIF

Display of 1-bit images

Display of 4-bit images

Display of 8-bit images

Display of 16-bit images Not supported Not supported Not supported

Display of 24-bit images Not supported

Display of 32-bit images Not supported Not supported Not supported

Table 117. Constraints on graphics context attributes (CgGC)

Item DOS/Windows OS/2 PM X/MOTIF

arcMode

background

capStyle CapRound only

clipMask

dashes Closest match done to 4predefined dash lists: #(44), #(24 8), #(12 8 4 8), #(124 4 4 4 4)

Closest match done to 7predefined dash lists: #(11), #(4 4), #(8 8), #(12 8 4 8),#(12 8), #(4 4 4 20), #(12 4 44 4 4)

fillRule

fillStyle Tiles/stipples notsupported by thick lines.FillStippled draws the sameas FillOpaqueStippled forfilled arcs.

font

foreground

function

joinStyle JoinRound only

© Copyright IBM Corp. 1994, 2000 515

Page 530: IBM Smalltalk: Programmer's Reference

Table 117. Constraints on graphics context attributes (CgGC) (continued)

Item DOS/Windows OS/2 PM X/MOTIF

lineStyle Dashes not supported bythick lines. Lines can haveeither dashes or stipple/tilepattern, but not both. Fillstyle has priority. Color notsupported byLineOnOffDash.

Dashes not supported bythick lines. Lines can haveeither dashes or stipple/tilepattern, but not both. Fillstyle has priority.LineDoubleDash notsupported.

lineWidth

stipple No limit for filledrectangles. 8x8 only forother graphics primitives.

Foreground andbackground colorsunsupported for stippleslarger that 8x8.

subwindowMode

tile No limit for filledrectangles. 8x8 only forother graphics primitives.

Table 118. Constraints on icons (CgIcon)

Item DOS/Windows OS/2 PM X/MOTIF

Icon size limit 32x32 32x32 (VGA) and 40x40(8514/A, XGA)

40x40 (8514/A, XGA)

Table 119. Constraints on indexed palettes (CgIndexedPalette)

Item DOS/Windows OS/2 PM X/MOTIF

Animating entries Only 256-color devices Not supported Not supported

516 IBM Smalltalk: Programmer’s Reference

Page 531: IBM Smalltalk: Programmer's Reference

Appendix E. Common widgets platform differences

Parts of the Common Widgets subsystem can behave differently depending onconstraints of the platform (hardware, operating system, and window system). Forexample, Windows supports only one alignment for text in button widgets. Wherepossible, Common Widgets features are mapped to the closest features available onthe platform.

The tables below identify the platform constraints of the Common Widgetssubsystem. Blank cells indicate that the corresponding item is fully supported forthe indicated platform.

Table 120. General constraints

Item DOS/Windows OS/2 PM X/MOTIF

Border width The borderWidth resourcecan only be 0 or 1 pixels.

The borderWidth resourcecan only be 0 or 1 pixels.

Background andforeground color

Only solid colors aresupported. Colors are notdithered. Limited to the 20system colors.

Table 121. Constraints on arrow button widgets. (CwArrowButton)

Item DOS/Windows OS/2 PM X/MOTIF

Sizing Displays the message‘Arrow too big’ when thewidget is grown such thatthe bitmap that is used todraw the arrow becomeslarger than 64K. This doesnot happen on Windows95.

Border width The borderWidth resource isignored.

Table 122. Constraints on button and label widgets. (CwLabel, CwPushButton, CwToggleButton, CwCascadeButton,CwDrawnButton)

Item DOS/Windows OS/2 PM X/MOTIF

Alignment The alignment resource isignored for CwPushButtonand CwToggleButton. Thelabel is placed by theoperating system.

The alignment resource isignored for CwPushButtonand CwToggleButton. Thelabel is placed by theoperating system.

Margins The following resourcesaffect only the total widthand height of the widget,not the positioning of thelabel or pixmap inside thewidget: marginBottom,marginHeight, marginLeft,marginRight, marginTop,marginWidth.

The following resourcesaffect only the total widthand height of the widget,not the positioning of thelabel or pixmap inside thewidget: marginBottom,marginHeight, marginLeft,marginRight, marginTop,marginWidth.

© Copyright IBM Corp. 1994, 2000 517

Page 532: IBM Smalltalk: Programmer's Reference

Table 122. Constraints on button and label widgets (continued). (CwLabel, CwPushButton, CwToggleButton,CwCascadeButton, CwDrawnButton)

Item DOS/Windows OS/2 PM X/MOTIF

Default shadow width The showAsDefault resourcecan only be 0 or 1.

The showAsDefault resourcecan only be 0 or 1.

Border width The borderWidth resource isignored.

As menu items The following are notsupported: backgroundColor,foregroundColor, tabtraversal and focus control(setInputFocus,navigationType, traverseOn).Geometry requests and thegeometry values areundefined. The followingmethods do nothing:stacking order requests(bringToFront), eventhandlers (even though theycan be hooked),deferRedraw:, andupdateWidget.

The following are notsupported: backgroundColor,foregroundColor, tabtraversal and focus control(setInputFocus,navigationType, traverseOn).Geometry requests and thegeometry values areundefined. The followingmethods do nothing:stacking order requests(bringToFront), eventhandlers (even though theycan be hooked),deferRedraw:, andupdateWidget.

Color Cannot set backgroundColoror foregroundColor.

Focus A CwToggleButton withindicatorTypeXmONEOFMANY forcesset to true when it takesfocus.

Table 123. Constraints on combo-box widgets. (CwComboBox)

Item DOS/Windows OS/2 PM X/MOTIF

Event handlers Event handlers can behooked on the combo-boxwidget but not on thechildren that implement thecombo box.

Event handlers can behooked on the combo-boxwidget but not on thechildren that implement thecombo box.

Editing When the comboBoxTyperesource is XmSIMPLE, thecombo box is alwayseditable. The editableresource has no effect.

When the comboBoxTyperesource is XmSIMPLE, thecombo box is alwayseditable. The editableresource has no effect.

Default selection When the comboBoxTyperesource isXmDROPDOWN and thereis no initial string setting,the first item in the combobox is selected when thecombo box is dropped.

518 IBM Smalltalk: Programmer’s Reference

Page 533: IBM Smalltalk: Programmer's Reference

Table 124. Constraints on list widgets. (CwList)

Item DOS/Windows OS/2 PM X/MOTIF

Selection policy XmSINGLESELECTbehaves the same asXmBROWSESELECT.

XmSINGLESELECTbehaves the same asXmBROWSESELECT.

Size limit There is a limit on thenumber of list items thatthe list will display.

There is a limit on thenumber of list items thatthe list will display.

Automatic scrolling Positioning the list (settingthe top and bottom item)may not actually scroll thelist. This is because onlyone blank line is allowed atthe bottom of the list and,therefore, depending on thenumber of items, the heightof the list, and the desiredposition, the list may notscroll.

Positioning the list (settingthe top and bottom item)may not actually scroll thelist. This is because onlyone blank line is allowed atthe bottom of the list and,therefore, depending on thenumber of items, the heightof the list, and the desiredposition, the list may notscroll.

Scroll bars When created normally (notas a scrolled list), no scrollbars appear.

When created as a scrolledlist, the vertical scroll bar isvisible only when required.

The horizontal scroll bar isvisible when thescrollHorizontal resource istrue and the list contains anitem that is wider than thewidth of the list.

When created normally (notas a scrolled list), a verticalscroll bar appears.

When created as a scrolledlist, the vertical scroll bar isalways visible.

The horizontal scroll bar isvisible when thescrollHorizontal resource istrue.

Border width The widget is alwaysdisplayed with a 1-pixelborder.

Table 125. Constraints on main window widgets. (CwMainWindow)

Item DOS/Windows OS/2 PM X/MOTIF

Organization Must be created as thechild of a shell.

Must be created as thechild of a shell.

Appendix E. Common widgets platform differences 519

Page 534: IBM Smalltalk: Programmer's Reference

Table 125. Constraints on main window widgets (continued). (CwMainWindow)

Item DOS/Windows OS/2 PM X/MOTIF

Scroll bar limitations Scroll bar children have thefollowing limitations: thehelp callback is ignored, tabtraversal and focus control(setInputFocus,navigationType, traverseOn)are not supported,geometry requests areignored, and the initialgeometry values areundefined. The followingmethods do nothing:stacking order requests(bringToFront), eventhandlers (even though theycan be hooked),deferRedraw:, andupdateWidget.

Scroll bar children have thefollowing limitations: thehelp callback is ignored, tabtraversal and focus control(setInputFocus,navigationType, traverseOn)are not supported,geometry requests areignored, and the initialgeometry values areundefined. The followingmethods do nothing:stacking order requests(bringToFront), eventhandlers (even though theycan be hooked),deferRedraw:, andupdateWidget.

Table 126. Constraints on menus and menu bar. (CwRowColumn with rowColumnType of XmMENUBAR,XmMENUPULLDOWN, or XmMENUPOPUP)

Item DOS/Windows OS/2 PM X/MOTIF

Types of child widgets Only CwLabel,CwToggleButton,CwSeparator, orCwCascadeButton can beadded.

Only CwLabel,CwToggleButton,CwSeparator, orCwCascadeButton can beadded.

Help callback Not supported Not supported

Background color Not supported Not supported

Tab traversal and focuscontrol (setInputFocus:,interceptEvents:, grabPointer:,ungrabPointer:,navigationType, traverseOn)

Not supported Not supported

Geometry requests Geometry requests areignored, and the initialgeometry values areundefined.

Geometry requests areignored, and the initialgeometry values areundefined.

Stacking order Stacking order requests(bringToFront) do nothing.

Stacking order requests(bringToFront) do nothing.

Event handlers Can be hooked but donothing.

Can be hooked but donothing.

Updating widgets The updateWidget methoddoes nothing.

The updateWidget methoddoes nothing.

Ignored resources The following resources areignored: adjustLast,borderWidth, entryAlignment,entryBorder, marginHeight,marginWidth, numColumns,orientation, packing, spacing.

The following resources areignored: adjustLast,borderWidth, entryAlignment,entryBorder, marginHeight,marginWidth, numColumns,orientation, packing, spacing.

520 IBM Smalltalk: Programmer’s Reference

Page 535: IBM Smalltalk: Programmer's Reference

Table 126. Constraints on menus and menu bar (continued). (CwRowColumn with rowColumnType ofXmMENUBAR, XmMENUPULLDOWN, or XmMENUPOPUP)

Item DOS/Windows OS/2 PM X/MOTIF

Accelerator text withpixmap menu items

When a child has alabelType of XmPIXMAP, itsacceleratorText is not shown.

When a child has alabelType of XmPIXMAP, itsacceleratorText is not shown.

Drawn buttons CwDrawnButton childrenare not supported.

CwDrawnButton childrenare not supported.

Separators The separatorType,orientation, and marginresources are ignored forCwSeparator children.

The separatorType,orientation, and marginresources are ignored forCwSeparator children.

Table 127. Constraints on menu bar. (CwRowColumn with rowColumnType of XmMENUBAR)

Item DOS/Windows OS/2 PM X/MOTIF

Unmapping Unmapping the widget hasthe same visual effect asunmanaging.

Unmapping the widget hasthe same visual effect asunmanaging.

Parent widget Can only be created as achild of a CwMainWindow.

Can only be created as achild of a CwMainWindow.

Can be created as a child ofany composite or shellwidget, but is usually achild of a CwMainWindow.

Table 128. Constraints on menu. (CwRowColumn with rowColumnType of XmMENUPULLDOWN orXmMENUPOPUP)

Item DOS/Windows OS/2 PM X/MOTIF

Redrawing The redraw andredraw:y:width:height:methods do nothing.

The redraw andredraw:y:width:height:methods do nothing.

Table 129. Constraints on scale widget. (CwScale)

Item DOS/Windows OS/2 PM X/MOTIF

Event handlers Event handlers can behooked on the scale widgetbut not on the children thatimplement the scale.

Event handlers can behooked on the scale widgetbut not on the children thatimplement the scale.

Table 130. Constraints on scrolled bar widget. (CwScrollBar)

Item DOS/Windows OS/2 PM X/MOTIF

Border width Ignored Ignored

Table 131. Constraints on scrolled window widget. (CwScrolledWindow)

Item DOS/Windows OS/2 PM X/MOTIF

Organization The work area must be achild of the scrolledwindow.

The work area must be achild of the scrolledwindow.

A CwDrawingArea isinserted between thescrolled window and thework area when scrollingpolicy is XmAUTOMATIC.

Appendix E. Common widgets platform differences 521

Page 536: IBM Smalltalk: Programmer's Reference

Table 131. Constraints on scrolled window widget (continued). (CwScrolledWindow)

Item DOS/Windows OS/2 PM X/MOTIF

Scroll bar limitations Scroll bar children have thefollowing limitations: thehelp callback is ignored, tabtraversal and focus control(setInputFocus,navigationType, traverseOn)are not supported,geometry requests areignored and the initialgeometry values areundefined. The followingmethods do nothing:stacking order requests(bringToFront), eventhandlers (even though theycan be hooked),deferRedraw:, andupdateWidget.

Scroll bar children have thefollowing limitations: thehelp callback is ignored, tabtraversal and focus control(setInputFocus,navigationType, traverseOn)are not supported,geometry requests areignored and the initialgeometry values areundefined. The followingmethods do nothing:stacking order requests(bringToFront), eventhandlers (even though theycan be hooked),deferRedraw:, andupdateWidget.

Table 132. Constraints on text widget. (CwText)

Item DOS/Windows OS/2 PM X/MOTIF

Highlight vs selection Highlight and selection are thesame. It is not possible to set thehighlight without affecting theselection.

Highlight and selection are thesame. It is not possible to setthe highlight without affectingthe selection.

Highlight appearance XmHIGHLIGHTSELECTED andXmHIGHLIGHT-SECONDARYSELECTED bothappear as inverse text.

XmHIGHLIGHTSELECTEDand XmHIGHLIGHT-SECONDARYSELECTED bothappear as inverse text.

Insertion vs selection Insertion and selection are thesame. It is not possible to movethe insertion point withoutaffecting the selection.

Insertion and selection are thesame. It is not possible tomove the insertion pointwithout affecting the selection.

Insertion point The insertion point(cursorPosition,getInsertionPosition) is alwaysanswered as the beginning of theselection if the editMode isXmSINGLELINEEDIT.

The insertion point(cursorPosition,getInsertionPosition) is alwaysanswered as the beginning ofthe selection if the editMode isXmSINGLELINEEDIT.

Visual appearance The selection is hidden whenthe widget loses focus.

Background andforeground color

Only solid background colorsare supported.

Table 133. Constraints on top-level shell and dialog shell. (CwTopLevelShell, CwDialogShell)

Item DOS/Windows OS/2 PM X/MOTIF

Window titles Centered Left Centered

522 IBM Smalltalk: Programmer’s Reference

Page 537: IBM Smalltalk: Programmer's Reference

Table 133. Constraints on top-level shell and dialog shell (continued). (CwTopLevelShell, CwDialogShell)

Item DOS/Windows OS/2 PM X/MOTIF

Behavior of mwmDecorationsresource1. A title bar is always included

(MWMDECORTITLE).2. If MWMDECORMAXIMIZE

or MWMDECORMINIMIZEis set, MWMDECORRESIZEHis added.

3. If a menu bar is added to ashell that hasMWMDECORBORDER,Windows does not paint theshell properly.

No title bar is includedunlessMWMDECORTITLE isset.

A title bar is included if anyone of the following is set:MWMDECORTITLE,MWMDECORMENU,MWMDECORMINIMIZE, orMWMDECORMAXIMIZE.

Appendix E. Common widgets platform differences 523

Page 538: IBM Smalltalk: Programmer's Reference

524 IBM Smalltalk: Programmer’s Reference

Page 539: IBM Smalltalk: Programmer's Reference

Index

Aaccelerator keys 171accepting drops 219adapters 263ambient-properties 462application-drawn button widgets 177application shell widgets 158arcs

drawing 92filled 93

Array 8, 10Association 14asynchronous

callouts 298messages (interrupts) 327

attributesprint job 276

BbackgroundColor 213Bag 8, 10, 12Behavior class 34bitmaps 106, 109Block 25, 48, 49Boolean 7building

DDE clients 357DDE servers 344

button tools 260button widgets 171

application-drawn 177cascade- 178greying out 178iconic- 176push- 172radio- 174toggle- 173

ButtonMenuMask 183ByteArray 8, 10

CC language

Common Graphics conversionfrom 79

Common Widgets conversionfrom 135

IBM C Set/2 compiler 333interfacing to 285programming model 286sample callback for OS/2 330supported parameter types 288writing user primitives 333

callbacks 146activate 146, 150, 172adding 277DDE events 362destroy 146, 164expose 164

callbacks 146 (continued)extended widgets 203focus 158, 163input 164methods 153notebooks and pages 250resize 164selection 186, 189simple 180valueChanged 163, 174

canceling a drag 269cascade-button widgets 171, 178CFS 1, 53CfsConstants 54CfsDirectoryDescriptor 54, 55, 58CfsDirectoryEntry 54, 59CfsError 54, 71

platform-specific errors 76testing for specific errors 73

CfsFileDescriptor 54, 55, 64, 67, 68, 76CfsFileStream 61, 67CfsReadFileStream 61CfsReadWriteFileStream 61CfsStat 54, 74CfsVolumeInfo 54CfsWriteFileStream 61CG 2, 79CgArc 82, 133CgCharStruct 82, 93, 99, 133CgConstants 83CgCursor 133CgCursors

constraints on cursors 515CgDeviceIndependentImage 120, 133CgDirectPalette 115, 120, 122, 133CgDisplay 81

cursors 103default object 81fonts 93

CgDrawable 81CgFileFormat 127, 131CgFont 93, 98, 133

cursors 103freeing 102loading 98

CgFontProp 82, 93, 133CgFontStruct 93, 98, 133

assigning to graphics context 101loading 98methods 99unloading 102

CgGC 82, 133default object 82fonts 93

CgGCValues 102, 133using 85

CgIcon 124, 134CgIconFileFormat 127CgID 82CgImageFileFormat 127CgIndexedPalette 115, 133

CGIndexedPaletteconstraints 515

CgLogicalFontDescription 82, 93, 98CgPalette 115CgPCXFileFormat 127CgPixmap 82, 106, 119, 133

cursors 103CgPMBMPFileFormat 127CgPMICOFileFormat 127CgRegion 82CgRGBColor 113, 133, 213CgScreen 81

colors 114default object 81icons 125, 126

CgSegment 82, 133drawing with 90

CgTextItem 93, 133drawing with 101

CgTIFFFileFormat 127CgVisual 82CgWinBMPFileFormat 127CgWindow 81, 82CgWinICOFileFormat 127Character 14Characters

double-byte 14check-box widgets 175child 135circles

drawing 92filled 93

circular constraint error 168Class class 36class hierarchies

Common Graphics 82Common Widgets 135, 137Extended Widgets 233

classescore Common Graphics 80dynamic data exchange 342seldom-used and abstract classes 82

CLDT 1, 5CldtConstants 15client requests, handling 351CLIM 1, 33clipboard uses 213coldlink events 356coldlinking items 361Collection 8

common protocols 10colors 113

color-specification string 114looking up values 114of widgets 213setting background in GC 88setting foreground in GC 88specifying by name 113specifying by RGB 113

combo-box widgets 189

© Copyright IBM Corp. 1994, 2000 525

Page 540: IBM Smalltalk: Programmer's Reference

commandsexecuting at a server 362

Common File System 53, 58classes in 54, 61constants 54error handling 71file streams 61filenames and paths 54files 64line delimiter constants 64locking 68managing files and directories 55mixing streams and file

descriptors 67obtaining volume information 57overview 1, 53path separators 55platform-specific error handling 76platform-specific operations 76root directories 55share modes 70testing file properties 74

Common File System, line delimiterconstants 64

Common Graphics 79, 82abstract classes 82class hierarchy 80constants 83drawing process overview 83frequently used classes 80image support 112overview 2platform differences 515printing with 279seldom-used classes 82Xlib compatibility 79, 112

Common Language Data Types 5Boolean classes 7collection classes 8collection protocols 9graphical classes 20magnitude classes 13object behavior 6overview 1, 5stream classes 22support classes 24

Common Language Implementationbehavior messages 34class messages 36CompiledMethod 42compiling and evaluating code 40creating new classes 38EmSystemConfiguration 42extended messages 39metaclass messages 38overview 1, 33

Common Printingclasses 273complete example 280definition 273overview 2, 273

Common Process Modeland Delay 47block evaluation methods 48block methods 49creating processes 45Delay methods 50

Common Process Model (continued)ending processes 46overview 1, 45process methods 49process priorities 46ProcessorScheduler methods 50resuming processes 46Semaphore 47Semaphore methods 51suspending processes 46synchronization 47

common resources 235Common Widgets 82

class hierarchy 135clipboard uses 213constants 144constraints 517drag and drop 215

classes 217convert proc 224drop proc 221drop site widgets 219transfer proc 225

OSF/Motif compatibility 135overview 2, 135platform differences 517timer proc 230work proc 230

CompiledMethod 42Compiler 40CompilerError 40composite widgets 136configuring systems 269constants

character 15file-system 54graphics constants 83platform constants 106widget constants 144

constraints 515, 517convenience methods

graphics contexts 88widget 148, 150

convert proc 224converting Smalltalk objects to a

ByteArray 372copying files 56CP 2, 273CPM 1, 45creating

object verb menu 451OLE Automation Objects 458OLE clients 444OLE main window 443tools 259widgets 148

Creation convenience methods 234cursors

color 105for platform 106from glyphs 103, 104from pixmaps 103, 105overview and process 103predefined 104

CW 2, 135CwAccelerator 171CwArrowButton 136

CwArrowButton 136 (continued)constraints 517methods 469

CwBasicWidget 136methods 469

CwBulletinBoard 190, 197methods 469

CwCascadeButton 136, 171constraints 517methods 470

CwComboBox 136, 189constraints 518methods 471

CwComposite 136methods 472

CwCompositeBox 190methods 472

CwConstants 144CwDialogShell 158, 191, 193, 196

constraints 522methods 473

CwDragContext 218CwDrawingArea 164

methods 473CwDrawnButton 136, 171

constraints 517methods 473

CwDropSite 219CwDropTransfer 223CwExtendedComposite

methods 491CwExtendedPrimitive

methods 491CwFileSelectionPrompter 197CwForm 197, 474CwFrame

methods 474CwLabel 136, 171

constraints 517methods 474

CwList 136, 185constraints 519methods 476

CwMainWindow 161constraints 519methods 477

CwMessageBox 191, 196methods 477

CwMessagePrompter 197CwOverrideShell 158

methods 477CwPrimitive 136

methods 477CwPrinterShell

resources and conveniencemethods 279

CwPushButton 136, 142, 146, 171constraints 517methods 478

CwRowColumn 169, 174, 175, 178constraints 520methods 478

CwScale 481constraints 521

CwScrollBar 136constraints 521methods 481

526 IBM Smalltalk: Programmer’s Reference

Page 541: IBM Smalltalk: Programmer's Reference

CwScrolledWindow 160constraints 521methods 483

CwSelectionBox 193, 197methods 483

CwSeparatormethods 484

CwShell 136methods 484

CwText 136, 162constraints 522methods 485

CwTextPrompter 197CwToggleButton 136, 171, 211, 486

constraints 517CwTopLevelShell 138, 158

constraints 522methods 487

CwTransientShellmethods 487

CwWidget 82, 136methods 487

CwWMShellmethods 489

Ddashes

GC convenience method 88data

requesting 360Date 16DBString 8, 10DD 2DDE 339DdeCallbackData class 343DdeClass

public instance methods 367DdeClient

discussion 359protocols 371public instance methods 369

DdeClient class 342DdeServer

protocols 371public instance methods 368

DdeServer class 343DdeServerManager

discussion 352public class methods 364public instance methods 364

DdeServerManager class 343decorations

window 159delay 228Delay 45, 47, 50device independent images

constraints 515dialogs 158, 190

bulletin board 197convenience methods 196error 196form 197information 196message 191, 196modal 191prompt 197

dialogs 158, 190 (continued)question 196selection 197warning 196working 196

Dictionary 8, 10direct editing

cell values 245direct editing of labels 239DirectedMessage 25directories

closing 61copying 56creating 55current working directory 55managing 55opening 58path 57reading 59removing 55renaming 56searching 58Startup 57

disconnecting 372DLL 124double-byte characters 9, 14double-click

drawing area widget 166drag and drop

adapters 263callbacks 513objects 217overview 2platform-integrated 215pluggable 263resources 513sequence of events 264target types 216

drag proc 220drag source widget 217drawing

arcs 92circles 92drawing process 83filled arcs 92filled polygons 92filled rectangles 91in color pixmaps 119lines 90pie slices with arcs 93points 90polygons 92rectangles 91setting state in GC 88strings 101text 101using palettes 118with color 117with fonts 100with widgets 82, 164, 177

drawn-button widgets 171drawn list 236drop proc 221drop site widgets 219dropping on a target 268dynamic data exchange 339

dynamic data exchange 339 (continued)building

DDE clients 357servers 344

callbacks 362classes 342concepts and definitions 339formats of transferred data 362platform-specific support 374test cases 372

Eediting

cell values 245labels 239policies 246

EmSystemConfiguration 42entry points 294errors

circular constraint errors 168Common File System

CfsError 54Common Graphics image files 127non-homogeneous 174

EsEntryPoint 294EsWindowSystemStartUp 226event handling 146, 154

event masks 154examples 146, 157, 166menu-button event 183

event polling 226events

coldlink 356request 356run and poke 357termination 357warmlink and hotlink 355

EW 2, 233EwConstants pool dictionary 233EwContainerList

methods 492EwDragAndDropAdapter

methods 513EwDrawnList

methods 493EwFlowedIconList

methods 494EwGroupTool 261EwIconArea

methods 494EwIconList

methods 496EwIconTree

methods 497EwLabelTool 260EwLinearList

methods 497EwList

methods 498EwNotebook

methods 499EwPage

methods 500EwPMNotebook

methods 501EwProgressBarTool 260

Index 527

Page 542: IBM Smalltalk: Programmer's Reference

EwPushButtonTool 260EwScrollable

methods 502EwSeparatorTool 260EwSimpleGroupTool 262EwSlider

methods 502EwSourceAdapter

methods 513EwSpinButton

methods 505EwTableColumn

methods 507EwTableList

methods 508EwTableTree

methods 510EwTargetAdapter

methods 513EwToggleButtonTool 260EwWINNotebook

methods 511ExAll 25ExceptionalEvent 25, 26

collections 28exceptions

completion-block 29creating 25examples 30handling 25, 26signaling 26

Extended class 39Extended list widgets 234extended widgets 201, 233

callbacks 203, 491class hierarchy 233examples 203initialization 202overview 2resources 202, 491using 203, 206, 211

External language interface 288

Ffile formats 126file streams

classes 61closing 61line delimiters 63locking 68of bytes 63of characters 63opening 61using access modes and flags 67with file descriptors 67writing 24

fileschanging offset 66closing 65copying 56deleting 56directory path case 57error handling 71existence 73, 74file streams 61flush 67

files (continued)locking 68managing 55name length 57names 57opening 64opening using share modes 71path 55platform-specific calls 76portable names 54properties 74reading using low-level

operations 66reading using streams 24, 61renaming 56rewind 67seeking 66share modes 70size 67supported lock types 69supported share modes 70with streams 67writing using streams 61

Float 19flowed icon lists 240focus 158fonts 93

as cursors 103assigning to graphics context 101drawing with 100freeing 102from graphics context 102loading 97overview and process 94pattern matching 95querying 95scalable 97used by widgets 211wildcard characters 95

form widgets 167circular constraint errors 168

formatsdata

DDE servers and clients 362Fraction 19freeing

DDE clients or servers 372fonts 102graphics contexts 89pixmaps 107summary 133

Ggarbage collection 326GC 82GCArcMode 86GCBackground 86GCCapStyle 86GCClipMask 86GCClipXOrigin 86GCClipYOrigin 86GCDashOffset 86GCFillRule 86GCFillStyle 86GCFont 86GCFunction 85, 86

GCJoinStyle 86GCLineStyle 86GCLineWidth 85, 86GCSubwindowMode 86GCTileStipXOrigin 86GCTileStipYOrigin 86geometry management 139, 161glyph cursors 104graphic constants 83graphics contexts 82

attributes of 86changing 89constraints 515convenience methods 88copying 88creating 85freeing 89GCFont values 102methods for 84retrieving values 85using 84valuemasks 85with other drawables 89

greying out widgets 178

Hhandling

client requests 351links 349

hierarchy, class 135hotlink events 355hotlinking to items 360

IIBM Smalltalk

architecture 3base subsystems 1design intent 2overview 1platform support 4

icon area widget 241icon lists 237icon trees 248icons 124, 126

constraints 515creating 124drawing 125for application windows 159in buttons 176loading from a file 128loading from ByteArray 130loading from DLL 125loading into a file 129loading into ByteArray 130OS 126

IdentityDictionary 8, 10image file formats 126, 131

PCX 131PM BMP 132TIFF 132Windows BMP 132

imagescopying from a drawable 123creating 121

528 IBM Smalltalk: Programmer’s Reference

Page 543: IBM Smalltalk: Programmer's Reference

images (continued)device independent 123device-independent 120direct-color 122displaying 122loading from a file 127loading from ByteArray 130loading into a file 129loading into ByteArray 130manipulating 121

implementing server behavior 349indexed palettes

constraints 515initiating DDE events 354Integer 18inter-process communication 425interrupts (asynchronous messages) 327Interval 8, 10, 12IPC 425

Kkeyboard events 154

Llabel tools 260label widgets 171labels, direct editing 239leaving a target 268limitations 270line delimiters 22

constants 64line delimiters, constants 15, 64lines

drawing 90drawLines:points:mode: 90setting line attributes 88

links, handling 349list widgets 185

multiple selection 187scrolled- 188single selection 186

listsdrawn 236flowed icon 240icon 237scrolled 235table 241

LookupTable 8, 10losingFocusCallback 163

Mmagnitude comparing 14main-window widgets 161managed pool dictionaries 396menu bar 180

normal 184simple 179

menusnormal 184pop-up 183pull-down 180simple 179

Message 25

message-box widgets 191Metaclass class 38methods 19, 39, 99, 486

- 17, 21, 10/ 17, 21* 17, 21& 7+ 17, 21= 7, 8, 14, 21// 17, 21@ 17== 7, 8\\ 17\< 12, 14, 21\<= 12, 14, 21> 12, 14, 21>= 12, 14, 21>> 35| 28abs 17, 21Accessing

fractionPart 20integerPart 20scale 20significantDigits 20

accessMode: 200activePriority 50activeProcess 50add: 10, 11add:after: 13add:afterIndex: 13add:before: 13add:beforeIndex: 13add:withOccurrences: 12addAll: 10, 11addAll:after: 13addAll:afterIndex: 13addAll:before: 13addAll:beforeIndex: 13addAllFirst: 13addAllLast: 13addCallback:receiver:-

selector:clientData: 150addClassVarName: 37addCompiledMethod: 36addDays: 16addDependent: 6addEventHandler:receiver:selector:

-clientData: 154addFirst: 13addInstVarName: 37addLast: 13addLineDelimiters 13addProcess 47address 291addSharedPoolName: 37addTime: 17addTimeOut:receiver:selector:

-clientData: 230addWorkProc:receiver:selector:

-clientData: 230allClassVarNames 37allInstances 35allInstVarNames 37allMask: 18allMethodsDo: 35

methods 19, 39, 99, 486 (continued)allMethodsNamed: 36allMethodsReferencing

-InstVarName: 36allMethodsReferencingLiteral: 36allMethodsSending: 36allMethodsSendingAll: 36allSelectors 35allSharedPoolNames 37allSubclasses 34allSubclassesBreadthFirstDo: 35allSubclassesDepthFirstDo: 35allSubclassesDo: 35allSuperclasses 34allSuperclassesDo: 35amountToTranslateWithin: 22and: 7answerString: 200anyMask: 18arcCos 18arcSin 18arcTan 18area 22areasOutside: 22argument 27argumentCount 13, 48arguments 25, 27arguments: 25asArray 10asBag 10asByteArray 10ascent 99, 100asCharacter 19asClassPoolKey 40asDBString 13asDecimal 19asFloat 17asFraction 17asGlobalKey 40asInteger 17asLowercase 12, 15asNumber 12asOrderedCollection 10asPoolKey 40asSBString 13asSeconds 16, 17asSet 10associationAt: 11associationAt:ifAbsent: 11associationsDo: 11asSortedCollection 10asSortedCollection: 10asString 12, 15asSymbol 12, 15asUppercase 12, 15asyncExecInUI: 229, 231at: 10, 11, 116, 120at:ifAbsent: 11at:ifAbsentPut: 11at:ifPresent: 8, 11at:put: 11, 12atAll:put: 12atAllPut: 12atEnd 24atEndOrWhenExceptionDo: 29, 32backgroundColor: 213basicAllInstances 35

Index 529

Page 544: IBM Smalltalk: Programmer's Reference

methods 19, 39, 99, 486 (continued)basicAt: 10basicAt:put: 12basicMultiAllInstances 40basicNew 34basicNew: 34basicSize 7bearing 100become: 7between:and: 14, 21bindWith: 13bindWith:with: 13bindWith:with:with: 13bindWith:with:with:with: 13bindWithArguments: 13bitAnd: 18bitAt: 18bitInvert 18bitOr: 18bitShift: 18bitXor: 18black 113blackPixel 83, 119blue 113bottom 22bottom: 22bottomCenter 22bottomLeft 22bottomLeft: 22bottomRight 22bottomRight: 22broadcast: 6broadcast:with: 6button 156buttonType: 72, 198call 292callingConvention 291callingConvention:address:-

parameterTypes:returnType: 292callingConvention:function:library:-

parameterTypes:returnType: 292callWith: 292callWith:with: 292callWith:with:...:with: 292canUnderstand: 36ceiling 18center 22changed 6changed: 6changeGC:values: 84, 89character 156chars: 101chars:delta:font: 101chdir: 55class 6classPool 37classVarNames 37clearBit: 18close 23, 62, 65, 72, 293closedir 61collect: 11colorCube: 122colorEncode 132colors: 116colorScheme 132colorsUsed 132comment 37

methods 19, 39, 99, 486 (continued)comment: 37compile:inClass: 41compile:inClass:ifFail: 41compile:inClass:warningLevel:-

onWarning:ifFail: 41compiledMethodAt: 35compiledMethodAt:ifAbsent: 35compiler 34compression 132compression: 132configuredSubsystems 42conform: 11connectToSuper 38contains: 22containsPoint: 22contents 23, 24, 62, 63, 72context 40Converting

asDecimal 20asFloat 20asFraction 20asInteger 20

copy 6copyArea:gc:srcX:srcY:width:-

height:destX:destY: 108, 120copyFrom:to: 10, 23copyGC:dest: 84, 88copyPlane:gc:srcX:srcY:width:- height:-

destX:destY:plane: 111copyReplaceAll:with: 10copyReplaceFrom:to:with: 10copyReplaceFrom:to:withObject: 10copyReplacing:withObject: 10copyright 43copyWith: 10copyWithout: 10corner 22corner: 21, 22cos 18count 155cr 24, 63createApplicationShell:argBlock: 149,

158createBitmapFromData:width:-

height: 105createBitmapFromData:with:-

height: 109createBulletinBoardDialog:-

argBlock: 197createComboBox:argBlock: 189createDrawingArea:argBlock: 164createErrorDialog:argBlock: 196createFontCursor: 106createForm:argBlock: 167createFormDialog:argBlock: 197createGC:values: 84, 85, 86createGlyphCursor:sourceChar:-

maskChar: 104createGlyphCursor:sourceChar:-

maskChar:foregroundColor:-backgroundColor: 104

createInformationDialog:-argBlock: 196

createLabel:argBlock: 172createList:argBlock: 185createMainWindow:argBlock: 161

methods 19, 39, 99, 486 (continued)createManagedWidget:parent:-

argBlock: 203createMessageBox:argBlock: 191createMessageDialog:argBlock: 191,

196createPixmap:height:depth: 107, 119createPixmapCursor:foreground-

Color:backgroundColor:x:y: 105createPixmapCursor:x:y: 105createPixmapFromBitmapData:-

width:height:fg:bg:depth: 107createPopupShell:

-parent:argBlock: 149, 158createPrimaryWidget:parent:-

argBlock: 202createPromptDialog:argBlock: 197createPushButton:argBlock: 172createQuestionDialog:argBlock: 196createRadioBox:argBlock: 174createRowColumn:argBlock: 169createScrolledList:argBlock: 149, 185,

188createScrolledText:argBlock: 162createScrolledWindow:argBlock: 160createSelectionBox:argBlock: 193createSelectionDialog:argBlock: 193,

197createSimpleMenuBar:argBlock: 179createSimplePopupMenu:

-argBlock: 179createSimplePulldownMenu:

-argBlock: 179createText:argBlock: 162createWarningDialog:argBlock: 196createWidget:parent:argBlock: 203createWidgetSystem 202createWorkingDialog:argBlock: 196Creating instances 20critical: 51currentError 127, 129currentErrorString 127, 129data 121dateAndTimeNow 16, 17dayIndex 16dayName 16dayOfMonth 16dayOfYear 16daysFromBaseDay 16daysInMonth 16daysInMonth:forYear: 16daysInYear 16daysInYear: 16daysLeftInMonth 16daysLeftInYear 16defaultButtonType: 199defaultChar 99defaultHandler 25defaultScreen 81defineCursor: 103definitionString 37degreesToRadians 17deleteAllSelectors: 36deleteSelector: 36deleteSelector:ifAbsent: 36delta: 101denominator 19

530 IBM Smalltalk: Programmer’s Reference

Page 545: IBM Smalltalk: Programmer's Reference

methods 19, 39, 99, 486 (continued)dependents 6depth 107, 109, 121descent 99, 100description 25, 27destroyIcon: 126destroyWidget 140detect: 11detect:ifNone: 11digitValue 14digitValue: 15disconnectFromSuper 38display 155, 279dist: 21dName 59do: 8, 11, 23doesNotUnderstand: 7dotProduct: 21doWithIndex: 11drawArc:x:y:width:height:-

angle1:angle2: 89, 92drawArcs:arcs: 89, 92drawIcon:x:y:icon: 125drawImageString:x:y:string: 89, 101drawLine:x1:y1:x2:y2: 89, 90drawLines:points:mode: 89drawPoint:x:y: 89, 90drawPoints:points:mode: 89, 90drawRectangle:x:y:width:height: 89,

91drawRectangles:rectangles: 89, 91drawSegments:segments: 89, 90drawString:x:y:string: 89, 101drawText:x:y:items: 89, 93, 101dropSiteRegister: 219equals: 42eqv: 7errno 72error: 7, 25evaluate: 41evaluate:for: 41evaluate:for:ifFail: 41evaluate:for:warningLevel:-

onWarning:ifFail: 41even 18exception 27, 29execLongOperation: 47exit 43exitWith: 27, 29exp 18expandBy: 22extent 22, 100, 121extent: 21, 22factorial 19fileDescriptor 68, 76fileName: 200fillArc:x:y:width:height:angle1:-

angle2: 89, 92fillArcs:arcs: 89, 92fillPolygon:points:shape:mode: 89, 92fillRectangle:x:y:width:height: 89, 91fillRectangles:rectangles: 89, 91findFirst: 10findLast: 10first 10firstDayOfMonth 16floor 18

methods 19, 39, 99, 486 (continued)floorLog: 18flush 24, 67font 99font: 101fontList 212fontList: 211fontName 212fontSettableWidgets 212fontStruct: 211foregroundColor: 213fork 45, 48, 49forkAt: 45, 47, 49formatMatchesByteObjects:-

offsetsIntoByteObjects: 131formatMatchesFileHandle:

-atOffset: 131formatMatchingByteObjects:-

offsetsIntoByteObjects:ifNone: 131formatMatchingFileHandle:-

atOffset:ifNone: 131forMilliseconds: 50forMutualExclusion 51forSeconds: 50fractionPart 19freeCursor 103, 133freeFont 102, 133freeGC 84, 89, 133freeIcon 124, 133freePixmap 107, 133from:to: 12from:to:by: 12from:to:do: 11from:to:doWithIndex: 11fromDays: 16fromImage:maskImage: 124fromOSIcon: 126fromResource: 125fromResource:fileName: 126fromSeconds: 17fromSystem: 126function: 85functionNumber 291gcd: 19getAddress: 293getChild: 192getcwd 55getDeviceIndependentImage: 123getGCValues: 102getGCValues:valuesReturn: 84getGeometry: 108getIcon:foregroundColor: 126getPalette 118getPixel:y: 122getPixels:y:width:pixels:-

startIndex: 122getsInstVar: 42getState 174getString 162, 189getSubImage: 122green 113halt 7halt: 7handlesByDefault 27hasErrorOccurred 127, 129hash 7hasMethods 36

methods 19, 39, 99, 486 (continued)height 22, 99, 100, 109, 121, 143, 155,

279height: 22, 143highBit 18highIOPriority 46, 50hours 17hRes 131icon 159iconMask 159iconPixmap 159iconToUnload 129iconType: 72, 199ident 132identifier 72ifFalse: 7ifFalse:ifTrue: 7ifTrue: 7ifTrue:ifFalse: 7imageStorage 130importantColors 132importantColors: 132includes: 12includesKey: 11includesSelector: 36increment 12indexOf: 10indexOf:ifAbsent: 10indexOf:matchCase:startingAt: 12indexOfDay: 16indexOfMonth: 16indexOfSubCollection:- startingAt: 10indexOfSubCollection:-

startingAt:ifAbsent: 10inheritsFrom: 34initialize 38, 202initializeAfterCreate 202initializeResources 202inject:into: 11insetBy: 22insetOriginBy:cornerBy: 22instSize 35instVarAt: 7instVarAt:put: 7instVarNames 37integerPart 19intensity: 113, 116intersect: 22intersects: 22isAlphaNumeric 16isBits 35isBitSet: 18isBlk 74isBytes 35, 63isBytes: 63isCfsError 53, 71, 73isCharacter 6isCharacters 63isCharacters: 63isChr 74isClass 6isDBString 6isDigit 16isDir 74isEmpty 12, 24isFifo 74isFixed 35

Index 531

Page 546: IBM Smalltalk: Programmer's Reference

methods 19, 39, 99, 486 (continued)isFloat 6isInteger 6isKindOf: 6isLetter 16isLowercase 16isMemberOf: 6isMetaclass 6isNil 6, 24isPointers 35isPrimitive 42isReg 74isSBString 6isSeparator 16isSpecial 74isString 6isSymbol 6isUppercase 16isUserPrimitive 42isVariable 35isVowel 16jobAttributes 279key 14key: 14key:value: 14keyAtValue: 11keyAtValue:ifAbsent: 11keys 11keysAndValuesDo: 11keysDo: 11keysym 156labelString: 171last 10, 55lbearing 100lcm: 19left 22left: 22left:right:top:bottom: 22leftCenter 22lessGeneralThan: 18library 291lineDelimiter 23, 63lineDelimiter: 23, 63lineWidth: 85listFonts: 97listFonts:maxnames: 95ln 18loadFont: 98loadFromByteObjects:-

offsetsIntoByteObjects: 130loadFromFile: 127, 128loadFromFileHandle:atOffset: 127,

128loadQueryFont: 98, 211lock:start:len: 69log: 18logicalName 293logicalName: 293lookupColor: 114, 116lowIOPriority 46, 50lseek:whence: 66manageChild 139mapFontCursor:platform-

Cursor: 106mapLogicalName:toPhysical-

Name: 293mapWidget 139

methods 19, 39, 99, 486 (continued)mask:keysym: 171match: 12max: 14, 21maxBounds 99merge: 22message 40, 72messageLoop 226messageString: 72, 198, 200methodClass 42methodClass: 42methodDictionary 35methodsDo: 35millisecondClockValue 17millisecondsPerDay 17millisecondsToRun: 17min: 14, 21minBounds 99minutes 17mkdir: 55monthIndex 16monthName 16moreGeneralThan: 18moveBy: 22moveTo: 22MultiAllInstances 40multiBecome: 12Multiple Instance Accessing 40mwmDecorations 159name 34, 99, 291nameOfDay: 16nameOfMonth: 16nearestColor: 117, 120nearestPixelValue: 117, 120negated 17, 21negative 17new 10, 51new: 10newChild 25newDay:month:year: 16newDay:monthIndex:year: 16newDay:year: 16newProcess 45, 46, 49newProcessWith: 45, 49next 24, 63next: 24next:put: 24nextLine 24, 63nextMatchFor: 24nextPut: 24, 63nextPutAll: 24, 62, 63noMask: 18normal 21not 7notEmpty 12notNil 6, 24now 17nullTerminated 12numChars 99numerator 19numerator:denominator: 19occurencesOf: 12odd 18on: 24, 67, 76on:from:to: 24open: 61, 71open:oflag: 64, 66, 71

methods 19, 39, 99, 486 (continued)open:oflag:share: 68, 71opendir:pattern:mode: 58openEmpty: 61, 71or: 7origin 22origin: 22origin:corner: 22origin:extent: 22pageNumber 279palette 121paletteInfo 131parameterTypes 291parent 25parseColor: 114pathSeparator 55pathSeparatorString 55peek: 24peekFor: 24pelsPerMeter 132pelsPerMeter: 132perChar 99perCharAtRow: 99perCharNumColumns 99perCharNumRows 99perform: 7perform:with: 7perform:with:with: 7perform:with:with:with: 7perform:withArguments: 7physicalName 293pi 19platformErrno 76platformErrorCategory 76platformErrorLocation 76platformRecommendedAction 76point 156pointRoot 156position 24position: 24positive 17predictor 132primaryInstance 38primaryInstance: 38primaryWidget 202primitiveFailed 7printOn: 6, 72, 138printOn:base: 19printOn:showDigits:Pad: 20printString 6, 72printStringRadix: 19printStringRadix:padTo: 19printStringRadix:showRadix: 19priority 46, 49priority: 46, 47, 49prompt 72, 198, 199, 200prompterStyle: 198putDeviceIndependentImage:-

image:srcRect:destRect: 122putPixel:y:pixelValue: 121putPixels:y:width:pixels:

-startIndex: 122queryBestIconSize 125queryFont 102queueInterrupt: 49quo: 17radiansToDegrees 17

532 IBM Smalltalk: Programmer’s Reference

Page 547: IBM Smalltalk: Programmer's Reference

methods 19, 39, 99, 486 (continued)raisedTo: 18raisedToInteger: 18rbearing 100read:startingAt:nbyte: 66readAndDispatch 227, 229readBitmapFile:widthReturn:-

heightReturn:bitmapReturn:-xHotReturn:yHotReturn: 111

readdir 59, 60readdir: 60readdirName 60, 61realizeWidget 139receiver 25receiver: 25reciprocal 18recolorCursor:backgroundColor: 105recording 132rectangle 155red 113red:green:blue: 113, 116redMask:greenMask:blueMask: 120referencesInstVar: 42referencesLiteral: 42rehash 11reject: 11release 6rem: 17remove: 11, 56remove:ifAbsent: 11removeAll: 11removeAllKeys: 11removeAllKeys:ifAbsent: 11removeAtIndex: 11removeClassVarName: 37removeDependent: 6removeFirst 11removeFromSystem 38removeInstVarName: 37removeKey: 11removeKey:ifAbsent: 11removeLast 11removeMappingForLogical-

Name: 293removeSharedPoolName: 37removeUnreferencedLibraries 294rename:new: 56rendering 132replaceFrom:to:with: 12replaceFrom:to:with:startingAt: 12replaceFrom:to:withObject: 12reportError:resumable:startBP 47reset 24resolution 279respondsTo: 6resumable 25resume 45, 46, 47, 49resumeWith: 27, 31resumptionTime 50resUnits 132retry 27returnType 291reverse 10reverseDo: 11rewind 67rewinddir 61right 22

methods 19, 39, 99, 486 (continued)right: 22rightCenter 22rmdir: 55rootDirectories 55rootWindow 81rounded 18, 21, 22roundTo: 18sameAs: 12saveImage 43scaleBy: 22screen 279searchMask: 200searchPath: 200seconds 17select: 11selectionLabelString: 194selector 25, 42selector: 25, 42selectors 35send 25sendsSelector: 42set 174setAreas:verticalScrollbar:

-workRegion: 160setBit: 18setClassName: 37setClassPool: 37setFont: 100setPalette: 118setSharedPoolNames: 37setsInstVar: 42setState:notify: 174setStipple: 109setString: 144, 162, 189setSubsystemType:to: 43setToEnd 24setValuesBlock: 143sharedPoolNames 37shouldNotImplement 7sign 18signal 26, 27, 47, 51signal:atTime: 50signalWith: 27signalWith:with: 26, 27signalWithArguments: 26, 27sin 18size 12, 23, 67, 70, 74size1 132size2 132skip: 24skipTo: 24skipToAll: 24, 64sleep 227sortBlock 13sortBlock: 13sourceCodeAt: 35sourceCodeAt:ifAbsent: 35sourceString 40, 42space 24sqrt 18squared 18startPosition 40stat 74stat: 60, 74, 75, 76state 156stAtime 75

methods 19, 39, 99, 486 (continued)stCTime 75stDev 75stFtime 75stGid 75stIno 75stMode 74stNlink 75stopPosition 40storeOn: 6storeString 6strictlyPositive 17stSize 74stUid 75subclass:classInstanceVariable-

Names:instanceVariableNames:-classVariableNames:poolDic-tionaries: 39

subclass:instanceVariable-Names:classVariableNames:-poolDictionaries: 39

subclasses 34subclassResponsibility 7subStrings 12subStrings: 12subsystemType: 43, 106subtractDate: 16subtractDays: 16subtractTime: 17superclass 34supplantation 16supportsLockType: 69supportsShareMode: 70suppressing system error dialogs 73suspend 46, 47, 49suspendSmalltalk 227, 228symbol 34symbolLiteral 42syncExecInUI: 229, 231systemBackgroundPriority 46, 50tab 24tan 18terminate 46, 49textExtents:stringdirectionReturn:-

dRetfontAscentReturn:aRetfont-DescentReturn:dRetoverallReturn:-oRet 99

textLabelString: 194textWidth:string 99time 156timesRepeat: 18timingPriority 46, 50title 159, 279title: 198to: 18to:by: 18to:by:do: 18to:do: 18today 16top 22top: 22topCenter 22topLeft 22topLeft: 22topRight 22topRight: 22totalSizeBeforeUnload: 130

Index 533

Page 548: IBM Smalltalk: Programmer's Reference

methods 19, 39, 99, 486 (continued)translateBy: 22transpose 21trimBlanks 13trimSeparators 13truncate 24truncated 18, 21, 22truncatedGrid: 21truncateTo: 18, 21type 155undefineCursor 103unload:intoByteObjects:offsetsInto-

ByteObjects: 130unload:intoFile: 129, 130unload:intoFileHandle:atOffset: 129unloadFont 102, 133unlock:start:len: 69unmapWidget 139untilMilliseconds: 50update: 6upTo: 24, 63upToAll: 24, 63, 64upToEnd 24userBackgroundPriority 46, 50userInterruptPriority 46, 50userSchedulingPriority 46, 50value 14, 48, 111value: 14, 15, 48value:onReturnDo: 48value:value: 48value:value:onReturnDo: 48value:value:value: 48value:value:value:onReturnDo: 48valueOnReturnDo: 48values 11valueWithArguments: 48valueWithArguments:onReturnDo: 48variableByteSubclass:-

classInstanceVariable-Names:classVariableNames:pool-Dictionaries: 39

variableByteSubclass:-classVariableNames:-poolDictionaries: 39

variableByteSubclass:classInstance-VariableNames:classVariableNames:-poolDictionaries: 39

variableSubclass:-classInstanceVariableNames:-instanceVariableNames:-classVariableNames:-poolDictionaries: 39

variableSubclass:instanceVariable-Names:classVariableNames:-poolDictionaries: 39

version 131vmType 43vRes 131wait 47, 48, 50, 51wake 227when:do: 26, 29when:do:when:do:, etc. 26whenExceptionDo: 29whichClassIncludesSelector: 34whichMethodsReferenceInstVar-

Name: 36whichMethodsReferenceLiteral: 36

methods 19, 39, 99, 486 (continued)whichMethodsSend: 36whichMethodsSendAll: 36whileFalse: 25, 32whileTrue: 25, 31white 113whitePixel 119width 22, 100, 109, 121, 155, 279width: 22width:height:depth:palette: 121window 81, 155, 164, 279with: 10, 24with:do: 11with:from:to: 24with:with: 10with:with:with: 10with:with:with:with: 10withAllSubclasses 34withAllSubclassesBreadthFirstDo: 35withAllSubclassesDepthFirstDo: 35withAllSubclassesDo: 35withAllSuperclasses 34withAllSuperclassesDo: 35write:startingAt:nbyte: 66writeBitmapFile:width:height:-

xHot:yHot: 110x 21, 155, 156, 279x: 21x:y: 21xor: 7xRes 132xRoot 156y 21, 155, 156, 279y: 21year 16yourself 7yRes 132yRoot 156

modal dialog 191modifyVerifyCallback 163mouse events 154

Nname and type, Volume 57name length

file 57volumes 58

National Language Support 377defining managed pool

dictionaries 396overview 377

NLS 377notebooks 250

callbacks 250PM 251WIN 253

Number 17

OObject class 5, 6Object Linking and Embedding 437ObjectPointer 316OCX 460OLE 437

OLE 437 (continued)ambient properties 462automation 457building containers 442classes

OleAutomationObject 442OleClient 441OleControl 442OleFile 442OleMainWindow 440OlePrimitive 441

clipboard operations 449creating

automation objects 458clients 444main windows 443object verb menus 451

custom control (OCX) 460licensed OCXs 467Links dialog 454retrieving clients 456saving clients 455wrapping OCXs 466

OrderedCollection 8, 10, 13origin

for drawing 81of graphic text 100of Point 21

OSBaseType 309, 311, 315OSF/Motif 135

input event processing 225widget resource compatibility 143

OSImmediate 309OSObject 308OSObjectPointer 309, 311OSStructure 309, 311, 315OSVariableStructure 309, 315other languages, interfacing to 285

Ppages

callbacks 250creating 250producing 278

palettes 114, 118default 115direct 120indexed 116retrieving 118selecting 118

parent 135paths 55pattern matching 95pie slices 93

drawing 93pixmaps

as cursors 103, 105copying 108creating 107creating bitmaps 109drawing in color 119freeing 107geometry 108overview 106reading files 111writing files 110

534 IBM Smalltalk: Programmer’s Reference

Page 549: IBM Smalltalk: Programmer's Reference

platform differencesCommon Graphics 515Common Widgets 517

platform-integrated drag and dropaccepting drops 219classes 217convert proc 224drop proc 221transfer proc 225transferring data 223

platform-specific supportdynamic data exchange 374

PlatformConstants 106PlatformFunction

calling 290declaring functions 333definition 285, 288protocols 291

PlatformLibrarydefinition 293protocols 293

PM notebook widget 251Point 20points, drawing 90poke events 357poking data to server 361policies

editing 246polygons

drawing 92pool dictionaries

CfsConstants 54CgConstants 83CldtConstants 15CwConstants 144EwConstants 233PlatformConstants 106SystemExceptions 30

pop-updialogs 158menus 183windows 149, 158

POSIX locale model 379PRAGMA field 396primitive widgets 136print job

attributes 276configuring 275configuring attributes 275ending 279

printersselecting 274setting up on a UNIX platform 282shell

creating 277starting a job 278using prompter 275

printing processoverview 274using printer shells 276

proc 217processes

and delay 228and Delay 47and Semaphore 47background 228creating 45

processes (continued)ending 46printing 274priorities 46Process class 45, 228process methods 49resuming 46suspending 46synchronization 47UIProcess 226

ProcessorScheduler 45, 50progress bar tools 260progress bars 253prompters 197

file selection 200message 198text 200

push-button widgets 171, 172

Qqueries 360

Rradio-button widgets 174raster operations, setting 88ReadStream 22, 23ReadWriteStream 22, 23Rectangle 21rectangles, drawing 91renderable objects 238request event 356requesting data 360resource management

summary 133resources 141, 144

common 235extended widgets 202getting 142setting 142setValuesBlock 143table list 242

return valuesDDE transfers 363

RGB colors 113row-column widgets

as check box 175as menu 184as menu bar 184as radio box 148, 174, 211non-homogeneous error 174

run events 357

Sscrolled lists 148, 149, 188, 235scrolled-window widgets 160selecting printers 274selection-box widgets 193Semaphore 45, 47, 51separator tools 260server behavior, implementing 349servers

executing commands at 362poking data to 361

Set 8, 10Set values block 143shell, for printer 277shell widgets 136, 137, 158

decorations 158, 159Signal 25, 27simple

drag and drop 270groups 262menus 179

sliders 254SortedCollection 8, 10, 13spin buttons 256split windows 257starting print jobs 278stipples, creating 109streams 61String 8, 10, 13strings, drawing 101suspend process, causes 47Symbol 8, 10, 13system browser font 212system configuration 269SystemExceptions 30

Ttable

columns 243lists 241

resources 242trees 249

target type 216termination events 357text

drawing 101widgets 162

Time 16timeouts 371timer proc 230toggle-button widgets 171, 173, 175tool bars 259

groups 261primitive tools 260simple groups 262using tools 260, 261widget tools 261

top-level shell widgets 158resources 159

transfer proc 225transferring data 223tree widgets 247

icon trees 248

UUIProcess 226UndefinedObject 24UNIX

configuring printer setup options 283pipe stream 431printer setup 282process 427

UNIX environment 425UNIXEnvironment

class usage example 426

Index 535

Page 550: IBM Smalltalk: Programmer's Reference

UNIXEnvironment (continued)methods 426

UNIXProcess 427methods 428usage example 430

UNIXReadPipeStream 431UNIXWritePipeStream 434user interface

background request 229concepts 137process model 225, 231

user primitivesaccessing objects 323classes available during 327converting C values to Smalltalk

objects 322converting Smalltalk objects to C

values 322definition 285dummy environment 328error codes 336external shared library 319functions available in 319miscellaneous functions 326object allocation 320protecting objects from garbage

collection 326samples 328sending messages 320syntax for 318testing objects 321using functions from other

places 328user primitives, error codes 336using

licensed OCXs 467OCXs 460printer shell 276

using OLE automation 457

Vvaluemasks 85Virtual Machine API 285volumes

file name lengths 58obtaining 57Volume name and type 57

voting and cursors 267

Wwarmlink events 355warmlinking to items 360warnings 174widgets

application-drawn button 177argBlock 143button 171callbacks 469check-box 175child 135class hierarchy 135colors 213combo-box 189composite 136convenience methods 148, 150creating 138, 148creation methods 148, 150definition 135destroying 140dialogs 190drawing area 164drawing in color 118drawn list 236event handling 146extended list 234flowsed icon lists 240fonts used by 211form 167functions 144geometry management 161getting resources 142greying out button 178icon area 241icon lists 237iconic-button 176layout 167limitations 270list 185main-window 161managing 139, 141mapping 139, 140menus 178message-box 191notebooks 250

PM 251WIN 253

overview of concepts 137

widgets (continued)parent 135parent-child relationship 138pop-up menus 183primitive 136progress bars 253pull-down menus 180push-button 172radio-button 174realizing 139resources 141, 469row-column 169scrolled-window 160selection-box 193setting resources 142shell 137simple menus 179sliders 254spin buttons 256split windows 257steps to display 138table lists 241text 162toggle-button 175tool bars 259top-level shell 158tree 138trees 247

icons 248table 249

wildcard characters 95in file names 58

WIN notebook widget 253window

decorations 159manager 158

work proc 230WriteStream 22, 23

XX logical font description 95X11 bitmap file format 110Xlib

Common Graphics compatibilitywith 79, 112

Common Widgets compatibilitywith 135

conversion to Smalltalk 79, 135predefined cursors 104

536 IBM Smalltalk: Programmer’s Reference