msim microsystems Programmer’s Reference Manual for Sun Windows Sun Microsystems, Inc. • 2550 Garcia Avenue • Mountain View, CA 94043 6 415-960-1300 Part No: 800-1167-01 Revision E of 15 May, 1985 Acknowledgements A preliminary implementation of the Sun Window System was written at Sun Microsystems, Inc. in December 1982 and January 1983. It incorporated a number of low-level operations and data, including raster operations and fonts, provided by Tom Duff of Lucasfilm, Inc. The present ver- sion is a major rework of the preliminary implementation, aimed at generality, extensibility, and reliability. Trademarks Sun Workstation, SunWindows and the combination of Sun with a numeric suffix are trademarks of Sun Microsystems, Inc. Sun Microsytems and Sun Workstation are registered trademarks of Sun Microsystems, Inc. UNIX, UNDC/32V, UNIX System III, and UNIX System V are trademarks of Bell Laboratories. Copyright ® 1982, 1983, 1984 by Sun Microsystems. This publication is protected by Federal Copyright Law, with all rights reserved. No part of this publication may be reproduced, stored in a retrieval system, translated, transcribed, or transmit- ted, in any form, or by any means manual, electric, electronic, electro-magnetic, mechanical, chemical, optical, or otherwise, without prior explicit written permission from Sun Microsystems. Revision History Contents Chapter 1 Overview 1_1 Chapter 2 Pixel Data and Operations 2-1 Chapter 3 Overlapped Windows: Imaging Facilities 3-1 Chapter 4 Window Manipulation 4_1 Chapter 5 Input to Application Programs 5_1 Chapter 8 Suntool: Tools and Subwindows 6-1 Chapter 7 Suntool: Subwindow Packages 7_1 Chapter 8 The Panel Subwindow Package 8_1 Chapter 8 Suntool: User Interface Utilities fl-1 Appendix A Rects and Rectlists A-l Appendix B Sample Tool B-l Appendix C Sample Graphics Programs C-l Appendix D Programming Notes D-l Appendix E Writing a Pixrect Driver E-l Appendix F Option Subwindow F-l Appendix G Converting from Option Subwindow to Panel Subwindow G-l — v — Contents Preface 15 Chapter 1 Overview 1.1. What is Sun Windows? 1_1 1.2. Hardware and Software Support j.j 1.3. Layers of Implementation 1-2 1.3.1. Pixrect Layer 1_2 1.3.2. Sunwindow Layer 1_3 1.3.3. Suntool Layer 1_3 Chapter 2 Pixel Data and Operations 2-1 2.1. Pixrects 2-1 2.1.1. Pixels: Coordinates and Interpretation 2-2 2.1.2. Geometry Structs 2-2 2.1.3. The Pixrect Struct 2-3 2.2. Operations on Pixrects 2-3 2.2.1. The Pixrectops Struct 2-4 2.2.2. Conventions for Naming Arguments to Pixrect Operations 2-4 2.2.3. Pixrect Errors 2-5 2.2.4. Creation and Destruction of Pixrects 2-5 2.2.4. 1. Open: Create a Primary Display Pixrect 2-5 2. 2. 4. 2. Region: Create a Secondary Pixrect 2-5 2. 2. 4. 3. Close / Destroy: Release a Pixrect’s Resources 2-6 2.2.5. Single-Pixel Operations 2-6 2.2.5. 1. Get: Retrieve the Value of a Single Pixel 2-6 2. 2. 5. 2. Put: Store a Value into a Single Pixel 2-7 2.2.6. Constructing an Op Argument 2-7 2. 2. 6.1. Specifying a RasterOp Function 2-7 2. 2. 6. 2. Ops with a Constant Source Value 2-8 2. 2. 6.3. Controlling Clipping in the RasterOp 2-9 2. 2. 6.4. Examples of Complete Op Argument Specification 2-9 2.2.7. Multi-Pixel Operations 2-9 2.2.7. 1. Rop: RasterOp Source to Destination 2-9 2. 2.7. 2. Stencil: RasterOps through a Mask 2-10 2. 2. 7. 3. Replrop: Replicating the Source Pixrect 2-11 2. 2. 7. 4. Batch RasterOp: Multiple Source to the Same Destination 2-11 — vii — 2. 2.7. 5. Vector: Draw a Straight Line 2-12 2. 2.7. 6. Draw Curved Shapes (pr_traprop) 2-13 2. 2.7.7. Polygon: Textured Polygons with Holes 2-16 2.2.8. Colorinap Access 2-17 2. 2. 8.1. Get Colormap 2-17 2. 2. 8. 2. Put Colormap 2-17 2. 2. 8. 3. Provision for Inverted Video Pixrects 2-18 2.2.9. Attributes for Bitplane Control 2-19 2. 2.9.1. Get Attributes 2-19 2. 2.9. 2. Put Attributes 2-19 2.2.10. Efficiency Considerations 2-20 2.3. Text Facilities for Pixrects 2-20 2.3.1. Pixfonts and Pixchars 2-20 2.3.2. Operations on Pixfonts 2-22 2.3.3. Pixrect Text Display 2-22 2.4. Memory Pixrects 2-24 2.4.1. The Mpr_data Struct 2-24 2.4.2. Pixel Layout in Memory Pixrects 2-25 2.4.3. Creating Memory Pixrects 2-25 2. 4.3.1. Mem_create 2-25 2. 4.3.2. mem_point 2-25 2. 4.3.3. Static Memory Pixrects 2-26 2.5. File I/O Facilities for Pixrects 2-27 2.5.1. Writing of Complete Raster Files 2-27 2.5.2. Reading of Complete Raster Files 2-28 2.5.3. Details of the Raster File Format 2-29 2.5.4. Writing Parts of a Raster File 2-30 2.5.5. Reading Parts of a Raster File 2-31 Chapter 3 Overlapped Windows: Imaging Facilities 3-1 3.1. Window Issues: Controlled Display Generation 3-1 3.1.1. Clipping and Locking 3-1 3.1.2. Damage Repair and Fixups 3-2 3.1.3. Retained Windows 3-2 3.1.4. Colormap Sharing 3-2 3.1.5. Process Structure 3-3 3.1.6. Imaging with Windows 3-3 3.1.7. Libraries and Header Files 3-3 3.2. Data Structures 3-3 3.2.1. Rects 3-4 3.2.2. Pixwins 3-4 3.2.3. Pixwin_clipdata Struct 3-6 3.2.4. Pixwin_clipops Struct 3-7 3.3. Pixwin Creation and Destruction 3-7 3.3.1. Region Creation 3-8 3.4. Locking and Clipping 3-8 — viii — 3.4.1. Locking 3.8 3.4.2. Clipping 3-10 3.5. Accessing a Pixwin’s Pixels 3_11 3.5.1. Write Routines 3_H 3.5.2. Drawing A Polygon within a Pixwin 3-13 3.5.3. Draw Curved Shapes 3-14 3.5.4. Read and Copy Routines 3-14 3.5.5. Bitplane Control 3-15 3.6. Damage 3_15 3.6.1. Handling a SIGWINCH Signal 3-15 3.7. Colormap Manipulation 3-17 3.7.1. Initialization 3-17 3.7.2. Background and Foreground 3-18 3.7.3. A New Colormap Segment 3_ig 3.7.4. Colormap Access 3-20 3.7.5. Surface Preparation 3-20 Chapter 4 Window Manipulation 4_1 4.1. Wndow Data 4_1 4.2. Wndow Creation, Destruction, and Reference 4-1 4.2.1. A New Wndow 4-2 4.2.2. An Existing Wndow 4_2 4.2.3. References to Windows 4-2 4.3. Wndow Geometry 4.3 4.4. The Wndow Hierarchy 4.4 4.4.1. Setting Wndow Links 4.4 4.4.2. Activating the Wndow 4.5 4.4.3. Modifying Wndow Relationships 4.5 4.5. User Data 4.6 4.6. Minimal-Repaint Support 4.7 4.7. Multiple Screens 4.7 4.8. Cursor and Mouse Manipulations 4-10 4.8.1. Cursors 4-10 4.8.2. Mouse Position 4-11 4.9. Providing for Naive Programs 4-12 4.9.1. Which Wndow to Use 4-12 4.9.2. The Blanket Wndow 4_12 4.10. Wndow Ownership 4-13 4.11. Error Handling 4-13 Chapter 5 Input to Application Programs 5>1 5.1. The Virtual Input Device 5-2 5.1.1. Uniform Input Events 5-2 5.1.2. Event Codes 5.3 5. 1.2.1. ASCII Events 5-3 5. 1.2. 2. Function Events . 5.3 — ix — 5. 1.2. 3. Pseudo Events 5-4 5.1.3. Event Flags 5-5 5.1.4. Shift Codes 5-5 5.2. Reading Input Events 5-5 5.3. Input Serialization and Distribution 5-6 5.3.1. Input Masks 5-7 5.3.2. Seizing All Inputs 5-9 5.4. Event Codes Defined 5-10 Chapter 6 Suntool: Tools and Subwindows 0.| 6.1. Tools Design 6-2 6.1.1. Non-Pre-emptive Operation 6-2 6.1.2. Division of Labor 6-2 6.2. Tool Creation 6-2 6.2.1. Tool Attributes 6-3 6.2. 1.1. The Tool Struct 6-8 6.2.2. Tool Initialization Parameters 6-9 6. 2. 2.1. Command Line Parsing 6-9 6.2.3. Creating the Tool Window 6-11 6.2.4. Subwindow Creation 6-12 6.2.5. Subwindow Layout 6-14 6.2.6. Subwindow Initialization 6-14 6.2.7. Tool Installation (>-15 6.2.8. Tool Destruction 6-15 6.2.9. Programmatic Tool Creation 6-15 6. 2. 9.1. Forking the Tool 6-15 6. 2.9. 2. Environment Parameters 6-16 6.3. Tool Processing 6-17 6.3.1. Toolio Structure 6-17 6.3.2. File Descriptor and Timeout Notifications 6-18 6.3.3. Window Change Notifications 6-18 6.3.4. Child Process Maintenance 6-19 6.3.5. Changing the Tool’s Attributes 6-19 6.3.6. Terminating Tool Processing 6-20 6.3.7. Replacing Toolio Operations 6-20 6.3.8. Boilerplate Tool Code 6-21 6.3.9. Old Style Tool Creation 6-22 Chapter 7 Suntool: Subwindow Packages 7-1 7.1. Minimum Standard Subwindow Interface 7-1 7.2. Empty Subwindow 7-3 7.3. Graphics Subwindow 7-3 7.3.1. In a Tool Window 7-4 7.3.2. Overlaying an Existing Window 7-5 7.4. Message Subwindow 7-7 7.5. Terminal Emulator Subwindow J.g — x — 7.5.1. The Tool Specific TTY Subwindow Type 7-11 7.5.2. TTY-Based Programs in TTY Subwindows 7-13 7.5.3. Driving a TTY Subwindow 7_14 7.5.4. Extending a TTY Subwindow 7_14 Chapter 8 The Panel Subwindow Package 8-1 8.1. Introduction 8-1 8.2. Definition and Uses of Panels 8-1 8.3. Panel Item Types and Their Uses 8-3 8.4. A Sample Panel 8-4 8.5. Attributes and Attribute-Lists 8-6 8.6. Creating Panels 8-7 8.7. Creating and Positioning Items 8-9 8.7.1. Creating Items 8-9 8.7.2. Positioning Items Within a Panel 8-10 8.7.3. Laying Out Components Within an Item 8-11 8.8. Description of Each Item Type 8-11 8.8.1. Messages 8-12 8.8.2. Buttons 8-12 8.8.3. Choices 8-14 8.8.4. Toggles 8-17 8.8.5. Text 8-19 8.8.6. Sliders 8-23 8.9. Modifying and Retrieving Attributes of Panels or Items 8-25 8.10. Painting Panels and Individual Items 8-27 8.11. Destroying Panels and Individual Items 8-28 8.12. Creating Reusable Attribute Lists 8-28 8.13. Summary of Panel Functions 8-30 8.14. Tables of Attributes 8-32 Chapter 9 Suntool: User Interface Utilities 9.1 9.1. Full Screen Access g_i 9.2. Icons g-2 9.2.1. Icon Display Facility g_2 9.2.2. Making a Static Icon 9.3 9.2.3. Dynamic Icon Loading g_5 9.3. Pop-up Menus g_6 9.4. Prompt Facility g_g 9.5. Selection Management g_8 9.6. Window Management g-10 9.6.1. Window Manipulation 9-10 9.6.2. Tool Invocation 9-12 9.6.3. Utilities g_13 Appendix A Rects and Rectlists A-l A.l. Rects A-l — xi — A.1.1. Macros on Re cts A-l A. 1.2. Procedures and External Data for Rects A-2 A. 2. Rectlists A-3 A.2.1. Macros and Constants Defined on Rectlists A-4 A.2.2. Procedures and External Data for Rectlists A-4 Appendix B Sample Tool B-l B. l. gfxtool.c Code B-l Appendix C Sample Graphics Programs C-l C. l. bouncedemo.c Source C-l C. 2. framedemo.c Source C-3 Appendix D Programming Notes D-l D. l. What Is Supported? D-l D.2. Program By Example D-l D.3. Header Files Needed D-l D.4. Lint Libraries D-2 D.5. Library Loading Order D-2 D.6. Shared Text D-2 D.7. Error Message Decoding D-3 D.8. Debugging Hints D-3 D.9. Sufficient User Memory D-4 D. 10. Coexisting with UNIX D-5 I). 10.1. Tool Initialization and Process Groups D-5 D. 10. 1.1. Signals from the Control Terminal D-5 D. 10. 1.2. Job Control and the C-Shell D-5 Appendix E Writing a Pixrect Driver E-l E. l. Glossary E-l E.2. What You’ll Need E-2 E.3. Implementation Strategy E-2 E.4. Files Generated E-3 E.4.1. Memory Mapped Devices E-3 E.5. Pixrect Private Data E-4 E.6. Creation and Destruction E-4 E.6.1. Creating a Primary Pixrect E-4 E.6.2. Creating a Secondary Pixrect E-7 E.6.3. Destroying a Pixrect El-7 E.6.4. The pr_makefun Operations Vector El-8 E.7. Pixrect Kernel Device Driver El-9 E.7.1. Configurable Device Support El-9 E.7.2. Open El-11 E.7.3. Mmap El-12 E.7.4. Ioctl E-12 E.7.5. Close El-14 — xii — E.7.6. Plugging Your Driver into UNIX E-14 E.8. Access Utilities £-15 E.9. Rop E-15 E.10. Batchrop E-16 E.ll. Vector £-16 E.ll.l. Importance of Proper Clipping E-16 E.12. Colormap E-16 E.12.1. Monochrome E-16 E.13. Attributes E-17 E. 13.1. Monochrome El-17 E.14. Pixel E-17 E. 15. Stencil E-17 Appendix F Option Subwindow F_1 F. l. Option Subwindow Standard Procedures F-2 F.2. Option Items F-3 F. 2.1. Boolean Items F-3 F.2.2. Command Items F-4 F.2.3. Enumerated Items F-4 F.2.4. Label Items p_4 F.2.5. Text Items p_5 F.3. Item Layout and Relocation — SIGWINCH Handling p_Q F.4. Client Notification Procedures p*7 F.5. Explicit Client Reading and Writing of Item Values F-8 F.6. Miscellany p.g Appendix G Converting from Option Subwindow to Panel Subwindow G-l — xm — Tables Table 2-1 Argument Name Conventions 2-4 Table 2-2 Useful Combinations of RasterOps 2-8 Table 3-1 Clipping State 3.7 Table 6-1 Summary of Tool Attributes 5.4 Table 6-2 Generic tool arguments g_10 Table 7-1 Differences between Sun terminal and SunWindows tty emulator 7.9 Table 7-2 Escape sequences for tty tool subwindow 7_12 Table 8-1 Some Sample Panel Attributes g_g Table 8-2 Frequently Used Panel Data Types g_7 Table 8-3 Example uses of the PANEL_CU() macro 8-10 Table 8-4 Notification behavior 8-20 Table 8-5 Possible return values from notify procedures 8-21 Table 8-6 Panel Attributes g-32 Table 8-7 Generic Item Attributes 8-34 Table 8-8 Choice and Toggle Item Attributes 8-37 Table 8-9 Text Item Attributes 8-40 Table 8-10 Slider Item Attributes 8-41 Table A-l Rectlist Predicates A-5 Table A-2 Rectlist procedures A-6 Table D-l Header Files Required D_2 Table D-2 sunwindow Variables for Disabling Locking D-4 Table F-l Option Image Types p_2 — xv — Figures Figure 2-1 Typical trapezon with source and destination pixrects 2-13 Figure 2-2 Some figures drawn by pr_traprop 2-13 Figure 2-3 Trapezon with clipped falls 2-16 Figure 2-4 Character and pc_pr origins 2-21 Figure 8-1 icorvtool — a tool that uses panels 8-2 — xvii — - 15 - Preface The Programmer ’» Reference Manual for SunWindows provides primarily reference material on Sun Windows, the Sun window system. It is intended for programmers of applications using win- dow system facilities. Manual Contents The contents of the manual are: Chapter 1 — Overview — Describes basic hardware and software support and the layers of implementation of SunWindows, the pixrect layer, the sunwindow layer, and the suntool layer. Chapter 2 — Pixel Data and Operations — Describes pixel data and operations in the lowest level output facilities of SunWindows, pixrects, pixrectops, memory pixrects, and text facilities for pixrects. Chapter 3 — Overlapped Windows: Imaging Facilities — Explains image generation on windows which may overlap other windows. Chapter 4 — Window Manipulation — Describes the sunwindow layer facilites for creating, posi- tioning, and controlling windows. Chapter 5 — Input to Application Programs — Discusses how user input is made available to application programs. Chapter 6 — Suntool: Tools and Subwindows — Discusses how to write a tool, and covers crea- tion and destruction of a tool and its subwindows, the strategy for dividing work among subwin- dows, and the use of routines provided to accomplish that work. Chapter 7 — Suntool: Subwindow Packages — Discusses subwindows as building blocks in the construction of a tool, covers the currently existing subwindows, and suggests the approach for creating new kinds of subwindows. Chapter 8 — The Panel Subwindow Package — Describes the use of panels, which are subwin- dows that present information and choices to the application user. Chapter 9 — Suntool: User Interface Utilities Covers user interface utilities, the independent packages for use with the suntools environment, includes the actual window manipulation rou- tines used by tool windows, the icon facility, the selection manager, the fullscreen access mechan- ism, and menus and prompts. Appendix A — Reds and Redlists — Describes the geometric structures used with the sunwin- dow layer and provides a full description of the operations on these structures. - 16 - Appendix B — Sample Toole — Provides an annotated collection of some simple tools to be used both as illustrations and as templates for client programmers. Appendix C — Sample Graphice Programs — Provides an annotated selection of several graphics programs for writing your own graphics programs; includes code for a bouncing ball demonstra- tion and for a “movie camera” program that displays files as frames from a movie. Appendix D — Programming Notes — Contains useful hints for programmers using the SunWin- dows library procedures. Appendix E — Writing a Pixrect Driver — Explains how to to construct a device driver for a pixel-addressable device so that it will provide Sun’s device-independent interface to the frame buffer. Apendix F — Option Subwindow — Describes a subwindow that implements a type of user inter- face to application programs. The material here is being phased out; programmers are encouraged to use the panel subwindow instead. Note: This manual is neither a user guide nor an explanation of the internals of the window sys- tem. It presents the material in a bottom-up fashion with primitive concepts and facilities described first. It is not intended to be read linearly front-to-back; glance at the table of con- tents and the chapters on tools to get a general idea of how to use the rest of the material. The Programmer’s Tutorial to SunWindows supplies the basics needed to build SunWindows tools. The User’s Manual for the Sun Workstation provides user information under sunt ools(l) for SunWindows and under the appropriate entry for the particular application programs. The Beginner’s Guide to the Sun Workstation provides a brief tutorial on general use of the mouse and the SunWindows pop-up menus. A Note About Special Terms Several terms in this manual have meanings distinct from their common definitions or introduce concepts that are specific to programming in the SunWindows environment. We discuss the most important here. The word client indicates a program that uses window system facilities. This is in contrast to user, which refers to a human. Terms referring to display hardware, such as framebuffer, pixel, and rasterop, are used in well- established senses; novices who are confused should consult one of the standard texts, such as Fundamentals of Interactive Computer Graphics by J.D. Foley and A. Van Dam, Addison- Wesley, 1983. The position of the mouse is indicated by a cursor on the screen; this is any small image that moves about the screen in response to mouse motions. The term “cursor” is used elsewhere to indicate the location at which type-in will be inserted, or other editor functions performed. The two concepts are not often distinguished. To keep them distinct, we use the term caret to refer to the type-in location. A menu is a list of related choice items displayed on the screen in response to a user mouse- action. The user chooses one menu item by pointing at it with the cursor. Such menus are - 17 - called transient or pop-up; they are displayed only while a mouse button is depressed, and are typically used for invoking parameterless operations. A red is a structure that defines a rectangle. A rectlist is a structure that defines a list of rects. Up-down encoded keyboards are devices from which it is possible to receive two distinct signals when a key is pressed and then released. An icon is a small form of a window that typically displays an identifying image rather than a portion of the window contents; it is frequently used for dormant application programs. For example, the default icon for a closed Shell Tool is a likeness of a CRT terminal. Chapter 1 Overview 1.1. What is SunWindows? SunWindows is the Sun window system. It is a tool box and parts kit, not a closed, finished, end product. Its design emphasizes extensibility, accessibility at multiple layers, and provision of appropriate parts and development tools. Specific applications are provided here both as exam- ples and because they are valuable for further development. The system is designed to be expanded by clients. The system is explicitly layered with interfaces at several levels for client programs. There is open access to lower levels, and also convenient and powerful facilities for common requirements at higher levels. For instance, it is always possible for a client to write directly to the screen, although in most circumstances it is preferable to employ higher-level routines. 1.2. Hardware and Software Support The Sun Microsystems Workstation provides hardware and software support for the construction of high-quality user interfaces. Hardware features include: • provision of a processor for each user, a prerequisite for powerful, responsive, cost-effective systems; • a bit-mapped display which allows arbitrary fonts and graphics to be used freely to make applications programs easier to learn and use; • hardware support of fast and convenient manipulation of image data; • a mouse pointing device for selecting operations from menus or for pointing at text, graphics and icons; and • an up-down encoded keyboard that supports sophisticated function-key interfaces at once simpler and more efficient than most command languages. Sun software is similarly structured to support high-quality interactions. The software features are: • a uniform interface to varied pixel-oriented devices that allows convenient incorporation of new devices into the system, and clean access to all these devices by application programs; • extended device independence for input such as function keys and locators, as well as for other user-interface features; Revision G of 15 April 1985 1-1 Overview SunWindows Reference Manual • a window management facility that keeps track of multiple overlapping windows, allowing their creation and rearrangement at will. The facility arbitrates screen access, detects des- tructive interactions such as overlapping, and initiates repairs. It also serializes and distri- butes user inputs to the multiple windows, allowing full type-ahead -and mouse-ahead; and e built on all these facilities, an executive and application environment that provides a system for running existing UNIX programs and new applications, taking advantage of icons, menus, prompts, mouse-driven selections, interprocess data exchange, a forms-oriented interface and useful cursor manipulations. 1.3. Layers of Implementation There are three broad layers of SunWindows. These layers may be identified by the libraries that contain their implementations. The organization of the reference part of this manual reflects the three layers as described below. 1. The pixrect level provides a device-independent interface to pixel operations. 2. The sunwindow 1 level implements a manager for overlapping windows, including imaging control, creation and manipulation of windows, and distribution of user inputs. 3. The suntool level implements a multi-window executive and application environment. In its user interface, it includes a number of relatively independent packages, supporting, for instance, menus and selections. 1.3.1. Pixrect Layer Chapter 2 describes the pixrect layer of the system. This level generalizes RasterOp display functions to arbitrary rectangles of pixels. Peculiarities of specific pixel-oriented devices, such as dimensions, addressing schemes, and pixel size and interpretation, are encapsulated in device- specific implementations, which all present the same uniform interface to clients. The concept of a pixrect is quite general; it is convenient for referring to a whole display, as well as to the image of a single character in a font. It may also be used to describe the image which tracks the mouse. There is a balance between functionality and efficiency. All pixrects clip operations that extend beyond their boundaries. Since this may require substantial overhead, clients which can guaran- tee to stay within bounds may disable this feature. Where hardware support exists, it is taken advantage of without sacrificing generality: all pixrects support the same set of operations on their contents. These operations include general raster operations on rectangular areas, vectors, batch opera- tions to handle common applications like text, and compact manipulation of constant or regularly-patterned data. A stencil operation provides spatial, two-dimensional masking of the source pixrect with a mask pixrect to control the areas of the destination pixrect to be written. Color pixrects, as well as monochrome pixrects, are supported. There are uniform operations for accessing a pixrect’s colormap. A colormap maps a pixel value to a screen color. The pixel 1 Note that the term ‘sunwindow’ refers to the layer or level of implementation while the word ‘SunWindows’ is the name of the Sun window system. 1-2 Revision G of 15 April 1985 SunWindows Reference Manual Overview planes affected by other operations can be controlled as well. Monochrome pixrects support the same interface as color pixrects. Programs intended primarily for color pixrects usually produce reasonable images on monochrome pixrects, and vice versa. 1.8.2. Sunwindow Layer Chapters 3 through 5 introduce windows and operations on them. A window is a rectangular display area, along with the process or processes responsible for its contents. This layer of the system maintains a database of windows which may overlap in both time and space. These win- dows may be nested, providing for distinct subwindows within an application’s screen space. Windows may be created, destroyed, moved, stretched or shrunk, set at different levels in the overlapping structure, and otherwise manipulated. The sunwindow level of the system provides facilities for performing all these operations. It also allows definition of the image which tracks the mouse while it is in the window, and inquiry and control over the mouse position. Windows existing concurrently may all access a display; the window system provides locking primitives to guarantee that these accesses do not conflict. Arbitration between windows is also provided in the allocation of display space. Where one win- dow limits the space available to another, it is necessary to provide clipping, so neither interferes with the other’s image. One such conflict handled by the sunwindow layer arises when windows share the same coordinates on the display: one overlaps the other. When one window impacts another window’s image without any action on the second window’s part, SunWindows informs the affected window of the damage it has suffered, and the areas that ought to be repaired. Windows may either recompute their contents for redisplay, or they may elect to have a full backup of their image in main memory, and merely copy the backup to the display when required. On color displays, colormap entries are a scarce resource. When shared among multiple applica- tions, they become even more scarce. Arbitration between windows is provided in the allocation of colormap entries. Provisions are made to share portions of the colormap. Separate collections of windows may reside on separate screens. The user interacts with these multiple screens with his single keyboard and mouse. User inputs are unified into a single stream at this level, so that actions with the mouse and key- board can be coordinated. This unified stream is then distributed to different windows, accord- ing to user or programmatic indications. Windows may be selective about which input events they will process, and rejected events will be offered to other windows for processing. This enables terminal-based programs to run within windows which will handle mouse interactions for them. 1.8.3. Suntool Layer Chapters 6 through 9 of this manual describe the suntool level of the system. While the first two layers provide client interfaces, the suntool level provides the user interface. We refer to an application program that is a client of this level of the window system as a tool. This term covers the one or more programs and processes which do the actual application pro- cessing. It also refers to the collection of windows through which the tool interacts with the user. This collection often includes a special icon, which is a small form the tool may take to be Revision G of 15 April 1985 1-3 Overview SunWindows Reference Manual unobtrusive on the screen but still identifiable. Some examples of tools are a calculator, a bit- map editor, and a terminal emulator. Sun provides a few ready-built tools, several of which are illustrated in Appendix B. Customers can develop their own tools to suit their specific needs. SunWindows provides some common components of tools: « an executive framework that supplies the usual “main loop” of a program and coordinates the activities of the various subwindows; • a standard tool window that frames the active windows of the tool, identifying it with a name stripe at the top and borders around the subwindows. Each tool window has a facility for manipulating itself in the overlapped wundow environment. This includes adjusting its size and position, including layering, and moving the boundaries between subwindows; • several commonly used subwindow types that can be instantiated in-the tool; • a standard scheme for laying out those subwindows; and • a facility that provides a default icon for the tool. The suntools program initializes the window environment. It provides for: » automatic startup of a specified collection of tools; • dynamic invocation of standard tools; • management of the default window called the root window, which underlies all the tools; and • the user interface for leaving the window system. Users who wish some other form of environment management can replace the suntools program, while retaining the tools and supporting utilities. The facilities provided in the suntool library are relatively independent; they can be used with window contexts other than suntools. The icon facility mentioned above is in this category, as are the window manipulation facilities of suntools. There is also a package for presenting menus to the user and interpreting the response. 1-4 Revision G of 15 April 1985 Sun Windows Reference Manual Overview Revision G of 15 April 1985 1-5 Chapter 2 Pixel Data and Operations This chapter discusses pixel data and operations in the lowest-level output facilities of SunWin- dows. These facilities will frequently be accessed indirectly, through higher-level abstractions described in chapters 3 through 9. However, some client implementors will deal at this level, for instance to include new display devices in the window system. The header file includes the header files that you need to work at this level of the window system. It will also suffice to include or . 2.1. Pixrects The fundamental object of pixel manipulation in the window system is the pixrect. A pixrect encapsulates a rectangular array of pixels along with the operations which are defined on that data. Pixrects are designed along the model of objects in an object-oriented programming sys- tem. They combine both data and operations, presenting their clients with a simple interface: a well-defined set of operations produces desired results, and details of representation and imple- mentation are hidden inside the object. The pixrect presents only its dimensions, a pointer to its operations, and a pointer to private data which those operations may use in performing their tasks. Further, the set of operations is the same across all pixrects, though of course their implementations must differ. This object- oriented style allows similar things which differ in small details to be gathered into a unified framework; it allows clients to use the same approach to all of them, and allows implementors to add new members or improve old ones without disturbing clients. The pixrect facility satisfies two broad objectives: ® To provide a uniform interface to a variety of devices for independence from device charac- teristics where they are irrelevant. Such characteristics include the actual device (pixrects may exist in memory and on printers as well as on displays), the dimensions and addressing schemes of the device, and the definition of the pixels, that is, how many bits in each, how they are aligned, and how interpreted. Color and monochrome devices use the same interface. Programs intended primarily for color pixrects usually produce reasonable images on mono- chrome pixrects, and vice versa. • To provide a proper balance of functionality and efficiency for a full range of pixel operations with performance close to that achieved by direct access to the hardware. Pixrect operations include generalized rasterops, vectors, text and other batch operations, compact manipulation of uniform and regularly-patterned data, as well as single-pixel reads and writes. All provide for clipping to the bounds of the rectangle if desired; this facility may be bypassed by clients which can perform it more efficiently themselves. A stencil function provides spatial masking of the source pixrect with a stencil pixrect to control the areas of the destination pixrect to be written. Where specialized hardware exists and can be used for a particular operation, it is Revision G of 15 April 1985 2-1 Pixel Data and Operations SunWindows Reference Manual used, but not at the expense of violating the device-independent interface. 2.1.1. Pixels: Coordinates and Interpretation Pixels in a pixrect are addressed in two dimensions with the origin in the upper left corner, and x and y increasing to the right and down. The coordinates of a pixel in a pixrect are integers from 0 to the pixrect’s width or height minus 1. A pixrect is characterized by a depth, the number of bits required to hold one pixel. A large class of displays uses a single bit to select black or white (or green or orange, depending on the display technology). On these monochrome displays and in memory pixrects one bit deep, a 1 indicates foreground and a 0 background. No further interpretation is applied to memory. The default interpretation on Sun displays is a white background and a black foreground. Other displays use several bits to identify a color or gray level. Typically, though not neces- sarily, the pixel value is used as an index into a colormap, where colors may be defined with higher precision than in the pixel. A common arrangement is to use an 8-bit pixel to choose one of 256 colors, each of which is defined in 24 bits, 8 each of red, green and blue. Memory pixrect depths of 1, 8, 16, and 24 are supported. Frame buffer pixrects are either 1 bit or 8 bits (color) per pixel. You can write depth 1 or 8 pixrects to a color frame buffer. 2.1.2. Geometry Structs As a preliminary to the discussion of pixrects, it is convenient to define a few structs which con- tain useful geometric information. The struct that defines a position in coordinates ( x , y) is: struct pr_pos { int x, y; >; Leaving a pixrect undefined for the moment, this struct defines a point within a specified pixrect: struct pr_prpos { struct pixrect *pr; struct pr_pos pos; }; It contains a pointer to the pixrect and a position within it. The following struct defines the width and height of an area: struct pr_size { int x, y; }; The following struct defines a sub-area within a pixrect: struct pr_subregion { struct pixrect *pr; struct pr_pos pos; struct pr_size size; >; It contains a pointer to the pixrect, an origin for the area, and its width and height. 2-2 Revision G of 15 April 1985 SunWindows Reference Manual Pixel Data and Operations 2.1.8. The Pixrect Struct A particular pixrect is described by a pixrect struct. This combines the definition of a rec- tangular array of pixels and the means of accessing operations for manipulating those pixels: struct pixrect { struct pixrectops *pr_ops; struct pr_size pr_size; int pr_depth; caddr_t pr_data; >; The width and height of the rectangle are given in pr_size, and the number of bits in each pixel in pr_depth. For programmers more comfortable referring to “width” and “height,” there are also two convenient macros: #define pr_width (pr_size.x) #define pr_height (pr_size.y) All other information about the pixrect (in particular, the location and values of pixels), is data private to it. Pixels are manipulated only by the set of pixrect operations described below. These operations will generally use information accessed through pr_data to accomplish their tasks. (This restriction is relaxed somewhat in the case of pixrects whose pixels are stored in memory; this provides an escape to mechanisms outside the pixrect facility for constructing and convert- ing pixrects of differing types. Memory pixrects are described in Memory Pixrects.) 2.2. Operations on Pixrects Procedures are provided to perform the following operations on pixrects: • create and destroy a pixrect (open, region and destroy) • read and write the values of single pixels (get and put) ® use RasterOp functions to affect multiple pixels in a single operation: write from a source to a destination pixrect (rop) write from a source to a destination under control of a mask (stencil) replicate a constant source pattern throughout a destination (replrop) write a batch of sources to different locations in a single destination (batchrop) draw a straight line of a single source value (vector) • read and write a colormap (getcolormap , putcolormap) • select particular bit-planes for manipulation on a color pixrect (getattributes, putat- tributes) Some of these operations are the same for all pixrects, and are implemented by a single pro- cedure. These device-independent procedures are called directly by pixrect clients. Other operations must be implemented differently for each device on which a pixrect may exist. Each pixrect includes a pointer (in its pr_ops) to a pixrectops structure, that holds the addresses of the particular device-dependent procedures appropriate to that pixrect. This allows clients to access those procedures in a device-independent fashion, by calling through the procedure pointer, rather than naming the procedure directly. To facilitate this indirection, the pixrect Revision G of 15 April 1985 2-3 Pixel Data and Operations SunWindows Reference Manual facility provides a set of macros which look like simple procedure calls to generic operations, and expand to invocations of the corresponding procedure in the pixrectops structure. The description of each operation will specify whether it is a true procedure or a macro, since some of the arguments to macros are expanded multiple times, and could cause errors if the arguments contain expressions with side effects. (In fact, two sets of parallel macros are pro- vided, which differ only in whether their arguments use the geometry structs defined above. Each is described with the operation.) 2.2.1. The Pixrectops Struct The pixrectops struct is a collection of pointers to the device-dependent procedures for a partic- ular device: struct pixrectops { int (*pro_rop) () ; int (*pro_stencil) () ; int (*pro_batchrop) () ; int (*pro_nop) () ; int (*pro_destroy) () ; int (*pro_get) () ; int (*pro_put) () ; int (*pro_vector) () ; struct pixrect * (*pro_region) () int (*pro_putcolormap) () ; int (*pro_getcolormap) () ; int (*pro_putattributes) () ; int (*pro_getattributes) () ; All other operations are implemented by device-independent procedures. 2.2.2. Conventions for Naming Arguments to Pixrect Operations In general, the following conventions are used in naming the arguments to pixrect operations: Table 2-1: Argument Name Conventions Argument Meaning d destination s source x and y left and top origins w and h width and height 2-4 Revision G of 15 April 1985 SunWindows Reference Manual Pixel Data and Operations 2.2.3. Pixrect Errors Pixrect procedures which return a pointer to a structure will return NULL when they fail. Other- wise, a return value of PDCERR (-1) indicates failure and 0 indicates success. The section describ- ing each library procedure makes note of any exceptions to this convention. 2.2.4. Creation and Destruction of Pixrects Pixrects are created by the procedures pr_open and mem_create, by the procedures accessed by the macro pr_region, and at compile-time by the macro mpr_static. Pixrects are destroyed by the procedures accessed by the macro pr_destroy. mem_create and mpr-_static are discussed in the section Memory Pixrects] the rest of these are described here. 2. 2. 4-1. Open: Create a Primary Display Pixrect The properties of a non-memory pixrect depend on an underlying UNIX device. Thus, when creating the first pixrect for a device you need to open it by a call to: struct pixrect *pr_open (devicename) char * devicename; The default device name for your display is /dev/fb (fb stands for framebuffer). Any other device name may be used provided that it is a display device, the kernel is configured for it, and it has pixrect support, for example, /dev/bwoneO, /dev/bwtwoO, /dev/cgoneO or /dev/c gtwoO. pr_open does not work for creating a pixrect whose pixels are stored in memory; that function is served by the procedure mem_create, discussed in the section Memory Pixrects. pr_open returns a pointer to a primary pixrect struct which covers the entire surface of the named device. If it cannot, it returns NULL, and prints a message on stderr. 2.2. 4- 2. Region: Create a Secondary Pixrect Given an existing pixrect, it is possible to create another pixrect which refers to some or all of the same pixels of the same pixrect. This is called a secondary pixrect, and is created by a call to the procedures invoked by the macros pr_region and prs_region: #define struct pixrect *pr_region (pr , x, y, w, h) struct pixrect *pr; int x, y, w, h; #define struct pixrect *prs_region (subreg) struct pr_subregion subreg; The existing pixrect is addressed by pr; it may be a pixrect created by pr_open, mem_create or mpr_static (a primary pixrect); or it may be another secondary pixrect created by a previous call to a region operation. The rectangle to be included in the new pixrect is described by x, y, w and h in the existing pixrect; (x, y) in the existing pixrect will map to (0, 0) in the new one. prs_region does the same thing, but has all its argument values col- lected into the single struct subreg. Each region procedure returns a pointer to the new Revision G of 15 April 1985 2-5 Pixel Data and Operations SunWindows Reference Manual pixrect. If it fails, it returns NULL, and prints a message on stderr. If an existing secondary pixrect is provided in the call to the region operation, the result is another secondary pixrect referring to the underlying primary pixrect; there is no further con- nection between the two secondary pixrects. Generally, the distinction between primary and secondary pixrects is not important; however, no secondary pixrect should ever be used after its primary pixrect is destroyed. 2.24.3. Close / Destroy: Release a Pixrect ’s Resources The following macros invoke device-dependent procedures to destroy a pixrect, freeing resources that belong to it: #define pr_close(pr) struct pixrect *pr; #define pr_destroy (pr) struct pixrect *pr; ^define prs_destroy (pr) struct pixrect *pr ; The procedure returns 0 if successful, PDCERR if it fails. It may be applied to either primary or secondary pixrects. If a primary pixrect is destroyed before secondary pixrects which refer to its pixels, those secondary pixrects are invalidated; attempting any operation but destroy on them is an error. The three macros are identical; they are all defined for reasons of history and stylistic consistency. 2.2.5. Single-Pixel Operations The next two operations manipulate the value of a single pixel. 2. 2. 5.1. Get: Retrieve the Value of a Single Pixel The following macros invoke device-dependent procedures to retrieve the value of a single pixel: #define pr_get(pr, x, y) struct pixrect *pr; int x, y; #define prs_get (srcprpos) struct pr_prpos srcprpos; pr indicates the pixrect in which the pixel is to be found; x and y are the coordinates of the pixel. For prs_get, the same arguments are provided in the single struct srcprpos. The value of the pixel is returned as a 32-bit integer; if the procedure fails, it returns PIX_ERR. 2-6 Revision G of 15 April 1985 SunWindows Reference Manual Pixel Data and Operations 2. 2. 5. 2. Put: Store a Value into a Single Pixel The following macros invoke device-dependent procedures to store a value in a single pixel: #define pr_put(pr, x, y, value) struct pixrect *pr; int x ( y, value; #def ine prs_put (dstprpos , value) struct pr_prpos dstprpos; int value; pr indicates the pixrect in which the pixel is to be found; x and y are the coordinates of the pixel. For prs_put, the same arguments are provided in the single struct dstprpos. value is truncated on the left if necessary, and stored in the indicated pixel. If the procedure fails, it returns PIX_ERR. 2.2.6. Constructing an Op Argument The multi-pixel operations described in the next section all use a uniform mechanism for specify- ing the operation which is to produce destination pixel values. This operation is given in the op argument and includes several components. Generally, op identifies a RasterOp. This is a logical function of two or three inputs; it com- putes the value of each pixel in the destination as a function of the previous value of that desti- nation pixel, of a corresponding source pixel, and possibly a corresponding pixel in a mask. Two other facilities are also specified in the op argument: • a single, constant, source value may be specified as a color in op, and • the clipping which is normally performed by every pixrect operation may be turned off by set- ting the PDLDONTCLIP flag in the op. We describe these three components of the op argument in order. 2. 2. 6.1. Specifying a RasterOp Function Four bits of the op are used to specify one of the 16 distinct logical functions which combine monochrome source and destination pixels to give a monochrome result. This encoding is gen- eralized to pixels of arbitrary depth by specifying that the function is applied to corresponding bits of the pixels in parallel. This emphasizes that the pixrects must be of the same depth. Some functions are much more common than others; the most useful are identified in the table Useful Combinations of Raster Ops. A convenient and intelligible form of encoding the function into four bits is supported by the fol- lowing definitions: #def ine PIX_SRC 0x18 #define PIX_DST 0x14 #def ine PIX_NOT(op) (OxlE & (’op)) PDCSRC and PDCDST are defined constants, and PDCNOT is a macro. Together, they allow a desired function to be specified by performing the corresponding logical operations on the Revision G of 15 April 1985 2-7 Pixel Data and Operations Sun Windows Reference Manual appropriate constants. (The explicit definition of PIX_NOT is required to avoid inverting non- function bits of op). A particular application of these logical operations allows definition of set and clear operations. The definition of the set operation that follows is always true, and hence sets the result: #def ine PIX_SET (PIX_SRC | PIX_NOT (PIX_SRC) ) The definition of the clear operation is always false, and hence clears the result: #define PIX_CLR (PIX_SRC & PIX_NOT (PIX_SRC) ) Other common RasterOp functions are defined in the following table: Table 2-2: Useful Combinations of RasterOps Op with Value Result PIX_SRC write (same as source argument) PIX_DST no-op (same as destination argument) PIX_SRC 1 PIX_DST paint (OR of source and destination) PIX_SRC & PIX_DST mask (AND of source and destination) PIX_NOT(PIX_SRC) & PIX_DST erase (AND destination with negation of source) PIX_NOT (PIX_DST) invert area (negate the existing values) PIX_SRC ~ PIX_DST inverting paint (XOR of source and destination) 2. 2. 6. 2. Ops with a Constant Source Value In certain cases, it is desirable to specify an infinite supply of pixels, all with the same value. This is done by using NULL for the source pixrect, and encoding a color in bits 5 - 31 of the op argument. The following macro supports this encoding: #def ine PIX_COLOR (color) ( (color) <<5) This macro extracts the color from an op: #def ine PIX_OPCOLOR (op) ((op)>>5) If no color is specified in an op, 0 appears by default. The color specified in the case of a null source pixrect or to specify the color of the ’ink’ in a depth 1 Note that the color is not part of the function component of an op argument; part of an argument to PEX_NOT. The color component of op is also used when a depth 1 pixrect is written to a In this case: o if the value of the source pixels = 0, they are painted 0, or background. the op is used in pixrect. it should never be depth >1 pixrect. 2-8 Revision G of 15 April 1985 SunWindows Reference Manual Pixel Data and Operations ® if the value of the source pixels = 1, they are painted color. If the color component of op is 0 (e.g., because no color was specified), the color will default to -1 (foreground). 2. 2.6. 3. Controlling Clipping in the Raster Op Pixrect operations normally clip to the bounds of the operand pixrects. Sometimes this can be done more efficiently by the client at a higher level. If the client can guarantee that only pixels which ought to be visible will be written, it may instruct the pixrect operation to bypass clipping checks, thus speeding its operation. This is done by setting the following flag in the op argu- ment: #def ine PIX_DONTCLIP Oxl The result of a pixrect operation is undefined and may cause a memory fault if PBCDONTCLIP is set and the operation goes out of bounds. Note that the PDCDONTCLIP flag is not part of the function component of an op argument; it should never be part of an argument to PEX_NOT. 2. 2.6.4. Examples of Complete Op Argument Specification A very simple op argument will specify that source pixels be written to a destination, clipping as they go: op = PIX_SRC; A more complicated example will be used to affect a rectangle (known to be valid) with a con- stant red color defined elsewhere. (The function is syntactically correct; it’s not clear how useful it is to XOR a constant source with the negation of the OR of the source and destination): op = (PIX_SRC * PIX_NOT (PIX_SRC | PIX_DST) ) | PIX_COLOR (red) | PIX_DONTCLIP 2.2.7. Multi-Pixel Operations The following operations all apply to multiple pixels at one time: rop, stencil , replrop, batchrop, and vector. With the exception of vector, they refer to rectangular areas of pixels. They all use a common mechanism, the op argument described in the previous section, to specify how pixels are to be set in the destination. 2. 2.7.1. Rop: RasterOp Source to Destination Device-dependent procedures invoked by the following macros perform the indicated raster operation from a source to a destination pixrect: #def ine pr_rop(dpr, dx, dy, dw, dh, op, spr, sx, sy) struct pixrect *dpr, *spr; int dx, dy, dw, dh, op, sx, sy; Revision G of 15 April 1985 2-9 Pixel Data and Operations SunWindows Reference Manual #define prs_rop (dstregion, op, srcprpos) struct pr_subregion dstregion; int op ; struct pr_prpos srcprpos; dpr addresses the destination pixrect, whose pixels will be affected; (dx, dy) is the origin (the upper-left pixel) of the affected rectangle; dw and dh are the width and height of that rectan- gle. spr specifies the source pixrect, and (sx, sy) an origin within it. spr may be NULL, to indicate a constant source specified in the op argument, as described previously; in this case sx and sy are ignored. op specifies the operation which is performed; its construction is described in preceding sections. For prs_rop, the dpr, dx, dy, dw and dh arguments are all collected in a pr_subregion structure, defined previously under Geometry Structa. Raster operations are clipped to the source dimensions, if those are smaller than the destination size given. Rop procedures return PEX_ERR if they fail, 0 if they succeed. Source and destination pixrects generally must be the same depth. The only exception allows depth=l pixrects to be sources to a destination of any depth. In this case, source pixels = 0 are interpreted as 0 and source pixels = 1 are written as the maximum value which can be stored in a destination pixel. 2. 2.7. 2. Stencil: Raster Ops through a Mask Device-dependent procedures invoked by the following macros perform the indicated raster operation from a source to a destination pixrect only in areas specified by a third (stencil) pix- rect: #define pr_stencil (dpr , dx, dy, dw, dh, op, stpr , stx, sty , spr , sx, sy) struct pixrect *dpr, *stpr, *spr; int dx, dy, dw, dh, op, stx, sty, sx, sy; #define prs_stencil (dstregion, op, stenprpos, srcprpos) struct pr_subregion dstregion; int op ; struct pr_prpos stenprpos, srcprpos; Stencil is identical to rop except that the source pixrect is written through a stencil pixrect which functions as a spatial write-enable mask. The stencil pixrect must be a memory pixrect with depth = 1. The indicated raster operation is applied only to destination pixels where the stencil pixrect is non-zero. Other destination pixels remain unchanged. The rectangle from (sx, sy) in the source pixrect spr is aligned with the rectangle from (stx, sty) in the stencil pix- rect stpr, and written to the rectangle at (dx, dy) with width dw and height dh in the desti- nation pixrect dpr. The source pixrect spr may be NULL, in which case the color specified in op is painted through the stencil. Clipping restricts painting to the intersection of the destine tion, stencil and source rectangles. Stencil procedures return PDC.ERR if they fail, 0 if they succeed. 2-10 Revision G of 15 April 1985 SunWindows Reference Manual Pixel Data and Operations 2.2.7. 8. Replrop: Replicating the Source Ptxrect Often the source for a raster operation consists of a pattern that is used repeatedly, or replicated to cover an area. If a single value is to be written to all pixels in the destination, the best way is to specify that value in the color component of a rop operation. But when the pattern is larger than a single pixel, a mechanism is needed for specifying the basic pattern, and how it is to be laid down repeatedly on the destination. The pr_replrop procedure replicates a source pat- tern repeatedly to cover a destination area: pr_replrop (dpr, dx, dy, dw, dh, op, spr, sx, sy) struct pixrect *dpr, *spr; int dx, dy, dw, dh, op, sx, sy; #de fine prs_replr op (dsubreg, op, sprpos) struct pr_subregion dsubreg; struct pr_prpos sprpos; dpr indicates the destination pixrect. The area affected is described by the rectangle defined by dx, dy, dw, dh. spr indicates the source pixrect, and the origin within it is given by sx, sy. The corresponding prs_replrop macro generates a call to pr_replrop, expanding its dsubreg into the five destination arguments, and sprpos into the three source arguments, op specifies the operation to be performed, as described above under Constructing Op Argu- ments. The effect of replrop is the same as though an infinite pixrect were constructed using copies of the source pixrect laid immediately adjacent to each other in both dimensions, and then a rop was performed from that source to the destination. For instance, a standard gray pattern may be painted across a portion of the screen by constructing a pixrect that contains exactly one tile of the pattern, and by using it as the source pixrect. The alignment of the pattern on the destination is controlled by the source origin given by sx, sy. If these values are 0, then the pattern will have its origin aligned with the position in the destination given by dx, dy. Another common method of alignment preserves a global align- ment with the destination, for instance, in order to repair a portion of a gray. In this case, the source pixel which should be aligned with the destination position is the one which has the same coordinates as that destination pixel, modulo the size of the source pixrect. replrop will perform this modulus operation for its clients, so it suffices in this case to simply copy the destination position (dx, dy) into the source position (sx, sy). Replrop procedures return PDCERR if they fail, 0 if they succeed. Internally replrop may use rop procedures. In this case, rop errors are detected and returned by replrop. 2. 2. 7. 4- Batch RasterOp: Multiple Source to the Same Destination Applications such as displaying text perform the same operation from a number of source pix- rects to a single destination pixrect in a fashion that is amenable to global optimization. Device- dependent procedures invoked by the following macros perform raster operations on a sequence of sources to successive locations in a common destination pixrect: Revision G of 15 April 1985 2-11 Pixel Data and Operations SunWindows Reference Manual #define pr_batchrop (dpr , dx, dy, op, items, n) struct pixrect *dpr; int dx, dy, op, in- struct pr_prpos items [ ] ; #define prs_batchrop (dstpos , op, items, n) struct pr_prpos dstpos; int op , n ; struct pr_prpos items [ ] ; items is an array of pr_prpos structures used by a batchrop procedure as a sequence of source pixrects. Each item in the array specifies a source pixrect and an advance in x and y. The whole of each source pixrect is used, unless it needs to be clipped to fit the destination pix- rect: advance is used to update the destination position, not as an origin in the source pixrect. Batchrop procedures take a destination, specified by dpr, dx and dy, or by dstpos in the case of prs_batchrop; an operation specified in op, as described in Constructing Op Argu- ments above, and an array of pr_prpos addressed by the argument items, and whose length is given in the argument n. The destination position is initialized to the position given by dx and dy . Then, for each item, the offsets given in pos are added to the previous destination position, and the operation specified by op is performed on the source pixrect and the corresponding rectangle whose origin is at the current destination position. Note that the destination position is updated for each item in the batch, and these adjustments are cumulative. The most common application of batchrop procedures is in painting text; additional facilities to support this application are described below under Text Facilities for Pixrects. Note that the definition of batchrop procedures supports variable-pitch and rotated fonts, and non-roman writ- ing systems, as well as simpler text. Batchrop procedures return PIX_ERR if they fail, 0 if they succeed. Internally batchrop may use rop procedures. In this case, rop errors are detected and returned by batchrop. 2. 2. 7. 5. Vector: Draw a Straight Line Device-dependent procedures invoked by the following macros draw a vector one unit wide between two points in the indicated pixrect: #define pr_vector (pr , xO, yO, xl, yl, op, value) struct pixrect *pr; int xO, yO, xl, yl, op, value; #define prs_vector (pr , posO, posl, op, value) struct pixrect *pr; struct pr_pos posO, posl; int op, value; Vector procedures draw a vector in the pixrect indicated by pr, with endpoints at (xO, yO) and (xl, yl), or at posO and posl in the case of prs_vector. Portions of the vector lying outside the pixrect are clipped as long as PDCDONTCLIP is 0 in the op argument. The op argu- ment is constructed as described previously under Constructing Op Arguments ; and value specifies the resulting value of pixels in the vector. If the color in op is non-zero, it takes pre- cedence over the value argument. 2-12 Revision G of 15 April 1985 SunWindows Reference Manual Pixel Data and Operations 2.2. 7.6. Draw Curved Shapes (pr_traprop) pr_traprop is an advanced pixrect operation analogous to pr_rop. pr_traprop operates on a region called a trapezon, rather than on a rectangle. A trapezon is a region with an irregular boundary. Like a rectangle, a trapezon has four sides: top, bottom, left, and right. The top and bottom sides of a trapezon are straight and horizontal. A trapezon differs from a rectangle in that its left and right sides are irregular curves, called falls, rather than straight lines. A fall is a line of irregular shape. Vertically, a fall may only move downward. Horizontally, a fall may move to the left or to the right, and this horizontal motion may reverse itself. A fall may also sustain pure horizontal motion, that is, horizontal motion with no vertical motion. The figures below show a typical trapezon with source and destination pixrects, and some exam- ples of filled regions that were drawn by pr_traprop. dest pr source pr Figure 2-1: Typical trapezon with source and destination pixrects Figure 2-2: Some figures drawn by pr_traprop Revision G of 15 April 1985 2-13 Pixel Data and Operations Sun Windows Reference Manual pr_traprop (dpr, struct struct int dx, dy, pixrect pr_trap dx, dy. t , op , spr , *dpr , * spr ; t; sx, sy op; sx. sy) dpr and spr are pointers to the destination and source pixrects, respectively, t is the trapezon to be used. dx and dy specify an offset into the destination pixrect. sx and sy specify an offset into the source pixrect. op is an op-code as specified previously (see the section entitled Constructing an Op Argument). struct pr_trap struct pr_fall ‘left, ‘right; int yO, yl; }; struct pr_fall { struct pr__pos pos; struct pr_chain * chain; }; struct pr_chain ■( struct pr_chain ‘next; struct pr_size size; int ‘bits; }: pr_traprop performs a rasterop from the source to the destination, clipped to the trapezon’s boundaries. A program must call pr_traprcp once per trapezon; therefore this procedure must be called at least twice to draw the letter ‘A’ in the figure Some figures drawn by pr_traprop. The source pixrect is aligned with the destination pixrect; the pixel at (sx,sy) in the source pix- rect goes to the pixel at (dx,dy) in the destination pixrect (see the figure Typical trapezon with source and destination pixrects). Positions within the trapezon are relative to position (dx,dy) in the destination pixrect. Thus, a position defined as (0,0) in the trapezon would actually be at (dx,dy) in the destination pixrect. The structure pr_trap defines the boundaries of a trapezon. A trapezon consists of pointers to two falls (* left and ‘right) and two y coordinates specifying the top and bottom of the tra- pezon (yO and yl). Note that the trapezon’s top and bottom may be of zero width; yO and yl may simply serve as points of reference. Each fall consists of a starting position (pos) and a pointer to the head of the list of chains describing the path the fall is to take (‘chain). A fall may start anywhere above the trapezon and end anywhere below it. pr_traprop ignores the portions of a fall that lie above and below the trapezon. If a fall is shorter than the trapezon, pr_traprop will clip the trapezon horizontally to the endpoint of the fall in question. The figure Trapezon with clipped falls illus- trates the way this works. A chain is a member of a linked list of structures that describes the movement of the fall. Each chain describes a single segment of the fall. Each chain consists of a pointer to the next member of the chain (‘next), the size of the bounding box for the chain (size), and a pointer to a bit 2-14 Revision G of 15 April 1985 SunWindows Reference Manual Pixel Data and Operations •vector containing motion commands (*bits). Please see the section Geometry Structs for a description of the pr_size structure. Each chain may specify motion to the right and/or down, or motion to the left and/or down; however, a single chain may not specify both rightward and leftward motion. Remember that motion may not proceed upward, and that straight horizontal motion is permitted. The x value of the chain’s size determines the direction of the motion: a positive x value indi- cates rightward motion, while a negative x value indicates leftward motion. The y value of the chain’s size must always be positive, since a fall may not move upward (in the direction of negative y). A chain’s bit vector is a command string that tells pr_traprop how to draw each segment of the fall. Each set (1) bit in the vector is a command to move one pixel horizontally and each clear (0) bit is a command to move one pixel vertically. The bits within the bit vector are stored in byte order, from most significant bit to least significant bit. This ordering corresponds to the left-to-right ordering of pixels within a memory pixrect. The fall begins at the starting position specified in pr_fall. The motion proceeds downward as specified in the first bit vector in the chain, from the high-order bit to the low-order bit. When the fall reaches the bottom of the bounding box, it continues at the top of the next chain’s bounding box. Note that the fall will always begin and end at diagonally opposite corners of a given bounding box. If a bit vector specifies a segment of the fall that would run outside of the bounding box, pr_traprop clips that segment of the fall to the bounding box. This would occur when the sum of the l’s in a chain’s bit vector exceeds the chain’s x size, or when the sum of the 0’s in the chain’s bit vector exceeds the chain’s y size. When this happens, the segment in question runs along the edge of the bounding box until it reaches the corner of the bounding box diagonally opposite to the corner in which it started. If the fall is to have a straight vertical segment, the x size of its chain must be 0. If the fall is to have a straight horizontal segment, the y size of its chain must be 0. Revision G of 15 April 1985 2-15 Pixel Data and Operations SunWindows Reference Manual The following program draws the octagon shown in the figure Some figures drawn by pr_traprop". Make sure to give cc the library argument -lpixrect. #include int shallowsteep [] = {Oxbbbbbbbb , Oxbbbbbbbb, 0x44444444, 0x44444444}, steepshallow[] = {0x44444444, 0x44444444, Oxbbbbbbbb, Oxbbbbbbbb}; struct pr_chain leftl = {0, {64, 64}, steepshal low} , leftO = {fileftl , {-64, 64}, shallowsteep}, rightl = {O, {-64, 64}, steepshal low}, rightO = {firightl, {64, 64}, shallowsteep}; struct pr_fall left_oct = {{0, O}, &leftO}, right_oct = {{O, O}, firightO}; struct pr_trap octagon = {&left_oct, &right_oct, 0, 128}; main () { pr_traprop (pr_open ("/dev/fb") , 576, 450, octagon, PIX_SET, O, O, O) > pr_chain specifies the left lower, the left upper, the right lower, and the right upper sides of the octagon, in that order. pr_fall specifies first the left side, then the right side of the octa- gon. Each of the eight sides of the octagon is half a chain. The two upper left sides correspond to chain leftO. The bits start out with mostly l’s (Oxb is binary 1011) for the shallow uppermost left edge. They turn to mostly O’s (0x4 is binary 0100) for the next edge down, which is steeper. 2.2. 7.7. Polygon: Textured Polygons with Holes pr_polygon_2 draws a polygon in a pixrect. The polygon can have holes. In addition, you can fill it with an image or a texture. You invoke pr_polygon_2 as follows: pr_polygon_2 (dpr , dx, dy, nbnds, npts, vlist, op, spr, sx, sy) struct pixrect *dpr, *spr; int dx, dy int nbnds, npts In- struct pr_pos ‘vlist; int op, sx, sy; This routine is like pr_rop except that nbnds, npts and vlist specify the destination region instead of (dw,dh) . nbnds is the number of individual closed boundaries (vertex lists) in the polygon. For example, the polygon may have one boundary for its exterior shape and several boundaries delimiting inte- rior holes. The boundaries may self intersect or intersect each other. Those pixels having an odd wrapping number are painted. That is, if any line connecting a pixel to infinity crosses an odd number of boundary edges, the pixel will be painted. For each of the nbnds boundaries npts specifies the number of points in the boundary. Hence the npts array is nbnds in length. The vlist contains all of the boundary points for all of 2-16 Revision G of 15 April 1985 SunWindows Reference Manual Pixel Data and Operations the boundaries. The number of points in order are npts[0]+...+npts[nbnds— 1], pr_polygon_2 joins the last point and first point to close each boundary. The spr source pixrect fills the interior of the polygon as in pr_rop. The position sx,sy in spr coordinates coincides with position dx, dy in dpr coordinates. If sx = -5 and sy = -10, for example, the source pixrect is positioned at (dx+5, dy+10) in dpr coordinates. pr_polygon_2 clips to both spr and dpr except in the case of NULL spr, where the polygon is filled with the color value in op. The source offset sx,sy is used to superimpose the source image over the polygon. The spr must have depth less than or equal to the depth of dpr. A point (pts [n] . x, pts [n] .y) in the boundary of a polygon is mapped to (dx + pts [n] . x, dy + pts [n] .y) . 2.2.8. Colormap Access A colormap is a table which translates a pixel value into 8-bit intensities in red, green, and blue. For a pixrect of depth n, the corresponding colormap will have 2 n entries. The two most com- mon cases are depth=l (monochrome with two entries) and depth=8 (with 256 entries). Memory pixrects do not have colormaps. 2. 2. 8.1. Get Colormap The following macros invoke device-dependent procedures to read all or part of a colormap into arrays in memory: #define pr_getcolormap (pr , index, count, red, green, blue) struct pixrect *pr; int index, count; unsigned char red [ ], green [ ], blue[ ]; ^define prs_getcolormap (pr, index, count, red, green, blue) struct pixrect *pr; int index, count; unsigned char red [ ], green [ ], blue [ ] ; These two macros have identical definitions; both are defined to allow consistent use of one set of names for all operations. pr identifies the pixrect whose colormap is to be read; the count entries starting at index (zero origin) are read into the three arrays. For monochrome pixrects the same value is read into corresponding elements of the red, green and blue arrays. These array elements will have their bits either all cleared, indicating black, or all set, indicating white. By default, the Oth ( background) element is white, and the 1st (foreground) element is black. Colormap procedures return -1 if the index or count are out of bounds, and 0 if they succeed. 2. 2.8. 2. Put Colormap The following macros invoke device-dependent procedures to store from memory into all or part of a colormap: Revision G of 15 April 1985 2-17 Pixel Data and Operations SunWindows Reference Manual ^define pr_putcolormap (pr , index, count, red, green, blue) struct pixrect *pr; int index, count; unsigned char red [ ], green [ ], blue[ ]; #define prs_putcolormap (pr , index, count, red, green, blue) struct pixrect *pr; int index, count; unsigned char red [ ], green [ ], blue[ ]; These two macros have identical definitions; both are defined to allow consistent use of one set of names for all operations. The count elements starting at index (zero origin) in the colormap for the pixrect identified by pr are loaded from corresponding elements of the three arrays. For monochrome pixrects, the only value considered is red[0]. If this value is 0, then the pix- rect will be set to a dark background and light foreground. If the value is non-zero, the fore- ground will be dark, e.g. black-on-white. Monochrome pixrects are dark-on-light by default. Note: Full functionality of the colormap is not supported for depth=l pixrects. Colormap changes to depth=l pixrects apply only to subsequent operations whereas a colormap change to a color device instantly changes all affected pixels on the display surface. 2. 2. 8.3. Provision for Inverted Video Pixrects Video inversion is accomplished by manipulation of the colormap of a pixrect. The colormap of a depth=l pixrect has two elements. The following procedures provide video inversion control: pr_blackonwhite (pr , min, max) struct pixrect *pr; int min , max ; pr_whiteonblack (pr , min, max) struct pixrect *pr; int min, max; pr_reversevideo (pr, min, max) struct pixrect *pr; int min, max; In each procedure, pr identifies the pixrect to be affected; min is the lowest index in the color- map, specifying the background color, and max is the highest index, specifying the foreground color. These will most often be 0 and 1 for monochrome pixrects; the more general definitions allow colormap-sharing schemes, such as the one described in Colormap Sharing, in the chapter Overlapped Windows: Imaging Facilities. “Black-on-white” means that zero (background) pixels will be painted at full intensity, which is usually white. pr_blackonwhite sets all bits in the entry for colormap location min and clears all bits in colormap location max. “White-on-black” means that zero (background) pixels will be painted at minimum intensity, which is usually black. pr„whiteonblack clears all bits in colormap location min and sets all bits in the entry for colormap location max. 2-18 Revision G of 15 April 1985 SunWindows Reference Manual Pixel Data and Operations pr_reversevideo exchanges the min and max color intensities. These procedures are ignored for memory pixrects. Note: These procedures are intended for global foreground/background control, not for local highlighting. For monochrome frame buffers, subsequent operations will have inverted intensities. For color frame buffers, the colormap is modified immediately, which affects everything in the display. 2.2.9. Attributes for Bitplane Control In a color pixrect, it is often useful to define bitplanes which may be manipulated independently; operations on one plane leave the other planes of an image unaffected. This is normally done by assigning a plane to a constant bit position in each pixel. Thus, the value of the ith bit in all the pixels defines the ith bitplane in the image. It is sometimes beneficial to restrict pixrect opera- tions to affect a subset of a pixrect’s bitplanes. This is done with a bitplane mask. A bitplane mask value is stored in the pixrect’s private data and may be accessed by the attribute opera- tions. 2. 2. 9.1. Get Attributes Device-dependent procedures invoked by the following macros retrieve the mask which controls which planes in a pixrect are affected by other pixrect operations: #define pr_getattributes (pr , planes) struct pixrect *pr; int ‘planes; #define prs_getattributes (pr , planes) struct pixrect *pr; int ‘planes; pr identifies the pixrect; its current bitplanes mask is stored into the word addressed by planes. If planes is NULL, no operation is performed. The two macros are identically defined; both are provided to allow consistent use of the same style of names. 2. 2. 9. 2. Put Attributes Device-dependent procedures invoked by the following macro manipulate a mask which controls which planes in a pixrect are affected by other pixrect operations: #define pr_putattributes (pr , planes) struct pixrect *pr; int ‘planes; #define prs_putattributes (pr , planes) struct pixrect *pr; int ‘planes; Revision G of 15 April 1985 2-19 Pixel Data and Operations SunWindows Reference Manual The two macros are identically defined; both are provided to allow consistent use of the same style of names. pr identifies the pixrect to be affected. The *p lanes argument is a pointer to a bitplane write-enable mask. Only those planes corresponding to mask bits having a value of 1 will be affected by subsequent pixrect operations. If *planes is NULL, no operation is performed. Note: If any planes are masked off by a call to pr_putattributes, no further write access to those planes is possible until a subsequent call to pr_put attributes unmasks them. How- ever, these planes can still be read. 2.2.10. Efficiency Considerations For maximum execution speed, remember the following points when you write pixrect programs: © pr_get and pr_put are relatively slow. For fast random access of pixels it is usually faster to read an area into a memory pixrect and address the pixels directly. © pr_rop is fast for large rectangles. s pr.vector is fast. ® functions run faster when clipping is turned off. Do this only if you can guarantee that all accesses are within the pixrect bounds. • pr_rop is three to five times faster than pr_stencil • pr_batch_rop cuts down the overhead of painting many small pixrects. 2.3. Text Facilities for Pixrects Displaying text is an important task in many applications, so pixrect-level facilities are provided to address it directly. These facilities fall into two main categories: a standard format for describing fonts and character images, with routines for processing them; and a set of routines which take a string of text and a font, and handle various parts of painting that string in a pix- rect. 2.8.1. Pixfonts and Pixchars The following two structures describe fonts and character images for pixrect-level text facilities: struct pixchar i struct pixrect *pc_pr; struct pr_pos pc_home; }; struct pr_pos pc_adv; struct pixfont { struct pr_size p f_de fault size; >; struct pixchar pf_char [256] ; 2-20 Revision G of 15 April 1985 SunWindows Reference Manual Pixel Data and Operations The pixchar defines the format of a single character in a font. The actual image of the char- acter is a pixrect (a separate pixrect for each character) addressed by pc_pr. The entire pix- rect gets painted. Characters that do not have a displayable image will have NULL in their entry in pc_pr. pc_home is the origin of pixrect pc_pr (its upper left corner) relative to the character origin. A character’s origin is the leftmost end of its baseline, which is the lowest point on characters without descenders. The figure below illustrates the pc_pr origin and the character origin. The leftmost point on a character is normally its origin, but kerning or mandatory letter spacing may move the origin right or left of that point. pc_adv is the amount the destination position is changed by this character; that is, the amounts in pc_adv added to the current character origin will give the origin for the next character. While normal text only advances horizontally, rotated fonts may have a vertical advance. Both are provided for in the font. A pixfont contains an array of pixchars, indexed by the character code; it also contains the size (in pixels) of its characters when they are all the same. (If the size of a font’s characters varies in one dimension, that value in pf_defaultsize will not have anything useful in it; however, the other may still be useful. Thus, for non-rotated variable-pitch fonts, pf_defaultsize .y will still indicate the unleaded interline spacing for that font.) Note: The definition of a pixfont is expected to change. Figure 2-4: Character and pc_pr origins Revision G of 15 April 1985 2-21 Pixel Data and Operations SunWIndows Reference Manual 2.8.2. Operations on Pixfonts Before a client may use a font, it must ensure that the font has been loaded into virtual memory; this is done with pf_open: struct pixfont *pf_open (name) char ‘name; This procedure opens the file with the given name. The file should be a font file as described in vfont{ 5): the file is converted to pixfont format, allocating memory for its associated structs and reading in the data for it from disk. A NULL is returned if the font cannot be opened. The procedure: struct pixfont *pf_default () performs the same function for the system default font, normally a fixed-pitch, 15-point sans serif font with upper-case letters 12 pixels high. If the environment parameter DEFAULTJFONT is set, its value will be taken as the name of the font file to be opened by pf_de fault. The entire path name of the font file must be specified, for example: myfont = pf_open ("/usr/lib/fonts/fixedwidthfonts/screen .r . 7") ; Note: p f_open and pf_de fault load a new copy of the font every time they are called, even if the font has already been loaded. To conserve memory, clients may use pw_pfsysopen, described in Overlapped Windows: Imaging Facilities, or take care only to open a font once in a process. When a client is finished with a font, it should call pf_close to free the memory associated with it: pf_close (pf) struct pixfont *pf; pf should be a font handle returned by a previous call to pf_open or pf_de fault. 2.8.8. Pixrect Text Display Characters are written into a pixrect with the pf_text procedure: pf_text (where, struct int struct char op, font, text) pr_prpos where; op; pixfont ‘font; ‘text; The where argument is the destination for the start of the text (nominal left edge, baseline; see Pixfonts ); op is the raster operation to be used in writing the text, as described in Constructing Op Arguments ; font is a pointer to the font in which the text is to be displayed; and text is the actual null-terminated string to be displayed. No error indicators are returned. Note: The color specified in the op specifies the color of the ink. The background of the text is painted 0 (background color). The following procedure paints “transparent” text: it doesn’t disturb destination pixels in blank areas of the character’s image: 2-22 Revision G of 15 April 1985 SunWindows Reference Manual Pixel Data and Operations p f_ttext (where , op, font, text) struct pr_prpos where; int op ; struct pixfont *font; char ‘text; The arguments to this procedure are the same as for pf_text. The characters’ bitmaps are used as a stencil, and the color specified in op is squirted through the stencil. No error indica- tors are returned. (For monochrome pixrects, the same effect can be achieved by using PDCSRC j PDCDST as the function in the op; this procedure is for color pixrects.) Auxiliary procedures used with pf_text include: struct pr_size pf_textbatch (where, lengthp, font, text) struct pr_pos where []; int * lengthp ; struct pixfont ‘font; char ‘text; struct pr_size pf_textwidth (len, font, text) int len; struct pixfont ‘font; char ‘text; p f _textbatch is used internally by pf_text; it constructs an array of pr_pos structures and records its length, as required by batchrop (see Batch Ratter Op), where should be the address of the array to be filled in, and lengthp should point to a maximum length for that array. text addresses the null-terminated string to be put in the batch, and font refers to the pixfont to be used to display it. When the function returns, ‘lengthp will refer to a word containing the number of pr_pos structures actually used for text. The pr_size returned is the sum of the pc_adv fields in their pixchar structs. pf_textwidth returns a pr_size which contains the sum of the len characters in the text of the pc_adv in their pixchar structs. The following routine may be used to find the bounding box for a string of characters in a given font. pf_textbound (bound, len, font, text) struct pr_subregion ‘bound; int len; struct pixfont ‘font; char ‘text; bound- >pos is the top-left corner of the bounding box, bound- >size . x is the width, and bound->size .y is the height. bound->pr is not modified. bound->pos is computed rela- tive to the location of the character origin (base point) of the first character in the text. Revision G of 15 April 1985 2-23 Pixel Data and Operations SunWindows Reference Manual 2«,4, Memory Pixrects Pixrects which store their pixels in memory, rather than displaying them on some display, are similar to other pixrects but have several special properties. Like all other pixrects, their dimen- sions are visible in the pr_size and pr_depth elements of their pixrect struct, and the device-dependent operations appropriate to manipulating them are available through their pr_ops. Beyond this, however, the format of the data which describes the particular pixrect is also public: pr_data will hold the address of an mpr_data struct, described below. Thus, a client may construct and manipulate memory pixrects using non-pixrect operations. There is also a public procedure, mem_create, which dynamically allocates a new memory pixrect, and a macro, mpr_static, which can be used to generate an initialized memory pixrect in the code of a client program. 2.4-1- The Mpr_data Struct The pr_data element of a memory pixrect points to an mpr_data struct, which contains the information needed to deal with a memory pixrect: struct mpr_data { int md_l inebytes ; short *md_lmage; struct pr_pos md_offset; short md_primary; short md_ flags ; }; #def ine MP_DI SPLAY #def ine MP_REVERSEVIDEO 1 inebytes is the number of bytes stored in a row of the primary pixrect. This is the difference in the addresses between two pixels at the same x-coordinate, one row apart. Because a secon- dary pixrect may not include the full width of its primary pixrect, this quantity cannot be com- puted from the width of the pixrect — see Region. The actual pixels of a memory pixrect are stored someplace else in memory, usually an array, which md_image points to; the format of that area is described in the next section. The creator of the memory pixrect must ensure that md_image contains an even address. md_offset is the x,y position of the first pixel of this pixrect in the array of pixels addressed by md_image. md_primary is 1 if the pixrect is pri- mary and had its image allocated dynamically (e.g. by mem.create). In this case, md_image will point to an area not referenced by any other primary pixrect. This flag is interrogated by the destroy routine: if it is 1 when that routine is called, the pixrect’s image memory will be freed. (md_ flags & MP_DISPLAY) is non-zero if this memory pixrect is in fact a display device. Other- wise, it is 0. (md_ flags & MP_REVERSEVIDEO) is 1 if reversevideo is currently in effect for the display device. md_flags is present to support memory-mapped display devices like the Sun— 2 black-and-white video device. Several macros exist to aid in addressing memory pixrects. The following macro obtains a pointer to the mpr_data of a memory pixrect. #define mpr_d(pr) ((struct mpr_data *) (pr) ->pr_data) 2-24 Revision G of 15 April 1985 SunWindows Reference Manual Pixel Data and Operations The following macro computes the bytes per line of a primary memory pixrect given its width in pixels and the bits per pixel. This includes the padding to word bounds. It is useful for incre- menting pixel addresses in the y direction. #define mpr_linebytes (width, depth) ( ( (pr_product (width, depth) +15) >>3) &~1) 2. 4-2. Pixel Layout in Memory Pixrects In memory, the upper-left corner pixel is stored at the lowest address. This address must be even. That first pixel is followed by the remaining pixels in the top row, left-to-right. Pixels are stored in successive bits without padding or alignment. For pixels more than 1 bit deep, it is pos- sible for a pixel to cross a byte boundary. However, rows are rounded up to 16-bit boundaries. After any padding for the top row, pixels for the row below are stored, and so on through the whole rectangle. Currently, memory pixrects are only supported for pixels of 1, 8, 16, or 24 bits. If source and destination are both memory pixrects they must have an equal number of bits per pixel. 2-4-3. Creating Memory Pixrects 2. 4-3.1. Mem_create A new primary pixrect is created by a call to the procedure mem_create: struct pixrect *mem_create (w, h, depth) int w, h, depth; w, h, and depth specify the width and height in pixels, and depth in bits per pixel, of the new pixrect. Sufficient memory to hold those pixels is allocated and cleared to 0, new mpr_data and pixrect structs are allocated and initialized, and a pointer to the pixrect is returned. If this can not be done, the return value is NULL. 2. 4-3. 2. mem_point The mem_point routine builds a pixrect structure that points to a dynamically created image in memory. Client programs may use this routine as an alternative to mem_create if the image data is already in memory. struct pixrect 4 mem_point (width, height, depth, data) int width, height, depth; short 4 data; width and height are the width and height of the new pixrect, in pixels. depth is the depth of the new pixrect, in number of bits per pixel, data points to the image to be associ- ated with the pixrect. Revision G of 15 April 1985 2-25 Pixel Data and Operations SunWindows Reference Manual 2. 4-3.3. Static Memory Pixrects A memory pixrect may be created at compile time by using the mpr_static macro: #define mpr_static (name, w, h, depth, image) int w, h, depth; short * image; where name is a token to identify the generated data objects; w, h, and depth are the width and height in pixels, and depth in bits of the pixrect; and image is the address of an even-byte aligned data object that contains the pixel values in the format described above. The macro generates two structs: struct mpr_data name_data; struct pixrect name; The mpr_data is initialized to point to all of the image data passed in; the pixrect then refers to mem_ops and to name_data. Note: Contrary to its name, this macro generates structs of storage class extern. 2-26 Revision G of 15 April 1985 SunWindows Reference Manual Pixel Data and Operations 2.5. File I/O Facilities for Pixrects Sun has specified a file format for files containing raster images. This format is defined by the header file . The pixrect library contains routines to perform I/O operations between pixrects and files in the raster file format. This I/O is done using the routines of the C Library Standard I/O package, requiring the caller to include the header file . The raster file format allows for multiple types of raster images. This means that both unen- coded and encoded images are supported. In addition, the pixrect library routines that read and write raster files support the notion of customer defined formats. This support is implemented by passing raster files with non-standard types through filters found in the directory /usr/lib/rasfilters. This directory also includes sample source code for a filter that corresponds to one of the standard raster file types. 2.5.1. Writing of Complete Raster Files The following procedure stores the image described by a pixrect onto a file. It normally returns 0, but if any error occurs it returns PDCERR. int pr_dump (input_pr , output, colormap, type, copy_flag) struct pixrect *input_pr; FILE ‘output; colormap_t ‘colormap; int type, copy_flag; The input_pr pixrect can be a secondary pixrect. This allows the caller to write a rectangular sub-region of a pixrect by first creating an appropriate input_pr via a call to pr_region. The output file is specified via output. The desired output type should either be one of the fol- lowing standard types or correspond to a customer provided filter. #def ine RT_OLD O #def ine RT_STANDARD 1 #def ine RT_BYTE_ENCODED 2 The RT_STANDARD type is the common raster file format in the same sense that memory pixrects are the common pixrect format: every raster file filter is required to read and write this format. The RT_OLD type is very close to the RT_STANDARD type; it was the former standard generated by old versions of Sun software. The RT_BYTE_ENCODED type implements a run-length encoding of bytes of the pixrect image; usually this results in shorter files. Specifying any other output type causes pr_dump to pipe a raster file of RTJSTANDARD type to the filter named /usr/1 ib/r as f i lters/convert . type, where type is the ASCII corresponding to the specified type in decimal. The output of the filter is then copied to output. It is strongly recommended that customer-defined formats use a type of 100 or more, to avoid conflicts with additions to the set of standard types. To aid in development of filters for customer-defined formats, pr_dump recognizes the RT_EXPEREMENTAL type as special, and uses the filter named #def ine RT_EXPERIMENTAL 65535 For pixrects displayed on devices with colormaps, the values of the pixels are not sufficient to recreate the displayed image. Thus, the image’s colormap can also be specified in the call to Revision G of 15 April 1985 2-27 Pixel Data and Operations SunWindows Reference Manual pr_dump. If the colormap is specified as NULL but input_pr is not of depth=l, pr_dump will attempt to write the colormap obtained from input_pr (via pr_getcolormap assuming a 256 element RGB colormap). The following struct is used to specify the colormap associated with input_pr: typedef struct { int int unsigned char } co lormap t ; The colormap type should be one of the Sun supported types: #def ine RMT_NONE 0 #def ine RMT_EQUAL_RGB 1 If the colormap type is RMT_NONE, then the colormap length must be 0. This case usually arises when dealing with monochrome displays and depth=l pixrects. If the colormap type is RMT _EQUAL_RGB , then the map array should specify the red (map [O] ), green (map [1] ) and blue (map [2] ) colormap values, with each vector in the map array being of the same specified color- map length. For developers of customer-defined formats, the following colormap type is provided but not interpreted by the pixrect software: #def ine RMTJRAW 2 Finally copy_flag specifies whether or not input_pr should be copied to a temporary pix- rect before the image is output. There are two situations in which the copy_flag value should be non-zero: • if the output type is RT_BYTE_ENCODED — This is because the encoding algorithm does the encoding in place and will destroy the image data of input_pr if it fails while working on input:_pr directly. • if input_pr is a pixrect in a framebuffer that is likely to be asynchronously modified — Note that use of copy_flag will still not guarantee that the correct image will be output unless the pr_rop to copy from the framebuffer is atomic or otherwise made uninterrupt- able. type; length; ‘map [3] ; 2.5.2. Reading of Complete Raster Files The following procedure can be used to retrieve the image described by a file into a pixrect. struct pixrect * pr_load (input, colormap) FILE ‘input; colormap_t ‘colormap; The raster file’s header is read from input, a pixrect of the appropriate size is dynamically allocated, the colormap is read and placed in the location addressed by ‘colormap, and finally the image is read into the pixrect and the pixrect returned. If any problems occurs, pr_load returns NULL instead. As with pr_dump, if the specified raster file is not of standard type, pr_load first runs the file through the appropriate filter to convert it to RTJSTANDARD type and then loads the output of the filter. 2-28 Revision G of 15 April 1985 SunWindows Reference Manual Pixel Data and Operations Additionally, if colormap is NULL, pr_load will simply discard any and all colormap informa- tion contained in the specified input raster file. 2.5.3. Details of the Raster File Format A handful of additional routines are available in the pixrect library for manipulating pieces of raster files. In order to understand what they do, it is necessary to understand the exact layout of the raster file format. The raster file is in three parts: first, a small header containing 8 ints; second, a (possibly empty) set of colormap values; third, the pixel image, stored a line at a time, in increasing y order. The image is essentially laid out in the file the exact way that it would appear in a memory pix- rect. In particular, each line of the image is rounded out to a multiple of 16 bits, corresponding to the rounding convention used by the memory pixrects. The header is defined by the following structure: struct rasterfile { int ras_magic; int ras_width; int ras_height; int ras_depth; int ras_length; int ras_type; int ras_maptype; int ras_maplength; }; The ras_magic field always contains the following constant: #def ine RAS_MAGIC 0x59a66a95 The ras_width, ras_height, and ras_depth fields contain the image’s width and height in pixels, and its depth in bits per pixel, respectively. The depth is usually either 1 or 8, corresponding to the standard frame buffer depths. The ras_length field contains the length in bytes of the image data. For an unencoded image, this number is computable from the ras_width, ras_height, and ras_depth fields, but for an encoded image it must be explicitly stored in order to be available without decoding the image itself. Note that the length of the header and of the possibly empty colormap values are not included in the value in the ras_length field; it is only the image data length. For histori- cal reasons, files of type RT_OLD will usually have a 0 in the ras_length field, and software expecting to encounter such files should be prepared to compute the actual image data length if it is needed. The ras_maptype and r a s_map length fields contain the type and length in bytes of the colormap values, respectively. If the ras_maptype is not RMT_NONE and the ras_maplength is not 0, then the colormap values are the ras_map length bytes immediately after the header. These values are either uninterpreted bytes (usually with the ras_maptype set to RMT_RAW) or the equal length red, green and blue vectors, in that order (when the ras_maptype is RMT_EQUAL_RGB). In the latter case, the ras_map length must be three times the size in bytes of any one of the vec- tors. Revision G of 15 April 1985 2-29 Pixel Data and Operations SunWindows Reference Manual 2.5.4- Writing Parts of a Raster File The following routines are available for writing the various parts of a raster file. Many of these routines are used to implement pr_dump. First, the raster file header and the colormap can be written by calling: int pr_dump_header (output, rh, colormap) FILE ‘output; struct raster file *rh; colormap_t ‘colormap; This routine returns PDCJCRR if there is a problem writing the header or the colormap, otherwise it returns 0. If the colormap is NULL, no colormap values are written. For clients that do not want to explicitly initialize the rasterfile struct the following routine can be used to set up the arguments for pr_dump_header: struct pixrect * pr_dump_init (input_pr , rh, colormap, type, copy_f lag) struct pixrect *input_pr; struct rasterfile *rh; colormap_t ‘colormap; int type, copy_flag; The arguments to pr_dump_init correspond to the arguments to pr_dump. However, pr_dump_init returns the pixrect to write, rather than actually writing it, and initializes the struct pointed to by rh rather than writing it. If colormap is NULL, the ras_maptype and r a s_map length fields of rh will be set to RMT_NONE and 0, respectively. If any error is detected by pr_dump_init, the returned pixrect is NULL. If there is no error and the copy_flag is zero, the returned pixrect is simply input_pr. However, if copy_flag is non-zero, the returned pixrect is dynamically allocated and the caller is responsi- ble for deallocating the returned pixrect after it is no longer needed. The actual image data can be output via a call to: int pr_dump_image (pr , output , rh) struct pixrect *pr; FILE ‘output; struct rasterfile *rh; This routine returns 0 unless there is an error, in which case it returns PDCERR. Since these routines sequentially advance the output file’s write pointer, pr_dump_image must be called after pr_dump_header. 2-30 Revision G of 15 April 1985 Sun Windows Reference Manual Pixel Data and Operations 2.5.5. Reading Parts of a Raster File The following routines are available for reading the various parts of a raster file. Many of these routines are used to implement pr_load. Since these routines sequentially advance the input file’s read pointer, rather than doing random seeks in the input file, they should be called in the order presented below. First, the raster file header can be read by calling: int pr_load_header (input, rh) FILE * input; struct raster file *rh; This routine reads the header from the specified input, checks it for validity and initializes the specified rasterfile struct from the header. The return value is 0 unless there is an error, in which case it returns PDCERR. If the header indicates that there is a non-empty set of colormap values, they can be read by cal- ling: int pr_load_colormap (input, rh, colormap) FILE ‘input; struct rasterfile *rh; colormap_t ‘colormap; If the specified colormap is NULL, this routine will skip over the colormap values by reading and discarding them. Note that the caller is responsible for looking at the raster file header and set- ting up an appropriate colormap struct before calling this routine. The return value is 0 unless there is an error, in which case it returns PDCJDRR. Finally, the image can be read by calling: struct pixrect * pr_load_ image (input, rh, colormap) FILE ‘input; struct rasterfile *rh; colormap_t ‘colormap; If the input is a standard raster file type, this routine reads in the image directly. Otherwise, it writes the header, colormap, and image into the appropriate filter and then reads the output of the filter. In this case, both the rasterfile and the colormap structs will be modified as a side- effect of calling this routine. In either case, a pixrect is dynamically allocated to contain the image, the image is read into the pixrect, and the pixrect is returned as the result of calling the routine. If there is an error, the return value is NULL instead of a pixrect containing the image. If it is known that the image is from a standard raster file type, then it can be read in by calling: struct pixrect * pr_load_std_image (input, rh, colormap) FILE ‘input; struct rasterfile *rh; This routine is identical to pr_load_image, except that it will not invoke a filter on non- standard raster file types. Revision G of 15 April 1985 2-31 Chapter 3 Overlapped Windows: Imaging Facilities This chapter and the following two deal with the sunwindow layer of the window system, which provides facilities for managing windows with overlap and concurrency. This chapter is specifically concerned with generating images in such an environment. Chapter 4 deals with con- trol of the windows, manipulating their size, location, and other structural characteristics. Chapter 5 describes the facilities for serializing multiple input streams and distributing them appropriately to multiple windows. The term “sunwindow layer” comes from the name of the library that contains its implementation. At this level of the system, a window is treated as a device: it is named by an entry in the /dev directory; it is accessed by the open (2) system call; and the usual handle on the window is the file descriptor (or fd) returned from that call. For this chapter, however, a window may be considered as simply a rectangular area with con- tents maintained by some process. Multiple windows, maintained by independent processes, may coexist on the same screen; SunWindows allows them to overlap, sharing the same (x, y) coordi- nates, and proceeding concurrently, while maintaining their separate identities. Window system facilities may also be used to construct a non-overlapped environment; the win- dow system facilities required are much the same as for constructing an overlapping environ- ment. 3.1. Window Issues: Controlled Display Generation Multiple windows on a display introduce two new issues, which may be broadly characterized as: 1) preventing the window from painting where or when it shouldn’t, and 2) ensuring that it does paint whenever and wherever it should. The first includes clipping and locking-, the latter covers damage repair and fixups. 3.1.1. Clipping and Locking Clipping constrains a window to draw only within the boundaries of its portion of the screen. Even this area is subject to changes beyond the control of a window’s process — another window may be opened on top of the first, covering part of its contents, or a window may be shrunk to make room for another alongside it. Thus, it is convenient for the window system to maintain up-to-date information on which portions of the screen belong to which windows, and for the windows to consult that information whenever they are about to draw on the screen. Locking prevents window processes from interfering with each other in several ways: © Raster hardware may require several operations to complete a change to the display; one process’ use of the hardware should be protected from interference by others during this critical interval. Revision G of 15 April 1985 3-1 Overlapped Windows: Imaging Facilities SunWindows Reference Manual • Changes to the arrangement of windows must be prevented while a process is painting, lest an area be removed from a window as it is being painted. • A software cursor that the window process does not control (the kernel is usually responsible for the cursor) may have to be removed so that it does not interfere with the window’s image. Use of explicit locking calls is extremely important for achieving maximum display performance. Clipping and locking are described in more detail in Locking and Clipping. 8.1.2. Damage Repair and Fixups A window whose image does not appear entirely as it should on the screen is said to be damaged. A common cause of damage is being first overlaid, and then uncovered, by another window. When a window is damaged, a portion of the window’s image must be repaired. Note that the requirement for repairing damage may arise at any time; it is completely outside the window’s control. When a process performs some operation which includes reading a portion of its window, for instance copying a part of the image from one region to another to implement scrolling, it may find the source pixels obscured. This necessitates a fixup, in which that portion of the image is regenerated, similar to repairing damage. Unlike damage generation, the need to do some fixup is provoked only in response to an action of the window’s process, e.g., scrolling. 8.1.3. Retained Windows Either form of regeneration may be done by recomputing the image; this approach is reasonable for applications like text where there is some underlying representation from which the display can be recomputed easily. For images which require considerable computation, SunWindows provides a retained window, whose image is maintained in memory as well as on the display. Such a window may have its image recopied to the display as needed to repair damage. The mechanism for making a window retained is described in the section entitled Pixwtns. 3.1. 4- Colormap Sharing On color displays, colormap entries are a limited resource. When shared among multiple appli- cations, colormap usage requires arbitration. For example, consider the following applications running on the same display at the same time in different windows: • Application program X needs 64 colors for rendering VLSI images. ® Application program Y needs 32 shades of gray for rendering black and white photographs. ® Application program Z needs 256 colors (assume this is the entire colormap) for rendering full color photographs. Colormap usage control is handled as follows: 9 To determine how X and Y figure out what portion of the colormap they should use so they don’t access each others’ entries, SunWindows provides a resource manager that allocates a colormap segment to each window from the shared colormap. To reduce duplicate colormap segments, they are named and can be shared among cooperating processes. 3-2 Revision G of 15 April 1985 SunWindows Reference Manual Overlapped Windows: Imaging Facilities 0 To hide concerns about knowing the correct offset to the start of a colormap segment from routines that access the image, SunWindow initializes the image of a window with the color- map segment offset. This effectively hides the offset from the application. ® To accommodate Z if its large colormap segment request cannot be granted, Z’s colormap is loaded into the hardware, replacing the shared colormap, whenever input is directed towards Z’s window. Z’s request is not denied even though it is not allocated its own segment in the shared colormap. 3.1.5. Process Structure In SunWindows, access to the screen is performed in each user process, instead of in a single, central, fully debugged screen management process. This increases the possibility of an incorrect user process damaging the display area of other application processes. Several compensating fac- tors justify this approach: e Clients may access this open system at whichever level is most convenient. Clients who require the ultimate efficiency of direct screen access need not sacrifice the window manage- ment functions of the window system. • Leaving processing in user processes promotes efficiency in both implementation and execu- tion: making and testing extensions and modifications is much easier in user code than in the kernel. 3.1.6. Imaging with Windows A detailed discussion of imaging with windows follows. We begin with a description of the basic data structures that are used in this level of Sunwindows. These are a primitive geometric facil- ity, the reef, for describing rectangles, and the basic structure, the pixwin, that describes a win- dow on the screen with its associated state and operation vectors. Following is a brief discussion of the simple process of creating and destroying pixwins. This is followed by a detailed description of the approach to locking and clipping, which leads naturally into a discussion of library routines that access a pixwin’s pixels. Detecting and repairing dam- age is treated next. 3.1.7. Libraries and Header Files The procedures described in this chapter are provided in the tunvuindotv library (/usr/lib/libsunwindow . a). The header file contains the declarations that must be #include’ed in a program that uses the facilities described in this chapter. 3.2. Data Structures Here are some data structures used in the implementation of pixwins. Be sure you understand reefs before proceeding. Descriptions of the data structure internals are also provided for addi- tional information. Revision G of 15 April 1985 3-3 Overlapped Windows: Imaging Facilities SunWindows Reference Manual 8.2.1. Reds Throughout Sunwindows, images are dealt with in rectangular chunks; where complex shapes are required, they are built up out of groups of rectangles. The basic description of a rectangle is the rect struct, defined in the header file . The same file contains definitions of several useful macros and procedures for dealing with recta. Where a window is partially obscured, its visible portion generally cannot be described by a sim- ple rectangle; instead a list of non-overlapping rectangular fragments which together cover the visible area is used. This rect list is declared, along with its associated macros and pro- cedures in the file . At this point we only discuss the rect struct and its most useful macros; a full description of both recta and rectlista is in Appendix A. #define coord short struct rect { coord coord short short }; r_left ; r_top; r_width, r_height ; In the context of a window, the rectangle lies in a coordinate system whose origin is in the upper left-hand corner, and whose dimensions are given in pixels. Two macros determine an edge not given explicitly in the rect. These macros are: #define rect_right (rp) #define rect_bottom (rp) struct rect *rp; These macros return the coordinate of the last pixel within the rectangle on the right or bottom, respectively. 8.2.2. Pixwins Pixwina are the basic imaging elements of the overlapped window system. The window layer of the system uses pixwins to represent pixrects on a window surface. The pixwin thus describes the window image and a set of routines to operate on the window. A client of the window system has a rectangular window in which it displays information for the user. Because of overlapping, however, it is not always possible to display information in all parts of a client’s window. Parts of an image may have to be displayed at some point long after they were generated, as a portion of the window is uncovered. The clipping and repainting necessary to preserve the identity of the rectangular image across interference with other objects on the screen is handled by manipulations on pixwins. The pixwin struct is defined in : 3-4 Revision G of 15 April 1985 SunWindows Reference Manual Overlapped Windows: Imaging Facilities struct pixwin { struct pixrect ops *pw_ops; caddr_t pw_opshandle; int pw_opsx; int pw_opsy; struct rectlist pw_ fixup; struct pixrect *pw_pixrect; struct pixrect *pw_prretained; struct pixwin_clipops *pw_clipops; struct pixwin_clipdata *pw_clipdata char pw_cmsname [20] ; }-• The pixwin refers to a portion of some device, typically a display; the device is identified by pw_pixrect. If the image displayed in the pixwin required a large effort to compute, it will be worth saving a backup copy of the whole image, making the window a retained window. This is done by creat- ing an appropriate memory pixrect as described in Memory Pixrects, and storing a pointer to it in pw_prretained. Portions of the image which could not be accessed by an operation which attempted to read pix- els from the pixwin are indicated by pw_fixup. pv_ops is a pointer to a vector of operations used in screen access macros to call the pixwin software level or, as an optimization, to call the pixrect software directly. The structure pix- rectops was discussed in Pixrectopt. The pw_opshandle is the data handle passed to the operations of pw_ops. pw_opsx and pw_opsy are additional offset information that screen access macros use. These three fields are dynamically altered based on locking and clipping status. pw_clipdata is a collection of information of special interest for locking and clipping. pw_clipops points to a vector of operations which are used in locking and clipping. The declarations of these last two structs are discussed more fully in pixwin_clipdata Struct, pixwin_clipops Struct, and subsequent sections. pw_cmsname is the identifier of the colormap segment that this pixwin is currently using. This value should only be accessed via pw_setcmsname and pw_getcmsname described below. Revision G of 15 April 1985 3-5 Overlapped Windows: Imaging Facilities SunWindows Reference Manual Pixwin_clipdata Struct struct pixwin. .clipdata { int pwcd_windowf d ; short pwcd_state; struct rectlist pwcd_clipping; int pwcd_clipid; int pwcd_damagedid; int pwcd_lockcount ; struct pixrect *pwcd_prmulti; struct pixrect *pwcd_prsingle; struct pixwin_prlist *pwcd_prl; struct rectlist pwcd_clippingsorted [RECTS_SORTS] struct rect *pwcd_regionrect ; }; #def ine PWCD_NULL O #def ine PWCD_MULTIRECTS 1 #def ine PWCD_SINGLERECT 2 #define PWCD_USERDEFINE 3 struct pixwin_prlist ■( struct p ixwin_pr list *prl_next; struct pixrect *prl_pixrect; int prl_x, prl_y; >; pwcd_windowfd is a file descriptor for the window being accessed. Within the owning process, it is the standard handle on a window. A description of the interplay between windows and pixwins continues in Pixwin Creation and Destruction. The portions of the window’s area acces- sible through the pixwin are described by the rectlist pwcd_c lipping pwcd_regionrect, if not NULL, points to a rect that is intersected with pwcd_clipping to further restrict the portions of the window’s area accessible through the pixwin. pwcd_clipid and pvcd_damagedid identify the most recent rectlists retrieved for a win- dow. pwcd_lockcount is a reference count used for nested locking, as described in Locking below. Copies of pwcd_c lipping, sorted in directions convenient for copy operations, are stored in pwcd_clippingsorted. 3-6 Revision G of 15 April 1985 SunWindows Reference Manual Overlapped Windows: Imaging Facilities pwcd_st ate can be one of the following: Table 3-1: Clipping State State Meaning PWCD_NULL no part of window visible PWCD_MULTIRECTS must clip to multiple rectangles PWCD_SINGLERECT need clip to only one rectangle PWCD_USERDEFINE the client program will be responsible for setting up the clipping pwcd_prmulti is the pixrect for clipping during drawing when there are multiple rectangles involved in the clipping. pwcd_prsingle is the pixrect for clipping during drawing when there is only one rectangle visible. pwcd_prl is a list of pixrects that may be used for clipping when there are multiple rectangles involved. For vector drawing, these clippers must be used to maintain stepping integrity across abutting rectangle boundaries. The prl_x and prl_y fields in the pixwin_pr list struc- ture are offsets from the window origin for the associated prl_pixrect. Pixwin_ clip ops Struct struct pixwin_clipops { int (*pwco_lock) () , int (*pwco_unlock) () , int (*pwco_reset) () , int (*pwco_getc lipping) () }; The pw_clipops struct is a vector of pointers to system-provided procedures that implement correct screen access. These are accessed through macros described in Locking and Clipping. 3.3. Pixwin Creation and Destruction To create a pixwin, the window to which it will refer must already exist. This task is accom- plished with procedures like win_getnewvindov and vin_setrect, described in Window Manipulation, or, at a higher level, tool_create and tool_createsubwindow, described in Suntool: Tools and Subwindows. The pixwin is then created for that window by a call to pw_open: struct pixwin *pw_open(fd) int fd; pw_open takes a file descriptor for the window on which the pixwin is to write. A pointer to a pixwin struct is returned. At this point the pixwin describes the exposed area of the window. If the client wants a retained pixwin, pw_prretained should be set to point to an Revision G of 15 April 1985 3-7 Overlapped Windows: Imaging Facilities SunWindows Reference Manual appropriately-sized memory pixrect after pw_open returns. When a client is finished with a window, it should be released by a call to: pw_close (pw) struct pixwin *pw; pw_close frees any dynamic storage associated with the pixwin, including its pw_pr retained pixrect if any. If the pixwin has a lock on the screen, it is released. 3.3.1. Region Creation One can use pixwins to clip rectangular regions within a window’s own rectangular area. The region operation creates a new pixwin that refers to an area within an existing pixwin: struct pixwin *pw_region (pw, x, y, w, h) struct pixwin *pw; int x, y, w, h; The pixwin which is to serve as the source is addressed by pw; x, y, w and h describe the rectangle to be included in the new pixwin. The upper left pixel in the returned pixwin is at coordinates (0,0); this pixel has coordinates (x, y) in the source pixwin. 3.4. Locking and Clipping Before a window process reads from or writes to the screen, it must satisfy several conditions: © It should obtain exclusive use of the display hardware, © The position of windows on the screen should be frozen, ® The window’s description of what portions of its window are visible should be up-to-date, and ® The window should confine its activities to those visible areas. The first three of these requirements is met by locking-, the last amounts to clipping the image the window will write to the bounds of its exposed area. All are handled implicitly by the access routines described in Accessing a Pixwin’s Pixels. 3.4-1. Locking Locking allows a client program to obtain exclusive use of the display. Making correct and judicious use of explicit display locking is EXTREMELY impor- tant for getting the best display speed possible. Note that if the client program does not obtain an explicit lock, the window system will. For example, if an application program is to draw one hundred lines, it can either explicitly lock the display once, draw the lines, and unlock explicitly, or it can ignore locking and simply draw the lines. In the latter case, the window system will perform locking and unlocking around each drawing operation, in effect acquiring and releasing the lock one hundred times instead of once. 3-8 Revision G of 15 April 1985 SunWindows Reference Manual Overlapped Windows; Imaging Facilities For efficiency’s sake, application programs should lock explicitly around a body of screen access operations. The pw_lock macro: pw_lock(pw, r) struct pixwin *pw; struct rect *r; uses the lock routine pointed to by the window’s pw_clipops to acquire a lock for the user process that made this call, pw addresses the pixwin to be used for the ouput; r is the rectan- gle in the window’s coordinate system that bounds the area to be affected. pw_lock blocks if the lock is unavailable, for example, if another process currently has the display locked. Lock operations for a single pixwin may be nested; inner lock operations merely increment a count of locks outstanding, pwcd_lockcount in the window’s pw_clipdata struct. Their affected rectangles must lie within the original lock’s. A similar macro is; pw_unlock (pw) struct pixwin *pw; which decrements the lock count. If this brings it to 0, the lock is actually released. Since locks may be nested, it is possible for a client procedure to find itself, especially in error handling, with a lock which may require an indefinite number of unlocks. To handle this situation cleanly, another routine is provided. The following macro sets pw’s lock count to 0 and releases its lock: pw_reset (pw) struct pixwin *pw; Like pw_lock and pw_unlock, pw_reset calls a routine addressed in the pixwin’s pixwin_clipops struct, in this case the one addressed by pwco_reset. Acquisition of a lock has the following effects: ® If the cursor is in conflict with the affected rectangle, it is removed from the screen. While the screen is locked, the cursor will not be moved in such a way as to disrupt any screen accessing. « Access to the display is restricted to the process acquiring the lock. • Modification of the database that describes the positions of all the windows on the screen is prevented. » The id of the most recent clipping information for the window is retrieved, and compared with that stored in pwcd_c lipid in the pixwin’s pw_clipdata. If they differ, the routine addressed by pwco_getc lipping is invoked, to make all the fields in pw_clipdata accurately describe the area which may be written into. e Once the correct clipping is in hand, the pwcd_state variable’s value determines how to set pw_ops, pw_opshandle, pw_opsx and pw_opsy. This setting is done in anticipa- tion of further screen access operations being done before a subsequent unlock. These values can often be set to bypass the pixwin software by going directly to the pixrect level. Revision G of 15 April 1985 3-9 Overlapped Windows: Imaging Facilities Sun Windows Reference Manual Nested locking is cheap, but initial locking is moderately expensive as it involves two system calls. Clients with a group of screen updates to do can gain noticeably by surrounding the group with lock-unlock brackets; then the locking overhead will only be incurred once. An example of such a group is displaying a line of text, or a series of vectors with pre-computed endpoints. While it has the screen locked, a process should not: ® do any significant computation unrelated to displaying its image; o invoke any system calls, including other I/O, which might cause it to block; or * invoke any pixwin calls except pw_unlock and those described in Accessing a Pixwin’s Pix- els. In any case, the lock should not be held longer than about a quarter of a second, even following all these guidelines. As a deadlock resolution approach, when a display lock is held for more than 10 seconds, the lock is broken. However, the offending process is not notified by signal; the idea is that a process shouldn’t be aborted for this infraction. A message is displayed on the console. 3.4.2. Clipping Output to a window is clipped to the window’s pwcd_clipping rectlist; this is a series of rec- tangles which, taken together, cover the valid area that this window may write to. There are two routines which set the pixwin’s clipping: pw_exposed (pw) struct pixwin *pw; pw_damaged (pw) struct pixwin *pw; pw_damaged is discussed in Damage. pw_exposed is the normal routine for discovering what portion of a window is visible. It retrieves the rectlist describing that area into the pixwin’s pwcd_c lipping, and stores the id identifying it in pwcd_clipid. It also stores its own address in the pixwin’s pwco_getc lipping, so that subsequent lock operations will get the correct area description. Clipping, even more than locking, should normally be left to the library output routines. For the intrepid, the strategy these routines follow is briefly sketched here; the rectlist data structures and procedures in Appendix A are required reading. Some procedure will set the pixwin’s pwcd_c lipping so that it contains a rectlist describing the region which may be painted. This is done by a lock operation which makes a call through *pwco_getc lipping, or an explicit call to one of pw_open, pw_donedamaged, pw_exposed or pw_damaged. This rectlist is essentially a list of rectangular fragments which together cover the area of interest. As an image is generated, portions of it which lie outside the rectangle list must be masked off, and the remainder written to the window through a pixrect. The clipping aid pwcd_prmulti is set up to be a pixrect which clips for the entire rectangular area of the window. Any clipping using this pixrect must utilize the information in pwcd_c lipping to do the actual clipping to multiple rectangles. pwcd_prl is set up to parallel each of the rectangles in pwcd_c lipping. Thus, if one draws to each of the pixrects in this data structure, the image will be correctly clipped. pwcd_state is set by examining the makeup of the pwcd_c lipping. If pwcd_state is 3-10 Revision G of 15 April 1985 SunWindows Reference Manual Overlapped Windows: Imaging Facilities PWCDJ3INGLERECT, a pixrect is set up in pvcd_prsingle also. When this case exists, after pw_lock and before pw_unlock, most screen accesses will directly access the pixrect level of software. Thus, in this common case, screen access is as fast in the window system as it is on the raw pixrect software outside of the window system. Also, pwcd_prsingle is set up with a zero height and width pixrect when pwcd_state is PWCD_NULL. As an escape, none of the pixrect setup described above takes place when pwcd_state is PWCD_USERDEFINE. This means that clipping is the responsibility of higher level software. A client may write to the display with an operation which specifies no clipping: (op | PIX_DONTCLIP) This means that it is doing the clipping at a higher level. Note that clipping data is only valid during the time the client may write to the screen, that is when the window’s owner process holds a lock on the screen. If the clipping is done wrong, it is possible to damage another window’s image. In particular, the client must clip to all of the rectangles in the rectlist, not just the bounding rectangle for the rectlist. 3.5. Accessing a Pixwin’s Pixels Procedures described in this section provide all the normal facilities for output to a window and should be used unless there are special circumstances. Each contains a call to the standard lock procedure, described in Locking. Each takes care of clipping to the rectlist in pw_c lipping. Since the routines are used both for painting new material in a window and for repairing dam- age, they make no assumption about what clipping information should be gotten. Thus, there should be some previous call to either pw_open, pw_donedamaged, pw_exposed or pw_damaged, to initialize pvo_getclipping correctly. The procedures described in this section will maintain the memory pixrect for a retained pixwin. That is, they check the window’s pw_prretained, and if it is not NULL, perform their opera- tion on that data in memory, as well as on the screen. 3.5.1. Write Routines pw_write (pw, struct int struct xd, yd, width, height, op, pr, xs, ys) pixwin *pw; op, xd, yd, width, height, xs, ys; pixrect *pr; pw_writebackground (pw, xd, yd, width, height, op) Pixels are written to the pixwin pw in the rectangle defined by xd, yd, width, and height, using rasterop function op (as defined in Constructing an Op Argument). They are taken from the rectangle with its origin at xs, ys in the source pixrect pointed to by pr. pw_writebackground simply supplies a null pr which indicates that an infinite source of pix- els, all of which are set to zero, is used. The following draws a pixel of value at (x, y) in the addressed pixwin: Revision G of 15 April 1985 3-11 Overlapped Windows: Imaging Facilities Sun Windows Reference Manual pw_put(pw, x, y, value) struct pixwin *pw; int x, y, value; The next draws a vector of pixel value from (xO, yO) to (xl, yl) in the addressed pixwin using rasterop op: pw_vector (pw, xO ( yO, xl, yl, op, value) struct pixwin *pw; int op, xO, yO, xl, yl, value; pw_rop performs the indicated rasterop from source to destination: pw_rop(dpw, dx, dy, w, h, op, sp, sx, sy) struct pixwin *dpw; struct pixrect ‘sp; int dx, dy, w, h, op, sx, sy; For further information, please see Rop: RaaterOp Source to Destination. pw_replrop (pw, xd, yd, width, height, op, pr, xs, ys) struct pixwin *pw; int op, xd, yd, width, height; struct pixrect *pr; int xs , ys ; This procedure uses the indicated raster op function to replicate a pattern (found in the source pixrect) into a destination in a pixwin. For a full discussion of the semantics of this procedure, refer to the description of the equivalent procedure pr_replrop in Pixel Data and Operations. The following two routines: pw_text(pw, x, y, op, font, s) struct pixwin *pw; int x, y, op; struct pixfont ‘font; char * s ; pw_char (pw, x, y, op, font, c) struct pixwin *pw; int x, y, op; struct pixfont ‘font; char c ; write a string of characters and a single character respectively, to a pixwin, using rasterop op as above. pw_text and pw_char are distinguished by their own coordinate system: the desti- nation is given as the left edge and baseline of the first character. The left edge does not take into account any kerning (character position adjustment depending on its neighbors), so it is pos- sible for a character to have some pixels to the left of the x-coordinate. The baseline is the y- coordinate of the lowest pixel of characters without descenders, ‘L’ or ‘o’ for example, so pixels will frequently occur both above and below the baseline in a string. font may be NULL in which case the system font is used. 3-12 Revision G of 15 April 1985 SunWindows Reference Manual Overlapped Windows: Imaging Facilities The system font is the same as the font returned from pf_de fault. In addition, the system font is reference counted and shared between software packages. To get the system font call pw_p fsysopen: struct pixfont *pw_p fsysopen () When you are done with the system font call pw_pfsysclose: pw_pfsysclose () Note: A font to be used in pw_text is required to have the same pc_home.y and character height for all characters in the font. The following routine: pw_ttext (pw, x ( y, op, font, s) struct pixwin *pw; int x, y, op; struct pixfont ‘font; char *s; is just like pw_text except that it writes transparent text. Transparent text writes the shape of the letters without disturbing the background behind it. This is most useful with color pixwins. Monochrome pixwins can use pw_text and aPDCSRC [ PEX_DST op, which is faster. Applications such as displaying text perform the same operation on a number of pixrects in a fashion that is amenable to global optimization. The batchrop procedure is provided for these situations: pw_batchrop (pw, dx, dy, op, items, n) struct pixwin *pw; int dx, dy, op, n; struct pr_prpos items [ ] ; pw_batchrop is analogous to pr_batchrop described in Pixel Data and Operations. Please refer to that section for a detailed explanation of pw_batchrop. Stencil ops are like raster ops except that the source pixrect is written through a stencil pixrect which functions as a spatial write enable mask. The indicated raster operation is applied only to destination pixels where the stencil pixrect is non-zero. Other destination pixels remain unchanged. pw_stencil (dpw, dx, dy, dw, dh, op, stpr, stx, sty, spr, sx, sy) struct pixwin *dpw; struct pixrect ‘stpr, *spr; int dx, dy, dw, dh, op, stx, sty, sx, sy; pw_stencil is exactly analogous to pr_stencil described in Pixel Data and Operations. Refer there for a detailed explanation of pw_stencil. 8.5.2. Drawing A Polygon within a Pixwin The following macro draws a polygon within a pixwin: Revision G of 15 April 1985 3-13 Overlapped Windows: Imaging Facilities SunWindows Reference Manual pw_polygon_2 (pw, dx, dy, nbds, npts, vlist, op, spr, sx, sy) struct pixwin *pw; int dx, dy; int nbds; int npts [] ; struct pr_pos *vlist; int op ; struct pixrect *spr; int sx, sy; You can create a polygon filled with a solid or textured pattern. pv_polygon_2 is analogous to pr_po ly gon_2 described in Pixel Data and Operations. Refer to pr_polygon_2 for further details on this procedure. 3.5.3. Draw Curved Shapes pw_traprop is a pixwin operation analogous to pv_rop. The main difference is that pw_traprop operates on a trapezon rather than a rectangle. Refer to the section Draw Curved Shapes (pr^traprop) for detailed information about trapezons. The function pr_traprop (dpw, dx, struct pixwin struct pr_trap struct pixrect int dy, t, op, spr, sx, sy) * dpw ; t; *spr; dx, dy, op, sx, sy; writes the source pixrect (spr) into the destination pixwin (dpw) via the operation op. op works in the same manner as pw_rop. The function then clips the output to the trapezon t. 3.5.4 ■ Read and Copy Routines The following routines use the window as a source of pixels. They may.find themselves thwarted by trying to read from a portion of the pixwin which is hidden, and therefore has no pixels. When this happens, pw_ fixup in the pixwin structure will be filled in by the system with the description of the source areas which could not be accessed. The client must then regenerate this part of the image into the destination. Retained pixwins will always return rl_null in pw_ fixup because the image is refreshed from pw_prretained. The following returns the value of the pixel at (x, y) in the addressed pixwin: pw_get(pw, x, y) struct pixwin *pw; int x, y, ; Pixels are read from the pixwin into a pixrect by: pw_read(pr, xd, yd, width, height, op, pw, xs, ys) struct pixwin *pw; int op, xd, yd, width, height, xs, ys; struct pixrect *pr; 3-14 Revision G of 15 April 1985 SunWindows Reference Manual Overlapped Windows: Imaging Facilities Pixels are read from the rectangle defined by xs, ys, width, height, in the pixwin pointed to by pw, using rasterop function op. The pixels are stored in the rectangle with its origin at xd, yd in the pixrect pointed to by pr. Copy is used when both source and destination are pixwins: pw_copy (dpw , xd, yd, width, height, op, spw, xs, ys) struct pixwin *dpw, *spw; int op, xd, yd, width, height, xs, ys; Note: Currently dpw and spw must be the same pixwin. 8.5.5. Bitplane Control For pixwins on color display devices, one must be able to restrict access to certain bitplanes. pw_put attributes (pw, planes) struct pixwin *pw; int ‘planes; planes is a bitplane access enable mask. Only those bits of the pixel corresponding to a 1 in the same bit position of ‘planes will be affected by pixwin operations. pw_putattributes sets the access enable mask of pw. If the planes argument is NULL, that attribute value will not be written. Note: Use pw_putattributes with care; it changes the internal state of the pixwin until pw_putattributes is next called. Don’t forget to restore the internal state once through accessing in this special mode. pw_getattributes (pw, planes) struct pixwin *pw; int ‘planes; retrieves the value of the access enable mask into ‘planes. 3.6. Damage When a portion of a client’s window becomes visible after having been hidden, it is damaged. This may arise from several causes. For instance, an overlaying window may have been removed, or the client’s window may have been stretched to give it more area. The client is notified that such a region exists by the signal SIGWINCH; this simply indicates that something about the window has changed in a fashion that probably requires repainting. It is possible that the window has shrunk, and no repainting of the image is required at all, but this is a degenerate case. It is then the client’s responsibility to repair the damage by painting the appropriate pixels into that area. The following section describes how to do that. 3.6.1. Handling a SIGWINCH Signal Note: it is a common programming error to try to access the pixwin at the time a SIGWINCH is received, rather than after returning from the SIGWINCH handler. Please read this section and avoid this problem. Revision G of 15 April 1985 3-15 Overlapped Windows: Imaging Facilities SunWindows Reference Manual There are several stages to handling a SIGWINCH. First, in almost all cases, the procedure that catches the signal should not immediately try to repair the damage indicated by the signal. Since the signal is a software interrupt, it may easily arrive at an inconvenient time, halfway through a window’s repaint for some normal cause, for instance. Consequently, the appropriate action in the signal handler is usually to set a flag which will be tested elsewhere. Conveniently, a SIGWINCH is like any other signal; it will break a process out of a select system call, so it is possible to awaken a client that was blocked, and with a little investigation, discover the cause of the SIGWINCH. See the select (2) system call and refer to the tool_select mechanism in Tool Processing for an example of this approach. Once a process has discovered that a SIGWINCH has occurred and arrived at a state where it’s safe to do something about it, it must determine exactly what has changed, and respond appropriately. There are two general possibilities: the window may have changed size, and/or a portion of it may have been uncovered. win_getsize (described in Window Manipulation) can be used to inquire the current dimen- sions of a window. The previous size must have been remembered, for instance from when the window was created or last adjusted. These two sizes are compared to see if the size has changed. Upon noticing that its size has changed, a window containing other windows may wish to rearrange the enclosed windows, for example, by expanding one or more windows to fill a newly opened space. Whether a size change occurred or not, the actual images on the screen must be fixed up. It is possible to simply repaint the whole window at this point — that will certainly repair any dam- aged areas — but this is often a bad idea because it typically does much more work than neces- sary. Therefore, the window should retrieve the description of the damaged area, repair that damage, and inform the system that it has done so: The pw_damaged procedure: pw_damaged (pw) struct plxwin *pw; is a procedure much like pw_exposed. It fills in pwcd_clipping with a rectlist describ- ing the area of interest, stores the id of that rectlist in the pixwin’s pw_opshandle and in pwcd_damagedid as well. It also stores its own address in pwco_getc lipping, so that a subsequent lock will check the correct rectlist. All the clippers are set up too. Colormap segment offset, initialization is done, as described in Surface Preparation. NOTE: A call to pw_damaged should ALWAYS be made in a sigwinch handling rou- tine. Likewise, pw_donedamaged should ALWAYS be called before returning from the sigwinch handling routine. While a program that runs on monochrome displays may appear to function correctly if this advice is not followed, running such a pro- gram on a color display will produce peculiarities in color appearance. Now is the time for the client to repaint its window — or at least those portions covered by the damaged rectlist; if the regeneration is relatively expensive, that is if the window is large, or its contents complicated, it may be worth restricting the amount of repainting before the clip- ping that the rectlist will enforce. This means stepping through the rectangles of the rectlist, determining for each what data contributed to its portion of the image, and recon- structing only that portion. See Appendix A for details about rectlists. For retained pixwins, the following call can be used to copy the image from the backup pixrect to the screen: 3-16 Revision G of 15 April 1985 SunWindows Reference Manual Overlapped Windows: Imaging Facilities pw_repairretained (pw) struct pixwin *pw; When the image is repaired, the client should inform the window system with a call to: pw_donedamaged (pw) struct pixwin *pw; pw_donedamaged allows the system to discard the rectlist describing this damage. It is possible that more damage will have accumulated by this time, and even that some areas will be repainted more than once, but that will be rare. After calling pw_donedamaged, the pixwin describes the entire visible area of the window. A process which owns more than one window can receive a SIGWINCH for any of them, with no indication of which window generated it. The only solution is to fix up all windows. Fortunately, that should not be overly expensive, as only the appropriate damaged areas are returned by pw_damaged. 3.7. Colormap Manipulation Pixwins provide an interface to a basic colormap sharing mechanism. Portions of the colormap, colormap segments, are named and can be shared among cooperating processes. Use of a colormap segment, as opposed to the entire colormap, is essentially invisible to clients. Routines that access a pixwin’s pixels do not distinguish between windows which use colormap segments and those which use the entire colormap. 8.7.1. Initialization pw_open and pw_region both create and return a pixwin. If a colormap segment is already defined for the window of the pixwin, this is the colormap segment used in the new pixwin. However, if the window has no colormap segment defined for it, the default colormap segment is setup for the pixwin. The default colormap segment is usually the monochrome colormap segment defined in . However, the default colormap segment can be programmatically changed. #def ine CMS_NAMESIZE 20 struct colormapseg •{ int cms_size; int cms_addr; char cms_name [CMS_NAMESIZE] ; }; struct cms_map { unsigned char *cm_red; unsigned char * cm_ green ; unsigned char *cm_blue; }; Revision G of 15 April 1985 3-17 Overlapped Windows: Imaging Facilities Sun Windows Reference Manual pw_setdefaultcms (cms , map) struct colormapseg *cms; struct cms_map *map; pw_setdefau Items copies the data in cms and map to serve as the default colormap seg- ment. cms- >cms_name is the name of the colormap segment (more on names below) and cms->cms_size is its size (cms->cms_addr should be 0). There are cms->cms_size bytes in each of the arrays of map. A —1 is returned if cms->cms_size is greater than 256. Other- wise, 0 is returned. pw_ge t default cms ( cms , map ) struct colormapseg *cms; struct cms_map *map; pw_getdefaul terns copies the data in the default colormap segment into the data pointed to by cms and map. Before the call, the byte pointers in map should be initialized to arrays of size cms->cms_size. A —1 is returned if cms->cms_size is less than the size of the default colormap segment. Otherwise, 0 is returned. Note: the correct way to access an existing pixwin’s colormap is via pv_putcolormap and pw_getcolormap. 3.7.2. Background and Foreground Every colormap segment has two distinguished values, its background and foreground. The back- ground color is defined as the value at the first position of a colormap segment. The foreground color is defined as the value at the last position of a colormap segment (the colormap segment’s size minus 1). The foreground is important in terms of color/monochrome compatibility. Any source color, other than 0, that is written on a monochrome pixrect is translated to the foreground color. pw_open sets the background and foreground of the returned pixwin to be those of the default colormap segment if the pixwin’s window has not defined a colormap segment. pw_region inherits the background and foreground of the source pixwin. Here are handy utilities to set two specific colormap segment entries: pw_reversevideo (pw, min, max) struct pixwin *pw; int min, max; pw_blackonwhite (pw, min, max) struct pixwin *pw; int min, max; pw_whiteonblack (pw, min, max) struct pixwin *pw; int min, max; min and max should be the first and last entries, respectively, in the colormap segment. If min is the background and max is the foreground and pw is a color pixwin, these calls do nothing. 3-18 Revision G of 15 April 1985 SunWindows Reference Manual Overlapped Windows: Imaging Facilities 3.7.8. A New Colormap Segment Changing a pixwin’s colormap requires two steps. First, the colormap segment must be appropri- ately named (see pw_setcmsname, below). Second, the colormap segment is loaded with the actual colors desired (see pw_putcolormap, covered in the next section). If a colormap segment is not to be shared by another window then the name should be unique. One would certainly want a unique colormap segment if that segment was to be used for color- map animation. A common way to generate a unique name is to append your process id to a more meaningful string that describes the usage of the colormap segment. If a colormap segment’s usage is static in nature, by all means try to use a shared colormap seg- ment definition. There are three basic types of shared colormap segments: • A colormap segment used by a single program. Sharing occurs when multiple instances of the same program are running. An example of such a program might be a color terminal emulator in which the terminal has a fixed selection of colors. • A colormap segment used by a group of highly interrelated programs. Sharing occurs when- ever two or more programs of this group are running at the same time. An example of such a group might be a series of CAD/CAM programs in which it is common to have multiple programs running at the same time. • A colormap segment used by a group of unrelated programs. Sharing occurs whenever two or more programs of this group are running. An example of such a colormap segment is CMS_MONOCHROME, as defined in . This colormap segment is, by convention, the default colormap. Examples of other colormap segment definitions that could be shared with other windows are in . These are cms_rgb.h, cms_grays.h, cms_mono . h, and cms_rainbow.h. Remember that colormap entries are scarce so try to share them. pw_setcmsname (pw, cmsname) struct pixwin *pw; char cmsname [CMS_NAMESIZE] ; cmsname is the name that pw will call its window’s colormap segment. Just setting the name resets the colormap segment to a NULL entry. Usually, the very next call after pw_setcmsname should be pw_putcolormap, to set the size of the colormap (see section fol- lowing). Colormap segments are associated with windows, not pixwins. Each window can have only one colormap segment. Pixwins provide an interface for managing that one colormap segment. Since more than one pixwin may exist per window, care should be taken to avoid changing the colormap segment definition out from underneath another pixwin on the same window. pw_getcmsname (pw, cmsname) struct pixwin *pw; char cmsname [CMS_NAMESIZE] ; The colormap segment name of pw is copied into cmsname. Revision G of 15 April 1985 3-19 Overlapped Windows: Imaging Facilities SunWindows Reference Manual 3.7. 4- Colormap Access pw_putcolormap (pw, index, count, red, green, blue) struct pixwin *pw; int index, count; unsigned char red [ ], green [ ], blue[ ]; Note: Before accessing the colormap, you must call pv_setcmsname. The count elements of the pixwin’s colormap segment starting at index (zero origin) are loaded with the first count values in the three arrays. A colormap has three components each indexed by a given pixel value to produce an RGB color. Monochrome pixwins assume red equals green equals blue. Pixrects of depth 8 have colormaps with 256 (2 to the eighth) entries. Background and foreground values are forced to the values defined by the screen if they are the same. pw_getcolormap (pw, index, count, red, green, blue) struct pixwin *pw; int index, count; unsigned char red [ ], green [ ], blue[ ]; finds out the state of the colormap segment. The arguments are analogous to those of pw_putcolormap. The utility: pw_cyclecolormap (pw, cycles, index, count) struct pixwin *pw; int cycles, index, count; is handy for taking a portion of pw’s colormap segment, starting at index for count entries, and rotating those entries among themselves for cycles. A cycle is defined as the count shifts it takes one entry to move through every position once. 3.7.5. Surface Preparation In order for a client to ignore the offset of his colormap segment the image of the pixwin must be initialized to the value of the offset. This surface preparation is done automatically by pixwins under the following circumstances: © The routine pw_damaged does surface preparation on the area of the pixwin that is dam- aged. © The routine pw_putcolormap does surface preparation over the entire exposed portion of a pixwin if a new colormap segment is being loaded for the first time. For monochrome displays, nothing is done during surface preparation. For color displays, when the surface is prepared, the low order bits (colormap segment size minus 1) are not modified. This means that surface preparation does not clear the image. Initialization of the image (often clearing) is still the responsibility of client code. There is a case in which surface preparation must be done explicitly by client code. When win- dow boundaries are knowingly violated (see vin_grabio), as in the case of pop-up menus, the following procedure must be called to prepare each rectangle on the screen that is to be written 3-20 Revision G of 15 April 1985 SunWindows Reference Manual Overlapped Windows: Imaging Facilities upon: pw_preparesurface (pw, rect) struct pixwin *pw; struct rect *r; rect is relative to pv’s coordinate system. Most commonly, a saved copy of the area to be written is made so that it can be restored later. Revision G of 15 April 1985 3-21 Chapter 4 Window Manipulation This chapter describes the sunwindow facilities for creating, positioning, and controlling windows. It continues the discussion begun in Overlapped Windows: Imaging Facilities, on the sunwindow level that allows displaying images on windows which may be overlapped. The structure that underlies the operations described in this chapter is maintained within the window system, and is accessible to the client only through system calls and their procedural envelopes, it will not be described here. The window is presented to the client as a device ; it is represented, like other devices, by a file descriptor returned by open. It is manipulated by other I/O calls, such as select, read, ioctl, and close. write to a window is not defined, since all the facilities of the previous chapter on Overlapped Windows: Imaging Facilities are required to display output on a window. The header file includes the header files needed to work at this level of the window system. 4.1. Window Data The information about a window maintained by the window system includes: • two rectangles which refer to alternative sizes and positions for the window on the screen; e a series of links that describe the window’s position in a hierarchical database, which deter- mines its overlapping relationships to other windows; • clipping information used in the processing described in Overlapped Windows: Imaging Facil- ities ; • the image used to track the mouse when it is in the window; • the id of the process which should receive SIGWINCH signals for the window (this is the owner process); o a mask that indicates what user input actions the window should be notified of; • another window, which is given any input events that this window does not use; and e 32 bits of data private to the window client. 4.2. Window Creation, Destruction, and Reference As mentioned above, windows are devices. As such, they are special files in the /dev directory with names of the form “/dev/vinn”, where n is a decimal number. A window is created by opening one of these devices, and the window name is simply the filename of the opened device. Revision G of 15 April 1985 4-1 Window Manipulation SunWindows Reference Manual 4-2.1. A New Window The first process to open a window becomes its owner. A process can obtain a window it is guaranteed to own by calling: int win_getnewwindow () This finds the first unopened window, opens it, and returns a file descriptor which refers to it. If none can be found, it returns —1. A file descriptor, often called the windowfd, is the usual han- dle for a window within the process that opened it. When a process is finished with a window, it may close it. This is the standard close (2) system call with the window’s file descriptor as argument. As with other file descriptors, a window left open when its owning process terminates will be closed automatically by the operating system. Another procedure is most appropriately described at this point, although in fact clients will have little use for it. To find the next available window, win_getnewwindow uses: int win_nextfree (fd) int fd; where fd is a file descriptor it got by opening /dev/winO. The return value is a window number, as described in References to Windows below; a return value of WIN_NULLLINK indicates there is no available unopened window. 4-2.2. An Existing Window It is possible for more than one process to have a window open at the same time; Providing for Naive Programs presents one plausible scenario for using this capability. The window will remain open until all processes which opened it have closed it. The coordination required when several processes have the same window open is described in Providing for Naive Programs. 4-2.3. References to Windows Within the process which created a window, the usual handle on that window is the file descrip- tor returned by open and win_getnewwindow. Outside that process, the file descriptor is not valid; one of two other forms must be used. One form is the window name (e.g., /dev/winl2); the other form is the window number, which corresponds to the numeric com- ponent of the window name. Both of these references are valid across process boundaries. The window number will appear in several contexts below. Procedures are supplied for switching the various window identifiers back and forth. win_numbertoname stores the filename for the window whose number is vinnumber into the buffer addressed by name: win_numbertoname (winrmmber , name) int winnumber ; char ‘name; name should be WIN_NAMESIZE long as should all the name buffers in this section. win_nametonumber returns the window number of the window whose name is passed in name: 4-2 Revision G of 15 April 1985 SunWindows Reference Manual Window Manipulation int win_nametonumber (name) char * name; Given a window file descriptor, win_fdtoname stores the corresponding device name into the buffer addressed by name: win_fdtoname (windowfd, name) int windowfd; char ‘name; The following returns the window number for the window whose file descriptor is windowfd: int win_fdtonumber (windowfd) int windowfd; 4.3. Window Geometry Once a window has been opened, its size and position may be set. The same routines used for this purpose are also helpful for adjusting the screen positions of a window at other times, when user-interface actions indicate that it is to be moved or stretched, for instance. The basic pro- cedures are: win_getrect (windowfd, rect) int windowfd; struct rect *rect; win_getsize (windowfd, rect) int windowfd; struct rect ‘rect; short win_getheight (windowfd) int windowfd; short win_getwidth (windowfd) int windowfd; win_getrect stores the rectangle of the window whose file descriptor is the first argument into the rect addressed by the second argument; the origin is relative to that window’s parent. Set- ting Window Links explains what is meant by a window’s “parent.” win_getsize is similar, but the rectangle is self-relative — that is, the origin is (0,0). win_getheight and win_getwidth return the single requested dimension for the indicated window. win_setrect copies the rect argument’s data into the rect of the indicated window: win_setrect (windowfd, rect) int windowfd; struct rect *rect; This changes its size and/or position on the screen. The coordinates are in the coordinate sys- tem of the window’s parent. Revision G of 15 April 1985 4-3 Window Manipulation SunWindows Reference Manual win_getsavedrect (windowfd, rect) int windowfd; struct rect *rect; win_setsavedrect (windowfd, rect) int windowfd; struct rect ‘rect; A window may have an alternate size and location; this facility is useful for icons (see Icons). The alternate rectangle may be read with win_getsavedrect, and written with win_setsavedrect. As with win_getrect and vin_setrect, the coordinates are rela- tive to the window’s parent. 4.4. The Window Hierarchy Position in the window database determines the nesting relationships of windows, and therefore their overlapping and obscuring relationships. Once a window has been opened and its size set, the next step in creating a window is to define its relationship to the other windows in the sys- tem. This is done by setting links to its neighbors, and inserting it into the window database. 4 . 4-1- Setting Window Links The window database is a strict hierarchy. Every window (except the root) has a parent; it also has 0 or more siblings and children. In the terminology of a family tree, age corresponds to depth in the layering of windows on the screen: parents underlie their offspring, and older windows underlie younger siblings which intersect them on the display. Parents also enclose their chil- dren, which means that any portion of a child’s image that is not within its parent’s rectangle is clipped. Depth determines overlapping behavior: the uppermost image for any point on the screen is the one that gets displayed. Every window has links to its parent, its older and younger siblings, and to its oldest and youngest children. Windows may exist outside the structure which is being displayed on a screen; they are in this state as they are being set up, for instance. The links from a window to its neighbors are identified by link selectors ; the value of a link is a window number. An appropriate analogy is to consider the link selector as an array index, and the associated window number as the value of the indexed element. To accommodate different viewpoints on the structure there are two sets of equivalent selectors defined for the links: WL_PARENT WL_OLDERSIB WI._YOUNGERSIB WL_OLDESTCHILD WL_YOUNGESTCHILD == WL_ENCLOSING == WL_COVERED == WL_COVERING == WL_BOTTOMCHILD == WL_TOPCHILD A link which has no corresponding window, for example, a child link of a “leaf” window, has the value WIN_NULLLINK. When a window is first created, all its links are null. Before it can be used for anything, at least the parent link must be set. If the window is to be attached to any siblings, those links should be set in the window as well. The individual links of a window may be inspected and changed by 4-4 Revision G of 15 April 1985 SunWindows Reference Manual Window Manipulation the following procedures. win_get 1 ink returns a window number. int win_getlink (windowfd, link_selector) int windowfd, link_selector ; This number is the value of the selected link for the window associated with windowfd. win_setlink (windowfd, link_selector , value) int windowfd, linl<_selector , value; win_setlink sets the selected link in the indicated window to be value, which should be another window number. The actual window number to be supplied may come from one of several sources: if the window is one of a related group, all created in the same process, file descriptors will be available for the other windows. Their window numbers may be derived from the file descriptors via win_fdtonumber. The window number for the parent of a new win- dow or group of windows is not immediately obvious, however. The solution is a convention that the \V1ND0W_PARENT environment parameter will be set to the filename of the parent. See Passing Parameters to a Tool for an example of this environment parameter’s usage. Activating the Window Once a window’s links have all been defined, the window is inserted into the tree of windows and attached to its neighbors by a call to win_insert (windowfd) int windowfd; This call causes the window to be inserted into the tree, and all its neighbors to be modified to point to it. This is the point at which the window becomes available for display on the screen. Every window should be inserted after its rectangle(s) and link structure have been set, but the insertion need not be immediate: if a subtree of windows is being defined, it is appropriate to create the window at the root of this subtree, create and insert all of its descendants, and then, when the subtree is fully defined, insert its root window. This activates the whole subtree in a single action, which typically will result in a cleaner display interaction. Once a window has been inserted in the window database, it is available for input and output. At this point, it is appropriate to call pw_open and access the screen. 4- 4-3. Modifying Window Relationships Windows may be rearranged in the tree. This will change their overlapping relationships. For instance, to bring a window to the top of the heap, it should be moved to the “youngest” posi- tion among its siblings. And to guarantee that it is at the top of the display heap, each of its ancestors must likewise be the youngest child of its parent. To accomplish such a modification, the window should first be removed: win_remove (windowfd) int windowfd; Revision G of 15 April 1985 4-5 Window Manipulation SunWindows Reference Manual After the window has been removed from the tree, it is safe to modify its links, and then reinsert it. A process doing multiple window tree modifications should lock the window tree before it begins. This prevents any other process from performing a conflicting modification. This is done with a call to: win_lockdata (windowfd) int windowfd; After all the modifications have been made and the windows reinserted, the lock is released with a call to: win_unlockdata (windowfd) int windowfd; Nested pairs of calls to lock and unlock the window tree are permitted. The final unlock call actually releases the lock. Note that if a client program uses any of the window manager routines, use of win_lockdata and win_unlockdata is not necessary. See Window Management in Chapter 9 for more details. Most routines described in this chapter, including the four above, will block temporarily if another process either has the database locked, or is writing to the screen, and the window adjustment has the possibility of conflicting with the window that is being written. As a method of deadlock resolution, SIGXCPU is sent to a process that spends more that 10 seconds of real time inside a window data lock, and the lock is broken. 4.5. User Data Each window has 32 bits of data associated with it. These bits are used to implement a minimal inter-process window-related status-sharing facility. Bits 0x01 through 0x08 are reserved for the basic window system; 0x01 is currently used to indicate if a window is a blanket window. Bits 0x10 through 0x80 are reserved for the user level window manager; 0x10 is currently used to indicate if a window is iconic. Bits 0x100 through 0x80000000 are available for client program- mer use. This data is manipulated with the following procedures: int win_getuser flags (windowfd) int windowfd; int win_setuser flags (windowfd, flags) int windowfd; int flags; int win_setuser flag (windowfd, flag, value) int windowfd; int flag; int value; win_getuser flags returns the user data. win_setuser flags stores its flags argument into the window struct. win_setuser f lag uses flag as a mask to select one or more flags in the data word, and sets the selected flags on or off as value is TRUE or FALSE. 4-6 Revision G of 15 April 1985 SunWindows Reference Manual Window Manipulation 4.0. Minimal-Repaint Support This section has strong connections to the preceding chapter and to Appendix A on Reels and Rectlists. Readers should refer to both from here. Moving windows about on the screen may involve repainting large portions of their image in new places. Often, the existing image can be copied to the new location, saving the cost of regenerat- ing it. Two procedures are provided to support this function: win_computeclipping(windowfd) int windowfd; causes the window system to recompute the exposed and damaged rectlists for the window identified by windowfd while withholding the SIGWINCH that will tell each owner to repair damage. win_partialrepair (windowfd, r) int windowfd; struct rect *r; tells the window system to remove the rectangle r from the damaged area for the window identified by windowfd. This operation is a no-op if windowfd has damage accumulated from a previous window database change, but has not told the window system that it has repaired that damage. Any window manager can use these facilities according to the following strategy: • The old exposed areas for the affected windows are retrieved and cached. (pw_exposed) • The window database is locked and manipulated to accomplish the rearrangement. (win_lockdata, win.remove, win_setlink, win.setrect, win_insert ...) • The new area is computed, retrieved, and intersected with the old. (win_computec lipping, pw_exposed, r l_intersection) • Pixels in the intersection are copied, and those areas are removed from the subject window’s damaged area. (pw_lock, pr_copy, win_partialrepair) • The window database is unlocked, and any windows still damaged get the signals informing them of the reduced damage which must be repaired. 4.7. Multiple Screens Multiple displays may be simultaneously attached to a workstation, and clients may want win- dows on all of them. Therefore, the window database is a forest, with one tree of windows for each display. Thus, there is no overlapping of window trees that belong to different screens. For displays that share the same mouse device, the physical arrangement of the displays can be passed to the window system, and the mouse cursor will pass from one screen to the next as though they were continuous. Revision G of 15 April 1985 4-7 Window Manipulation SunWindows Reference Manual struct singlecolor -{ u_char red, green, blue; >; struct screen < char scr_rootname [SCR_NAMESIZE] ; char scr_kbdname [SCR_NAMESIZE] ; char scr_msname [SCR_NAMESIZE] ; char scr_fbname [SCR_NAMESIZE] ; struct singlecolor scr_f oreground ; struct singlcolor scr_background; int scr_ flags; struct rect scr_rect; >; #def ine SCR_NAMESIZE 20 #def ine SCR_SWI TCHBKGRDFRGRD Oxl The screen structure describes a client’s notion of the display screen. There are also fields indicating the input devices associated with the screen. scr_rootname is the device name of the window which is at the base of the window display tree for the screen; the default is /dev/winO. scr_kbdname is the device name of the keyboard associated with the screen; the default is /dev/kbd. scr_msname is the device name of the mouse associated with the screen; the default is /dev/mouse. scr_fbname is the device name of the frame buffer on which the screen is displayed; the default is /dev/fb. scr_kbdname, scr_msname and scr_fbname can have the string “NONE” if no device of the corresponding type is to be asso- ciated with the screen. scr_ foreground is three RGB color values that define the fore- ground color used on the frame buffer; the default is {colormap size— 1, colormap size— 1, color- map size— 1}. scr_background is three RGB color values that define the background color used on the frame buffer; the default is {0, 0, 0}. The default values of the background and fore- ground yield a black on white image. scr_flags contains boolean flags; the default is 0. SCR_SWITCHBKGRDFRGRD is a flag that directs any client of the background and foreground data to switch their positions, thus providing a video reversed image (usually yielding a white on black image), scr.rect is the size and position of the screen on the frame buffer; the default is the entire frame buffer surface. win_screennew: int win_screennew (screen) struct screen ‘screen; opens and returns a window file descriptor for a root window. This new root window resides on the new screen which was defined by the specifications of ‘screen. Any zeroed field in ♦screen tells win_screennev to use the default value for that field (see above for defaults). Also, see the description of vin_initscreenfromargv below. If —1 is returned, an error message is displayed to indicate that there was some problem creating the screen. There can be as many screens as there are frame buffers on your machine and dtop devices configured into your kernel. The kernel calls screen instances desktops or dtops. vin_screenget: win_screenget (windowfd, screen) int windowfd; struct screen ‘screen; 4-8 Revision G of 15 April 1985 SunWindows Reference Manual Window Manipulation fills in the addressed struct screen with information for the screen with which the window indicated by windowfd is associated. win_screendestroy: win_screendestroy (windowfd) int windowfd; causes each window owner process (except the invoking process) on windowfd to be sent a SIGTERM signal. win_setscreenpositions informs the window system of the screens: win_setscreenposltions (windowfd, neighbors) int windowfd, neighbors [SCR_POSITIONS] ; #def ine SCR_NORTH 0 #def ine SCR_EAST 1 #def ine SCR_SOUTH 2 #def ine SCR_WEST 3 #def ine SCR_POSITIONS 4 This enables the cursor to cross to the appropriate screen, window fd’s window is the root for its screen; the four slots in neighbors should be filled in with the window numbers of the root windows for the screens in the corresponding positions. No diagonal neighbors are defined, since they are not strictly neighbors. win_getscreenpositions fills in neighbors with window fd’s screen’s neighbors: win_getscreenpositions (windowfd, neighbors) int windowfd, neighbors [SCR_POSITIONS] ; win_setkbd: int win_setkbd (windowfd, screen) int windowfd; struct screen ‘screen; is used to change the keyboard associated with window fd’s screen. Only the data pertinent to the keyboard is used (i.e., screen— >scr_kbdname). win_setms: int win_setms (windowfd, screen) int windowfd; struct screen ‘screen; is used to change the mouse associated with window fd’s screen. Only the data pertinent to the mouse is used (i.e., screen— >scr_msname). win_initscreen f romar gv: int win_lnltscreen fromar gv (screen , argv) struct screen ‘screen; char **argv; can be used to do a standard command line parse of argv into ‘screen. ‘screen is first zeroed. The syntax is: the screen associated with logical layout of multiple Revision G of 15 April 1985 4-9 Window Manipulation SunWindows Reference Manual [— d display device] [—in mouse device] [— k keyboard device ] [— i] [— f red green blue ] [— b red green blue J See suntools (1) for semantics and details. 4.8. Cursor and Mouse Manipulations This section describes the interface to the mouse and the cursor that follows the mouse. Both of these are maintained by the window system internals. 4-8.1. Cursors The cursor is the image which tracks the mouse on the screen: struct cursor short int struct >; { cur_xhot , cur_yhot ; cur_f unction ; pixrect *cur_shape; #def ine CUR_MAX I MAGE WORDS 16 cur_shape points to a memory pixrect which holds the actual image for the cursor. The win- dow system supports a cur_shape .pr_data— >md_image up to CUR_MAXIMAGEWQRDS words. This means that a cursor has a maximum size of 256 pixels, due to alignment constraints inherent in memory pixrects. The pixels in a cursor are usually arranged 16 x 1.6, although 8 pix- els high by 32 wide is also possible. The “hot spot” defined by (cur_xhot / cur_yhot) associates the cursor image, which has height and width, with the mouse position, which is a single point on the screen. The hot spot gives the mouse position an offset from the upper-left corner of the cursor image. Most cursors have a hot spot whose position is dictated by the image shape: the tip of an arrow, the center of a bullseye, the center of a cross-hair. Cursors can also be used as a status feedback mechanism, an hourglass to indicate that some processing is occurring for instance. This type of cursor should have the hot spot located in the middle of its image so the user has a definite spot for pointing and does not have to guess where the hot spot is. The function indicated by cur_ function is a rasterop (as described in Constructing an Op Argument), which will be used to paint the cursor. PDCSRC [ PEX_DST is generally effective on light backgrounds, for example in text, but invisible over solid black. PBCSRC A PEX_DST is a rea- sonable compromise over many different backgrounds, although it does poorly over a gray pat- tern. win_getcursor (windowfd, cursor) int windowfd; struct cursor ‘cursor; stores a copy of the cursor that is currently being used on the screen into the buffer addressed by cursor. Note that the caller must have set cursor->cur_shape to point to a pixrect large enough to hold the cursor image. 4-10 Revision G of 15 April 1985 SunWindows Reference Manual Window Manipulation win_setcursor (windowfd, cursor) int windowfd; struct cursor ‘cursor; sets the cursor and function that will be used whenever the mouse position is within the indi- cated window. If a window process does not want a cursor displayed, the appropriate mechanism is to set the cursor to one whose dimensions are both 0. Use the following macro as an aid in making your own cursor: DEFINE_CURSOR_FROM_IMAGE (name, hot_x, hot_y, func, image) This macro makes a cursor that is 16 bits wide by 16 bits high. It generates several static struc- tures. The first argument to the macro is the name that will be given to the cursor struct. The second and third arguments are the x and y positions of the hotspot relative to the upper- lefthand corner of the cursor shape. The fourth argument is the RasterOp function used to display the cursor, and the final argument is an array which contains 16 shorts that are the bit pattern of the cursor image. Typically this array will be declared as follows static short cursor_image [] = { #include " f ile_generated_by_icontool" >; For example, DEFINE_CURSOR_FROM_IMAGE might be used as follows: #include static short hour_glass_image [] = { #include "hourglass .pr" >; DEFINE_CURSOR_FROM_IMAGE (hour_glass, 8, 8, PIX_SRC|PIX_NOT / hour_glass_image) ; This defines a cursor called hour_glass which could then be used in some window. For exam- ple, win_setcursor (windowfd, &hour_glass) ; As an alternative, use the following macro; it takes the actual shorts for the image (il through il6) rather than the array. DEFINE_CURSOR (name, hot_x, hot_y, func, il, i2, i3, i4, i5, i6, i7, i8 , 19, ilO, ill, 112 , 113, 114, 115, 116) Note that due to the restictions imposed by the C pre-processor, you cannot use a # include in the call to the DEFINE_CURSOR macro to obtain il through il6 from a file. 4-8.2. Mouse Position Determining the mouse’s current position is treated under Input to Application Programs. We note here that the standard procedure for a process to track the mouse is to arrange to receive an input event every time the mouse moves; and in fact, the mouse position is passed with every user input a window receives. Revision G of 15 April 1985 4-11 Window Manipulation SunWindows Reference Manual The mouse position can be reset under program control; that is, the cursor can be moved on the screen, and the position that is given for the mouse in input events can be reset without the mouse being physically moved on the table top: win_setmouseposition (windowfd, x, y) int windowfd, x, y; puts the mouse position at (x, y) in the coordinate system of the window indicated by win- dowfd. The result is a jump from the previous position to the new one without touching any points between. Input events occasioned by the move, window entry and exit and cursor changes, will be generated. This facility should be used with restraint, as users are likely to lose a cursor that moves independently of their control. Occasionally it is necessary to discover which window underlies the cursor, usually because a window is handling input for all its children. The procedure used for this purpose is: int win_findintersect (windowfd, x, y) int windowfd, x, y; where windowfd is the calling window’s file descriptor, and (x, y) define a screen position in that window’s coordinate space. The returned value is a window number, x and y may lie outside the bounds of the window. 4.9. Providing for Naive Programs There is a large class of applications that are relatively unsophisticated about the window sys- tem, but want to run in windows anyway. For example, a simple-minded graphics program may want a window in which to run, but doesn’t want to know about all the details of creating and positioning it. This section describes a way of allowing for these applications. 4-9.1. Which Window to Use SunWindows defines an important environment parameter, WINDOW_GFX. By convention, WIND O W_GFX is set to a string that is the device name of a window in which graphics programs should be run. This window is already opened and installed in the window tree. Routines exist to read and write this parameter: int we_getgfxwindow (name) char ‘name we_setgfxwindow (name) char ‘name we_getgfxwindow returns a non-zero value if it cannot find a value. 4-9.2. The Blanket Window A good way to take over an existing window is to create a new window that becomes attached to and covers the existing window. Such a covering window is called a blanket window. The covered window will be called the parent window in this subsection because of its window tree relationship with a blanket window. Note: It’s a bad idea to take over an existing window using win_setowner. 4-12 Revision G of 15 April 1985 SunWindows Reference Manual Window Manipulation The appropriate way to make use of the blanket window facility is as follows: Using the parent window name from the environment parameter WINDOW_GFX (described above), open (2) the parent window. Get a new window to be used as the blanket window using win_getnewwindow. Now call: int win_insertblanket (blanketfd, parentfd) int blanketfd, parentfd; A non-zero return value indicates success. As the parent window changes size and position the blanket window will automatically cover the parent. To remove the blanket window from on top of the parent window call: win_r emoveb 1 anket (b 1 anket f d) int blanketfd; If the process that created the blanket window dies before win_removebl anket can be called, the blanket window will automatically be removed and destroyed upon automatic closure of the window device. This automatic closure happens because the only open file descriptor on the win- dow will be in the creating process. A non-zero return value from win_isbl anket indicates that blanketfd is indeed a blanket window. int win_isblanket (blanketfd) int blanketfd; 4.10. Window Ownership Note: Do not use the two routines in this section for temporarily taking over another window. These routines are included for backwards compatibility reasons. SIGWINCH signals are directed to the process that owns the window, the owner normally being the process that created the window. The following procedures may read from and write to the window: int win_getowner (windowfd) int windowfd; win_setowner (windowfd, pid) int windowfd, pid; win_getowner returns the process id of the indicated window owner. If the owner doesn’t exist, zero is returned. win_setowner makes the process identified by pid the owner of the window indicated by windowfd. win_setovner causes a SIGWINCH to be sent to the new owner. 4.11. Error Handling Except as explicitly noted, the procedures described in this section do not return error codes. The standard error reporting mechanism inside the sunwindow library is to call an error handling routine that displays a message, typically identifying the iocbl call that detected the error. After the message display, the calling process resumes execution. Revision G of 15 April 1985 4-13 Window Manipulation SunWindows Reference Manual This default error handling routine may be replaced by calling: int (*win_errorhandler (win_error) ) () int (*win_error) () ; The win_errorhandler procedure takes the address of one procedure, the new error handler, as an argument and returns the address of another procedure, the old error handler, as a result. Any error handler procedure should be a function that returns an integer. win_error (errnum, winopnum) int errnum, winopnum; errnum will be —1 indicating that the actual error number is found in the global errno. winopnum is the ioctl number that defines the window operation that generated the error. See Error Message Decoding in Programming Notes in the appendix. 4-14 Revision G of 15 April 1985 Chapter 5 Input to Application Programs This chapter continues the description of the sunwindow level of the Sun window system. Here we discuss how user input is made available to application programs. Unless otherwise noted, the structures and procedures discussed in this section are found in the header file /usr/include/sunwindow/vin_input . h. The window system provides facilities which meet two distinct needs regarding input to an appli- cation program: • A uniform interface to multiple input devices allows programs to deal with varying key- boards and positioning devices, ignoring complexities due to facilities which the programs do not use. ® Several different keyboards are available with Sun systems; they differ in the number and arrangement of keys. At a minimum, some clients will require ASCII characters, one per keystroke. More sophisticated clients will assign special values to non-standard keys (such as “META” characters in the range 0x80 and above). Some clients will assign functions to par- ticular keys on the keyboard, and will distinguish key-down from key-up events. • The standard positioning device on a Sun workstation is the mouse, which reports a location and the state of three buttons. Alternatively, some clients may use a tablet and stylus, or in place of the stylus, a “puck” with as many as 10 buttons on it. ® In some client systems, the time between input events is significant; for example, when smoothing a user’s stylus trace, or assigning special meaning to multiple clicks of a button within a short period. The window system allows clients with only the simplest requirements to ignore all the complica- tions, while providing more sophisticated clients the facilities they require. The mechanism for accomplishing this is called the virtual input device. This mechanism with its input events is described in Virtual Input Device. The second major section of this chapter describes how user inputs are collected from multiple sources, serialized, and distributed among multiple consumers. Multiple clients are able to accept inputs concurrently, and a slow consumer does not affect other clients’ ability to receive their inputs. Type-ahead and mouse-ahead are fully supported. ® Client programs operate under the illusion that they have the user’s full attention, leav- ing the window system to handle the multiplexing. Therefore, a client sees precisely those input events that the user has directed to that application. • Conversely, the client may require inputs from multiple devices, where the exact sequences across all those devices is significant. The order of mouse and function key events is likely to be significant, for instance. This is provided for via a single unified input stream, rather than requiring polling of multiple streams, which would be unac- ceptable in a multi-processed environment. Revision G of 15 April 1985 5-1 Input to Application Programs SunWindows Reference Manual ® The distribution of input events takes into account the window’s indication of what events it is prepared to handle; other events are redirected, allowing a division of labor among the various components of a system. 5.1. The Virtual Input Device This section describes the virtual device which generates user input, and how the input is presented to the client process. The device appears as an extended keyboard, different from existing keyboards, but incorporating the common features of most of them. It also incorporates a locator which indicates a screen position, and a clock which reports a time in seconds and microseconds. 5.1.1. Uniform Input Events Each user action generates an input event, which is reported in a uniform format regardless of the event. An event is reported in the following struct: struct inputevent ■{ short ie_code; short ie_ flags; short ie_shi f tmask ; short ie_locx; short ie_locy; struct timeval ie_tima; }; ie_code identifies the source of the event, as a switch position on a Virtual Input Device. The exact definition of the codes is given in Event Codes. In general, the input events fall into one of three classes: events that generate a single ASCII character; events related to locator motion and window geometry; and events identified with invocation of a special function, usually involving the depression or release of a single special button on the mouse or keyboard. These classes are known as ASCII, pseudo, and function events, respectively. The information provided by the code in ie_code is interpreted according to event flags in ie_f lags. (See Event Flags below.) The remaining elements of the struct provide general status information which may be useful on any event: ie_shiftmask is used to report the state of certain shift-keys that is, to modify the meaning of other events. and provide the position of the locator in the window’s coordinate system at the time the event occurred. provides a timestamp for the event, in the format of a system timeval, as defined in . ie_locx ie_locy ie_time 5-2 Revision G of 15 April 1985 SunWindows Reference Manual Input to Application Programs 5.1.2. Event Codes Event codes can take on any value in the range from 0 to 65535 inclusive. Of the codes defined in the header file, 256 are assigned to the ASCII event class and the other 128 are partitioned between the pseudo and function event classes. The following constants define the number of codes and the first and last code in the latter two classes: #define VKEY_CODES 128 #define VKEY_FIRST 32512 #def ine VKEY_LAST VKEY_FIRST+VKEY_C0DES-1 5. 1.2.1. ASCII Events The event codes in the range 0 to 255 inclusive are assigned to the ASCII event class. This class is further sub-divided: ^define ASCII_FIRST O #def ine ASCII_LAST 127 In particular, striking a key which has an obvious ASCII meaning causes the Virtual Input Dev- ice to enqueue for the client an event whose code is the 7-bit ASCII character corresponding to that key. Such a key with an obvious ASCII meaning is one in the main typing array labelled with a single letter of the alphabet. This is independent of the physical keyboard actually used. A slight complication occurs because of the presence of both upper- and lower-case characters in ASCII: if the user “shifts” the physical keyboard by depressing the CAPS-LOCK, SHIFT-LOCK, or SHIFT key the ie_code contains the shifted ASCII character corresponding to the struck key. For physical keystations that are mapped to cursor control keys, the current implementation transmits a series of events with codes that correspond to the ANSI X3.64 7-bit ASCII encoding for the cursor control function. For physical keystations that are mapped to function keys, the current implementation transmits a series of events with codes that correspond to an ANSI X3.64 user-definable escape sequence. For further details, see kbd(5). #define META^FIRST 128 #def ine META^LAST 255 Event codes from 128 to 255 inclusive are generated when the client has META translation enabled and the user strikes a key that would generate a 7-bit ASCII code while the META key is also depressed. In this case, the event code is the 7-bit ASCII code added to META_FIRST. 5. 1.2. 2. Function Events Event codes in the function class correspond to button strikes that do not result in generation of an event code in the ASCII class. In the function class are the event codes associated with locator buttons: #define BUT(i) A physical locator often has up to 10 buttons connected to it. Alternatively, even though the physical locator does not have any buttons physically available on it," it may have buttons on Revision G of 15 April 1985 5-3 Input to Application Programs SunWindows Reference Manual another device assigned to it. A light pen is an example of such a locator. In either case, each of the n buttons (where 0 < n <= 10) associated with the Virtual Input Device’s locator are assigned an event code; the i-th button is assigned the code BUT(i). Thus a 3-button mouse reports x and y and buttons 1—3. In the function class are the event codes associated with keyboard function keys that don’t gen- erate single ASCII charaters: #def ine KEY_LEET(i) #def ine KEY_RIGHT(i) #def ine KEY_TOP(i) #def ine KEY_BOTTOMLEFT #def ine KE Y_BOTTOMR I GHT The function keys in the Virtual Input Device define an idealized standard layout that groups keys by location: 16 left, 16 right, 16 top and 2 bottom. While the actual position on the key- board may be different, it is convenient to provide some grouping for the large number of func- tion keys. The mapping to physical keys on various keyboards is defined in and discussed in kbd(5). 5. 1.2. 3. Pseudo Events ttdefine VKEY_FIRSTPSEUDO #def ine VKEY_LASTPSEUDO Event codes in the pseudo class are events that involve locator movement instead of physical button striking. The physical locator constantly provides an (x, y) coordinate position in pixels; this position is transformed by the Virtual Input Device to the coordinate system of the window receiving an event. In order to watch actual locator movement (or lack thereof), the client must be enabled for the events with codes. #def ine LOC_MOVE #def ine LOC_MOVEWHILEBUTDOWN #def ine LOC_STILL A LOC_MOVE is reported only when the locator actually moves. Since fast motions may yield non-adjacent locations in consecutive events, the locator tracking mechanism reports the current position at a set sampling rate, currently 40 times per second. LOC3IOVEWHILEBUTDOWN is like LOC_MOVE but happens only when a button on the locator is down. A single LOCLSTILL event is reported when the locator has been still for a specified period, currently 1/5 of a second. Clients can be notified when the locator has entered or exited a window via the event codes: #define LOC_WINENTER #def ine LOC_WINEXIT 5-4 Revision G of 15 April 1985 SunWindows Reference Manual Input to Application Programs 5.1.3. Event Flags Only one event flag is currently defined: #def ine IE_NEGEVENT indicates the event was “negative.” Positive events include depression of any button or key, including buttons on the locator, motion of the locator device while it is available to this client, and entry of the cursor into a window. The only currently defined negative event is the release of a depressed button. Stopping of the locator and locator exit from the window are positive events, distinct from locator motion and window entry. This asymmetry allows a client to be informed of these events without the performance penalty associated with receiving all negative events and then discarding all but these two. Two macros are defined to inquire about the state of this flag: #define win_inputnegevent (ie) #define win_inputposevent (ie) struct inputevent *ie; These are TRUE or FALSE if the IE_NEGEVENT bit is 1 or 0 respectively in the input event pointed to by ie. 5.1.4- Shift Codes ie_shiftmask contains a set of bit flags which indicate an interesting state when an input event occurs. The most obvious example is the state of the Shift or Control keys when some other key is pressed. Eventually, clients will be able to declare any Virtual Input switch as an “interesting” shift switch. For now, only the following bits are reported: #def ine CAPSMASK OxOOOl #def ine SHIFTMASK OxOOOE #def ine CTRLMASK 0x0030 #def ine UPMASK 0x0080 These are defined in , and described in kbd(5). 5.2. Reading Input Events A library routine exists for reading the next input event for a window: int input_readevent (fd, ie) int fd; struct inputevent *ie; This fills in the indicated struct, and returns 0 if all went well. In case of error, it sets the global variable errno, and returns —1; the client should check for this case. A window can be set to do either blocking or non-blocking reads via a standard fcntl system call, as described in fcntl (2) (using F_SETFL) and fcntl (5) (using FNDELAY). A window is defaulted to blocking reads. The blocking status of a window can be determined by the fcntl system call. Revision G of 15 April 1985 5-5 Input to Application Programs SunWindows Reference Manual A window process can ask to be sent a SIGIO if any input is pending in a window. Enabling this option is also via a standard fcntl system call, as described in fcntl(2) (using F_SETFL) and fcntl(5) (using FASYNC). The programmer can set up a signal catcher for SIGIO by using the signal (3) call. The number of character in the input queue of a window can be determined via a FBIONREAD ioctl (2) call. FBIONREAD is described in tty (4). Note that the value returned is the number of bytes in the input queue. If you want the number of inputevents then you need to divide by sizeof (struct inputevent) . The recommended normal style for handling input uses blocking I/O and the select (2) system call to await both input events and signals such as SIGWINCH. This allows a signal handler to merely set a flag, and leave substantial processing to be performed synchronously when the select returns. The tool_select mechanism described in chapter 6 illustrates this approach. Using blocking I/O and read (2) without a prior select forces the client to process SIGWINCH signals entirely in the asynchronous interrupt handler. This necessitates extra care to avoid race conditions and other asynchronous errors. Non-blocking I/O may be useful in a few circumstances. For example, when tracking the mouse with an image which requires significant computation, it may be desirable to ignore all but the last in a queued sequence of motion events. This is done by reading the events, but not process- ing them until a non-motion event is found, or until all events are read. Then the most recent mouse location is displayed, but not all the points covered since the last display. When all events have been read and the window is doing non-blocking I/O, input_readevervt returns —1 and the global variable errno is set to EWOULDBLOCK. 5.3. Input Serialization and Distribution With the exception of some of the pseudo event codes, the Virtual Input Device described in preceding sections is not logically tied to the Sun window system; the scheme could be used by any system desiring that form of unification. This section is more specific to the window system, since it discusses how events are selected and distributed among the various windows which might use them. Each user input event is formatted into an inputevent, which is then assigned to some reci- pient. There are three ways a process gets to receive an input event: © Most commonly, it reads the window which lies under the cursor, and that window has an input mask which matches the event. Input masks are described in Input Masks. If several windows are layered under the cursor, the event is tested first against the input mask of the topmost window. • If the event does not match the input mask of one window, other windows will be given a chance at it, as described below. • Much less frequently, a window will be made the recipient of all input events; this is dis- cussed under win_grabio below. Each window designates another window to be offered events which the first will not accept. By default this is the window’s parent; another backstop may be designated in a call to win_setinputmask, described in the next section. If an event is offered unsuccessfully to the root window, it is discarded. Windows which are not in the chain of designated recipients never have a chance to accept the event. 5-6 Revision G of 15 April 1985 Sun Windows Reference Manual Input to Application Programs If a recipient is found, the locator coordinates are adjusted to the coordinate system of the reci- pient, and the event is appended to the recipient’s input stream. Thus, every window sees a sin- gle stream of input events, in the order in which the events happened (and time-stamped, so that the intervals between events can also be computed), and including only the events that window has declared to be of interest. 5.8.1. Input Masks The input masks facilitate two things: © Events can be accepted or rejected by classes; for instance, a process may want only ASCII characters. ® The times when events are accepted can be controlled, minimizing the processing required to accept and ignore uninteresting events. For instance, a process may track the mouse only when it is inside one of its windows, or when one of the mouse buttons is down. Clients specify which input events they are prepared to process by setting the input mask for each window being read. struct inputmask { short im_ flags ; char im_inputcode [IM_CODEARRAYSIZE] ; short lm_shifts; short im_shiftcodes [IM_SHIFTARRAYSIZE] ; >; #def ine IM_CODEARRAYSIZE (VKEY_CODE/ ( (sizeof char) *BITSPERBYTE) ) #def ine IM_SHIFTARRAYSIZE ((sizeof short) *BITSPERBYTE) ±m_ flags specifies the handling of related groups of input events: ^define IM_ASCII indicates that the Virtual Input Device translation should occur. #define IM_ANSI indicates that the process wants keystrokes to be interpreted as ANSI characters and escape sequences: normal ASCII characters are represented by their ASCII code in ie_code, described in Uniform Input Events. Function keys with a standard interpretation, such as the cursor con- trol keys, are represented by a sequence of input events, whose ie_codes are ASCII characters starting with . See kbd(5) for further details. #def ine IM_POSASCII indicates that the client only wants to be notified of positive events for ASCII class events, even though IM_NEGEVENT is enabled. Note: The current implementation automatically enables both IM.ANSI and IM_POSASCII when IMASCn is specified. Requesting a particular function event in addition turns off any ANSI escape-coding for that function event. tdefine IM_META indicates that META-translation should occur. This means ASCII events that occur while the Revision G of 15 April 1985 5-7 Input to Application Programs SunWindows Reference Manual META key is depressed are reported with codes in the META range. Note that IM_META does not make sense unless IM_ASCn is enabled. #def ine IM_NEGEVENT indicates that the client wants to be notified of negative events as well as positive ones. See Event Flags for a discussion of positive and negative events. #def ine IM_UNENCODED indicates that no translation of physical device events should be performed. The Virtual Input Device should not intervene between the window and the user input. In this case, the most significant byte of ie_code in an input event is the id number of the device that generated the event, and the least significant byte contains the physical keystation number of the keystation that the user struck. The current device ids are those assigned to the supported keyboards and the id assigned to the mouse #def ine MOUSE_DEVID 127 For unencoded mouse input, the least significant byte of the event code is identical to the least significant byte of the corresponding encoded input event. Note that unencoded pseudo events are associated with the physical locator; that is, a button-push on a tablet puck will generate a different code from a corresponding button-push on a mouse. im_inputcode is an array of bit flags indexed by biased event codes. A 1 in the ith position of the bit array indicates that the event with code VKEY_FIRST-|-i should be reported. This filter applies in both IM_UNENCODED and IM_ASCII modes. There are two routines which are of interest here. win_setinputmask (wlndowfd, acceptmask, flushmask, designee) int wlndowfd; struct inputmask ‘acceptmask, ‘flushmask; int designee; sets the input mask for the window identified by window fd. acceptmask addresses the new mask — events it passes will be reported to this window after the call to win_setinputmask. flushmask specifies a set of events which should be flushed from this window’s input queue. These are events which were accepted by the previous mask, and have already been generated, but not read, by this window. This is a dangerous facility; type-ahead and mouse-ahead will often be lost if it is used. The most obvious application is for confirmations, but these can be better implemented by requiring the confirmation within a short time-out. Note: If flushmask is non-NULL, the current implementation flushes all events from the queue, not just those specified in flushmask. designee is the window number, which specifies the next potential recipient for events rejected by this window. If it is set to WIN_NULLLINK (defined in ), it is interpreted as designating the window’s parent. Note: Changing masks in response to some input should be done with caution. There will be a lapse of time between the event which persuades the client it wants a new mask and the time the system interprets the resulting call to win_setinputmask. Events which occur in this interval will be passed or discarded according to the old input mask. Thus, it is probably not appropriate to wait for a button down before requesting the corresponding button-up; the button-up may arrive and be discarded before the mask is changed. It’s less dangerous to wait until a button goes down to start tracking the mouse, since the client will be caught up as soon 5-8 Revision G of 15 April 1985 SunWindows Reference Manual Input to Application Programs as the first motion event arrives. But even here, it’s better to ask for the LOC3IOVEWHILEBUTDOWN event, and never change the mask. The input mask for a window is read with win_getinputmask (windowfd, im, designee) int windowfd; struct inputmask *im; int ‘designee; The input mask for the window identified by windowfd is copied into the buffer addressed by im. The number of the window that is the next possible recipient of input is copied into the integer addressed by designee. We return to win_input.h for these routines useful for manipulating input masks. The first three are macros; ^define win_setinputcodebit (im, code) struct inputmask *im; char code; sets the bit indexed by code in the input mask addressed by im to 1. #define win_unsetinputcodebit (im, code) struct inputmask *im; char code; resets the bit to zero. The routine: #define win_getinputcodebit (im, code) struct inputmask *im; char code; returns non-zero if the bit indexed by code in the input mask addressed by im is set. input_imnull (mask) struct inputmask ‘mask; is a procedure which initializes an input mask to all zeros. It is critical to initialize the input mask explicitly when the mask is defined as a local procedure variable. 5.3.2. Seizing All Inputs Normally, input events are directed to the window which underlies the cursor at the time the event occurs. Two procedures modify that behavior. A window may temporarily seize all inputs by calling: win_grabio (windowfd) int windowfd; The caller’s input mask still applies, but it receives input events from the whole screen; no win- dow other than the one identified by windowfd will be offered an input event or allowed to write on the screen after this call. win_releaseio (windowfd) int windowfd; undoes the effect of a win_grabio, restoring the previous state. Revision G of 15 April 1985 5-9 Input to Application Programs SunWindows Reference Manual 5.4. Event Codes Defined In the following table are collected together all of the special event code names discussed above. These names define values which appear in the ie_code field of an inputevent. As the sys- tem evolves, the particular value bound to a name is likely to change, thus event codes should be compared to the symbolic names below, not to the current values of those names. #define ASCI I_FIRST (0) #define ASCI I_LAST (127) #define META-FIRST (128) #def ine META-LAST (255) #define VKEY_ CODES (128) #define VKEY—FIRST (32512) #def ine VKEY—F IRSTPSEUDO (VKEY—FIRST) #def ine LOC_MOVE (VKEY— FIRSTPSEUDO+O) #def ine LOC_STILL (VKEY— FIRSTPSEUDO+1) #define LOC_WINENTER (VKEY— FIRSTPSEUDO+2) #define LOC_WINEXIT (VKEY— FIRSTPSEUDO+3) #define LOC_MOVEWHILEBUTDOWN (VKEY— FIRSTPSEUDO+4) #define VKEY_LASTPSEUDO (VKEY— FIRSTPSEUDO+15) #define VKEY—F IRSTFUNC (VKEY— LASTSHIFT+1) #def ine BUT_FIRST (VKEY_F IRSTFUNC) #def ine BUT (i) ( (BUT_FIRST) + (i)-l) #def ine BUT-LAST (BUT— FIRST+9) #def ine KEY-LEFTFIRST ( (BUT_LAST) +1) #define KEY-LEFT (i) ( (KEY_LEFTFIRST) + (i) -1) #define KEY_LEFTLAST ( (KEY-LEFTFIRST) +15) #define KEY_RIGHTFIRST ( (KEY-LEFTLAST) +1) #def ine KEY-RIGHT (i) ( (KEY-RIGHTFIRST) + (i) -1) #define KEY-RIGHTLAST ( (KEY_RIGHTFIRST) +15) #def ine KEY-TOPFIRST ( (KEY-RIGHTLAST) +1) #def ine KEY-TOP (i) ( (KEY-TOPFIRST) + (i) -1) #define KEY_TOPLAST ( (KEY_TOPFIRST) +15) #define KEY-BOTTOMLEFT ( (KEY_TOPLAST) +1) #def ine KEY-BOTTOMRIGHT ( (KEY_BOTTOMLEFT) +1) #define VKEY— LASTFUNC (VKEY—F IRSTFUNC+ 101) tdefine VKEY— LAST VKEY— FIRST+ VKEY— CODES— 1 There are 3 synonyms for the common case of a 3-button mouse: #define MS-LEFT BUT(l) ttdefine MS_MIDDLE BUT (2) #def ine MS_RIGHT BUT (3) 5-10 Revision G of 15 April 1985 Chapter 6 Suntool: Tools and Subwindows This chapter introduces the third and highest level of SunWindows, suntools. It discusses how to write a tool: it covers creation and destruction of a tool and its subwindows, the strategy for dividing work among them, and the use of routines provided to accomplish that work. At the suntools level, the lower-level facilities are actually used to build user interfaces. This chapter also describes a model for building applications, a number of components that implement commonly-needed portions of such applications, and an executive and operating environment that supports that model. We refer to an application program that is a client of this SunWindows level as a tool. Tool cov- ers the one or more processes that do the actual application work. This term also refers to the collection of typically several windows through which the tool interacts with the user. Simple tools might include a calculator, a bitmap editor, and a terminal emulator. Sun Microsystems provides a few ready-built tools, several of which are illustrated in Appendix B. Others may be developed to suit particular needs. Common SunWindows tool components and their functions include: • A standard tool window that frames the subwindows of the tool, identifying it with a name stripe at the top and borders around the subwindows. Each tool window can adjust its size and position, including layering, and subwindow boundary movement. e An executive framework that supplies the usual “main loop” of a program, and which coor- dinates the activities of the various subwindows. • Several standard subwindows that can be instantiated in the tool. 0 A standard scheme for laying out those subwindows. » A facility that provides a default icon, which is a small form the tool takes to be unobtrusive but still identifiable. The suntools program initializes and oversees the window environment. It provides: 0 Automatic startup of a specified collection of tools. • Dynamic invocation of standard tools through a menu interface. ® Management of the window, called the root window, which underlies all tools and paints a simple pattern. e The user interface for leaving the window system. Users desiring another interface to these functions can replace the suntools program, while retaining specific tools. The procedures that support the facilities described in this chapter and the following two are in the suntool library, /usr/lib/libsuntool . a. These procedures and their data structures are declared in a number of distinct header files, which are included in Revision G of 15 April 1985 6-1 Suntool: Tools and Subwindows SunWindows Reference Manual . 6.1. Tools Design A typical tool is built as a tool window, and contained within that, a set of aubwindowa, which incorporate most of the user interface to the tool’s facilities. Each subwindow is a “window” in the sense described in Window Manipulation ; the subwindows form a subtree rooted at the tool window, and the various tool windows are all children of the root window associated with the screen. 6.1.1. N on-Pre-emptive Operation In general, tools should be designed to function in a non-pre-emptive style: they should wait without consuming resources until given something to do, perform the task expeditiously, and promptly return control to the user. If some task requires extensive processing, a separate pro- cess should be forked to run it without blocking the user interface. This non-pre-emptive style implies that the tool is built as a set of independent procedures, which are invoked as appropriate by a standardized control structure. The basic advice to client programs is, “Wait right there; we’ll let you know as soon as we have something for you to do.” From a programming point of view, the main function that the tool mechanism provides is the provision of the control structure to implement this non-pre-emptive programming style. The tool window and its subwindows all have the same interface to this control mechanism. 6.1.2. Division of Labor The tool window performs a few functions directly. These are the user interface functions, which are common to all tools. Subwindows are the workhorses of the suntool environment, but most of the work they do is specific to their own tasks, and of little interest here. It is important to understand that a subwindow corresponds to a data type: there will be many instantiations of particular subwin- dows, quite possibly several in a single tool. Various types of subwindows are developed as separate packages that can be assembled at a high level. In addition to programmer convenience, this approach promotes a consistent user inter- face across applications. The remainder of this chapter divides a tool’s existence into two large areas: creation and des- truction, and tool-specific aspects of processing. 6.2. Tool Creation All of the following processing must be performed as a tool is started: • Parameters for this invocation of the tool are passed to it. Some of the parameters are application specific and some parameters are generic to all tools. • The tool window is created with space allocated for it and its various options defined; simi- larly, its subwindows are created and positioned in the tool window. 6-2 Revision G of 15 April 1985 SunWindows Reference Manual Suntool: Tools and Subwindows © The UNIX signal system is initialized to catch appropriate signals, e.g., SIGWINCH, that will be sent to the tool’s process. • The tool’s window is installed into the display structure. ® Finally, the tool starts its normal processing. 6.2.1. Tool Attributes The programming interface to the tool window is based on attribute manipulation. An attribute is an identifier/ value pair. The identifier is an integer constant. The value is a long word (32 bit) quantity that may be a single numeric quantity or a pointer to other data. Attributes can be gathered together into an attribute list. An attribute list can contain other attribute lists as well. The tool window has a collection of attributes that can be set to affect the behavior of the tool window. The following table lists each tool attribute, followed by the type of value that may be assigned to it, and a short description of the attribute’s meaning. The procedures used to mani- pulate these attributes are discussed throughout this chapter. Tool attribute identifiers are defined in . Revision G of 15 April 1985 6-3 Suntool: Tools and Subwindows SunWindows Reference Manual Table 6-1: Summary of Tool Attributes Summary of Tool Attributes Name Value type win_columns [unsigned int] WIN_LINES [unsigned int] WIN_WIDTH [unsigned in WIN_HEIGHT [unsigned in WIN_LEFT [int] WIN_TOP [int] WIN_ICONIC [0 or l] WIN_REPAINT_LOCK [0 or 1] Description This attribute is the width, in columns of characters, of the internal area of a tool that is available to subwindows. A tool is 80 columns by default. This attribute is the height, in rows of characters, of the internal area of a tool that is available to subwin- dows. A tool is 34 rows by default. This attribute is the width, in pixels, of a normal sized tool. This attribute is the height, in pixels, of a normal sized tool. This attribute is the x position of the upper left hand corner, in pixels, of the tool. This attribute is the y position of the upper left hand corner, in pixels, of the tool. This attribute is the state of the tool: 0 means normal state (opened) and 1 means iconic state (closed). A tool is open by default. This attribute indicates the state of a tool’s repaint lock: 0 means repaint as usual and 1 means don’t repaint as usual. Turning of! the repaint lock or explicitly calling tool_display forces a repaint. One might turn on the repaint lock if one was doing a batch of things to the tool and only wanted the tool’s image to repaint once at the end of the changes. This attribute is 0 by default. 6-4 Revision G of 15 April 1985 SunWindows Reference Manual Suntool: Tools and Subwindows Summary of Tool Attributes Name Value tvDe Description WIN_LAYOUT_LOCK [0 or 1] This attribute indicates the state of a tool’s subwindow layout lock, 0 means use the tool’s tiling algorithm to lay out the position and size of subwindows, and 1 means don’t do any layout. Turning on the layout lock makes subwindow layout the programmer’s complete responsibility (see tool_layoutsubwindows). This attribute is 0 by default. WI N_NAME_S TR I PE [0 or 1] This attribute indicates whether the tool has a name stripe at the top of the tool: 1 means yes and 0 means no. This attribute is 1 by default. WI N_BOUNDARY_MGR [0 or 1] This attribute indicates whether the user is allowed to try to interactively move the boundary between subwin- dows of the tool with the mouse. A 1 value means yes and a 0 value means no. This attribute is 0 by default. WIN_LABEL [char *] This attribute indicates the string used in the name stripe of the tool. This attribute is NULL by default. WIN_ICON [struct icon *] This attribute is the icon used by the tool. Its default value is NULL which means that a default iconic image is displayed. WIN_ICON_LEFT [int] This attribute is the x position, in pixels, of the upper left hand corner of an iconic tool. WI N_ I CON_TOP [int] This attribute is the y position of the upper left hand corner, in pixels, of an iconic tool. WIN_ICON_LABEL [char *] This attribute indicates the string used as the text in the icon. This attribute is NULL by default. Note: The current implementation of this attribute does not support setting it unless a WINJCON has been done already. Revision G of 15 April 1985 6-5 Suntool: Tools and Subwindows SunWindows Reference Manual Name WIN_ICON_IMAGE WI N_ I CON_F ONT WIN_ J ATTR_LIST WIN_DEFAULT_CMS Summary of Tool Attributes Value type Description [struct pixrect *] This attribute is the memory pixrect used for the graphic portion of the icon. It’s default value is NULL which means that a default iconic image is displayed. Note: The current imple- mentation of this attribute does not support setting it unless a WIN_IGON has been done already. [struct pixfont *] This attribute is the font handle used to display text in the icon. Its default value is NULL, which means that the system default font is displayed. Note: The current imple- mentation of this attribute does not support setting it unless a WINJCON has been done already. [char **] This is a pseudo-attribute that is a list of other attributes. A 0 attribute identifier terminates the list. Query- ing for this attribute is an error. [0 or 1] This attribute indicates the state of the default colormap segment. The default colormap segment is that to which newly created pixwins are ini- tialized. Normally, the default color- map segment is named “mono- chrome” with its two colors defined by the values set during screen crea- tion. If the value of WIN_DEFAULT_CMS is 1 then the colormap segment currently being used by the tool window is set to be the default colormap segment for the tool’s process. This attribute is 0 by default. WIN_DEFAULT_CMS is usu- ally set to 1 from the command line so that the tool window colors, set with WIN_FOREGROUND and WIN_BACKGROUND, are used for all the subwindows as well. Note: The current implementation of this attri- bute does not support resetting it back to 0 once set to 1. 6-6 Revision G of 15 April 1985 SunWindows Reference Manual Suntool: Tools and Subwindows Summary of Tool Attributes Name Value type Description WIN_FORE GROUND [struct singlecolor *] This attribute indicates the fore- ground color of the tool window. This attribute’s default value is the foreground color set during screen creation. WIN_ BACKGROUND [struct singlecolor *] This attribute indicates the back- ground color of the tool window. This attribute’s default value is the background color set during screen creation. Revision G of 15 April 1985 6-7 Suntool: Tools and Sub-windows SunWindows Reference Manual 6. 2.1.1. The Tool Struct The tool structure is considered private to the implementation of the tool. Its data should be accessed indirectly via attribute calls. However, in previous versions of the system, programmers were instructed to write code that directly accesses this structure, and not all tool data is directly accessible via the attributes mechanism. Therefore, this section describes the fields of the structure. Note: Mixing access of the tool structure by direct access (via tool structure field reference) and indirect access (via attributes) will often yield incorrect results. The attribute interface dynamically allocates storage for the fields of the tool struct while the old interface saved whatever the programmer handed it. The tool struct is defined in . It is: struct tool { short tl_ flags; int tl_windowfd; char *tl_name; struct icon *tl_icon; struct toolio tl_io; struct toolsw *tl_sw; struct pixwin *tl_pixwin; struct rect tl_rectcache; >; tl_ flags holds state information. Currently, there are 6 defined flags: ^define TOOL_NAME STRIPE OxOl #define TOOL_BOUNDARYMGR 0x02 #def ine T00L_IC0NIC 0x04 #define T00L_SIGCHLD 0x08 #def ine T00L_SIGWINCHPENDING 0x10 #def ine T00L_D0NE 0x20 Their meanings are as follows: TOOLJMAMESTRIPE indicates that the tool is to be displayed with a black stripe holding its name at the top of its window. TOOLJBOUNDARYMGR enables the option that allows the user to move inter-subwindow boundaries. TOOLJCONIC indicates the current state of the tool: 1 = small (iconic); 0 = normal (open). Note that client programs should never set or clear the TOOL_ICONIC flag. TOOL_SIGCHLD and T00LJ5IGWINCHPENDING mean that the tool has received the indicated signal and has not yet performed the processing to deal with it. TOOL_DONE indicates the tool should exit the tool_select notification loop. 6-8 Revision G of 15 April 1985 SunWindows Reference Manual Suntool: Tools and Subwindows The last three flags are used during tool_select processing described below and should be considered private to the tool implementation. tl_windowfd holds the file descriptor for a tool’s window. This is used for both input and output. It also identifies the window for manipulations on the window database, such as modifying its position or shape. Possible uses of window fd are dis- cussed in chapters 3 through 5. tl_name addresses the string that can be displayed in the tool’s namestripe and default icon. tl_rect cache holds a rectangle that indicates the size of the tool’s window. Because the rec- tangle is in the tool’s coordinate system, the origin will always be (0, 0). This size information is cached so that the tool can tell when its size has changed by comparing the cached rect with the current rect. tl_icon holds a pointer to the icon struct for this tool. tl_pixwin addresses the window’s pixwin, which is the structure through which the tool accesses the display. tl_sw points to the first and oldest of the tool’s subwindows. The following section discusses these structs. The tool uses tl_io to control notification of input and window change events to itself. Toolio Structure details this structure type. During tool creation, the fields of this structure are set up with values to do default tool processing. 6.2.2. Tool Initialization Parameters Tool manager specific parameters are passed through the environment and via the command line. Most programmers can ignore the environment parameters, which are described below in Environment Parameters. However, most programmers do need to deal with command line argu- ments. 6. 2. 2.1. Command Line Parsing The following table lists the command line arguments that the user should be able to pass to a tool on the command line. All tools should be able to accept these arguments and thus they are called generic tool arguments. Revision G of 15 April 1985 6-9 Suntool: Tools and Subwindows SunWindows Reference Manual Table 6-2: Generic tool arguments FLAG ARGS ATTRIBUTE -Ww (-width) column WIN_COLUMNS -Wh (-height) line WIN_LINES -Ws (-size) xy WIN_WIDTH WINJIEIGHT -Wp (-position) xy WIN_LEFT WIN.TOP -WP (-icon_position) x y WIN_JCON_LEFT WIN_ICON_TOP -W1 (-label) string WIN_LABEL -Wi (-iconic) WINJCONIC -Wn (-no_name_stripe) WIN_NAME_STRIPE -Wt (-font) filename -Wf (-foreground_color) red green blue WIN_FOREGROUND -Wb (-background_color) red green blue WIN_BACKGROUND -Wg (-set_default_color) WIN_DEFAULT_CMS -WT (-icon_image) filename WIN_ICON_IMAGE -WL (-iconjabel) »» , »t string WIN_ICON_LABLE -WT -WH (-icon_font) (-help) filename WIN_ICON_FONT So that tool builders can parse the command line for generic tool arguments in a uniform way, some utilities are provided. int tool_parse_all (argc_ptr , argv, tool_args_ptr , tool_name) int *argc_ptr; char **argv; char * * *tool_args_ptr ; char *tool_name; tool_parse_al 1 scans the entire length of argv for generic tool arguments and builds up an attributes list in *tool_args_ptr. It is important to initialize *tool_args_ptr to NULL before making this call. As flags and their arguments are successfully parsed argv is modified to no longer contain the matched arguments and *argc_ptr is decremented. *argc_ptr is the count of elements in argv. tool_name is passed in so that meaningful error messages can be sent to stderr if an error is detected in the command line. tool_parso_al 1 returns —1 to indicate such an error and 0 to signify success. When an error is detected, it is a good idea to call tool_usage. tool_usage (tool_name) char *tool_name; tool_usage sends an message to stderr listing the command line format of generic tool arguments. tool_name is used in formatting the message. Some programs have reason to not give over control of their command lines to tool_parse_all. For these programs, tool_parse_one is provided. int tool_parse_one (argc, argv, tool_args_ptr , tool_name) int argc; char **argv; char * * *tool_args_ptr ; char *tool_name ; 6-10 Revision G of 15 April 1985 SunWindows Reference Manual Suntool: Tools and Subwindows tool_parse_one scans the first string in argv for a generic tool argument flag. If it finds one, the attributes list in *tool_args_ptr has another attribute added to it. It is important to initialize *tool_args_ptr to NULL before calling this routine for the first time. Unlike tool_parse_all, tool_parse_one doesn’t modify argv or argc. A positive number return value indicates how many arguments from the front of argv were used. It is then the callers responsibility to modify argv and argc. Error reporting is as with tool_parse_al 1. Some programs want the convenience of tool_parse_al 1 but would like to explicitly deter- mine if a particular attribute has been specified by the user from the command line. Tool_find_attribute is a utility to help do this. int tool_f ind_attribute (tool_args , id, value_ptr) char **tool_args; int id; char **value_ptr; tool_find_attribute looks for the attribute identifier id in tool_args. If the attribute is not found then the return value is 0. If the attribute is found then the return value is 1 and *value_ptr is set to the value of the attribute. The storage for *value_ptr must later be released via a call to tool_free_at:tribute (described below). The storage used for the attribute list built up by the calls to tool_parse_al 1 and tool_parse_one should eventually be freed via a call to tool_free_attribute_list. int tool_free_attribute_list (tool_args) char **tool_args; too l_free_attribute_ list releases the storage used by tool_args after releasing all the storage for its component attributes. This call is most often made just after calling tool_make. 6.2.3. Creating the Tool Window The pair of procedures tool_make and tool_createsubwindow perform the main work of creating a tool with its subwindows. These take a series of parameters that define the object to be created, and return a pointer to an object that encapsulates the information about the tool or a subwindow. That pointer is then passed to a number of other routines that manipulate the object; the client is usually not concerned with the exact definition of the structure. tool_make and tool_createsubwindow include a large part of the processing described in the earlier parts of this manual. Thus, client programmers need not necessarily concern them- selves much with the details of pixwins and window devices. A tool is created by a call to: /* VARARGS */ struct tool *tool_make (id, value, id, value, ... 0) int id; caddr_t value; tool_make takes a variable number of attribute identifier/value pairs, terminated by the spe- cial attribute identifier 0. These attributes control the behavior of the tool. A list of valid attri- butes is available in the section Tool Attributes. id’s are the attribute identifiers, value’s are the attribute values of the preceding id. A tool handle is returned. If the tool handle is Revision G of 15 April 1985 6-11 Suntool: Tools and Subwindows SunWindows Reference Manual NULL then the call failed. tool_make changes the process group of the current process to the current process id. All value arguments passed into tool_make are copied. Thus, all subsequent accesses of tool attribute values must use tool_get_attribute (see Changing the Tools’ Attributes). For example, if you use WINJCON to set the tool’s icon, changing the icon structure after you passed it into tool_make will not change the tool’s icon. There are parameters passed in the environment (see Environment Parameters ) that tool_make examines during its execution. Attribute arguments to tool_make that duplicate environment parameters override the environment parameters. In addition, an attribute specified early in the calling sequence is overridden by a later instance of the same attribute. Thus, the order of attributes in the call to tool_make is significant. Here is how attributes should be ordered in the call to tool_make: ® Attributes that set the default setting for the tool should come first, e.g., WIN_LABEL and WINJCON. e Attributes that the user has specified from the command line should come next, i.e., specify WIN_ATTRJLIST and its value. ® Attributes that you, as the programmer, are absolutely not going to allow the user to over- ride should come last, e.g., WIN_WIDTH and WINJIEIGHT if you insist that the tool be started a fixed size. Here is a sample call to tool_make that illustrates the ordering of attributes as described above: tool = tool_make( WIN_LABEL, WIN_ICON, WIN_ATTR_LIST, WIN_WIDTH, WIN_HEIGHT, o) ; "Tool 2.0", fiicon, tool_args, 200 , 100 , Remember to call tool_free_attribute_list after calling tool_make. Creating the tool does not cause it to appear on the screen; a separate step is used for that pur- pose as described in Tool Installation. 6.2.4- Subwindow Creation After the tool is created, its subwindows are added to it. This section describes the basic tool subwindow creation procedure. Often, however, you are not providing your own subwindow implementation. Instead, an existing subwindow package is providing the implementation, e.g., a message subwindow or a panel subwindow. Their create procedures, e.g., msgsw_createtool subwindow or panel_create, handle tool subwindow creation for you. If you are not providing your own subwindow implementation then you can skip down to Tool Installation. 6-12 Revision G of 15 April 1985 SunWindows Reference Manual Suntool: Tools and Subwindows struct toolsw *tool_createsubwindow (tool , name, width, height) struct tool *tool; char * name ; short width, height; #def ine TOOL_SWEXTENDTOEDGE -1 makes a new subwindow, adds it to the list of subwindows for the indicated tool, and returns a pointer to the new toolsw struct. The width and height parameters are hints to the lay- out mechanism indicating what size the windows should be if there is enough room to accommo- date them. There are no guarantees about maintaining subwindow size because changing window sizes can ruin any scheme. TOOL_SWEXTENDTOEDGE may be passed for width and/or height; it allows the subwindow to stretch with its parent in either or both directions. Sub win- dow Layout details the subwindow layout algorithm. The name is currently unused; it may eventually support the capability to refer to subwindows by name. The remaining subwindow initialization requires reference to the data structure: struct toolsw •( struct toolsw *ts_next; int ts_windowfd; char *ts_name; short ts_width; short ts_height; struct toolio ts_io; int (*ts_destroy) () ; caddr_t ts_data; }; The subwindows of a tool are chained on a list with ts_next in one subwindow pointing to the next in line, until the list is terminated with a null pointer. Like the tool window, each subwindow must have an associated open window device; tool_createsubwindow stores the file descriptor in ts_windowfd. ts.name, ts_width and ts_height are exactly as in the call to too l_createsubwindow. The tool uses ts_io to control notification of input and window change events to the subwin- dow. Upon subwindow creation, the ts_io structure has null values in it that need to be set. This is normally done by the create routine for a standard subwindow type. Toolio Structure details this structure. ts_destroy gets called when the tool is being destroyed by tool_destroy so that the subwindow may terminate cleanly. ts_data provides 32 bits of uninterpreted data private to the subwindow implementation. Typi- cally, it will be a pointer to information for this instance of the subwindow. That is, all subwin- dows of the same type will share common interrupt handlers and layout characteristics. Window contents and other information specific to one particular window will alt be accessed through this pointer. This is discussed at more length in Minimum Standard Subwindow Interface in Chapter 7. Revision G of 15 April 1985 6-13 Suntool: Tools and Subwindows SunWindows Reference Manual 6.2.5. Subwindow Layout By default, subwindows are laid out in their tool’s area in a simple left-to-right, top-to-bottom fashion, in the order they are created. A subwindow is placed as high as it can be, and in that space, as far to the left as it can be. The ts_width and ts_height fields in the toolsw structure control the width and height of the subwindow. The default subwindow layout mechanism breaks down for complicated subwindow layouts. This is how you replace the default subwindow layout mechanism with your own. Include a function named too 1_ 1 ayoutsubvindows in your program. Your version of this function will be loaded instead of the function of the same name that the suntool library contains. tool_layoutsubvindows just takes a tool handle and has no return value. It will be called by the tool manager whenever the following occurs: ® The tool’s size has changed. This includes the first time that the tool goes to display itself. q The subwindow boundary manager has changed one of the values of ts_width or ts_height in a toolsw structure. ® The WIN_LAYOUT_LOCK attribute has been set to 0. You can then use win_setrect in your implementation of too 1_1 ayoutsubvindows to layout the subwindows yourself. Note that just setting WIN_LAYOUT_LOCK to 1 and laying out your subwindows at create time is inadequate because you don’t know when to change the subwindow layout. Three functions return numbers useful for doing subwindow layout: short tool_stripeheight (tool) struct tool *tool; returns the height in pixels of the tool’s name stripe. Note that the tool argument cannnot be NULL. short tool_borderwidth (tool) struct tool *tool; returns the width in pixels of the tool’s outside border. If the caller supplies a null tool argu- ment, the function returns the default border width. short tool_subwindowspacing (tool) struct tool *tool; returns the number of pixels that should be left as a margin between subwindows of a tool. 6.2.6. Subwindow Initialization By the time tool_createsubwindow has returned, the subwindow is already inserted in the subtree growing out of the tool window; however, the subwindow will not perform any interest- ing function until ts_io and ts_data have been initialized. Normally, tool_createsubwindov is not directly called. Instead, the tool subwindow creation pro- cedure for a subwindow type is called. The subwindow specific routine will call tool_createsubwindow and then initialize ts_io and ts_data. 6-14 Revision G of 15 April 1985 SunWindows Reference Manual Suntool: Tools and Subwindows 6.2.7. Tool Installation Once the tool is created and its subwindows have been created, the software interrupt system should be turned on via a call to signal as described in Window Change Notifications. At least SIGWINCH should be caught; if there are inferior processes in any of the subwindows, SIGCHLD should be added with any others as appropriate. Finally, the tool is installed into the display window tree by a call to: tool_install (tool) struct tool ‘tool; At this point, the tool is operating; in fact, it will probably shortly receive a SIGWINCH asynchro- nously to paint its window(s) for the first time. 6.2.8. Tool Destruction Explicitly destroying a tool as it reaches the end of its processing allows the system to reclaim resources and remove the windows gracefully. The procedure to invoke this cleanup is: tool_destroy (tool) struct tool ‘tool; tool_destroy will destroy every subwindow of the indicated tool as part of its processing, so the subwindows need not be destroyed explicitly. Each subwindow’s ts_destroy procedure gets called, so they can clean up gracefully. The pointer passed to tool_destroy must never be dereferenced after that call, since it is no longer valid. A single subwindow can be destroyed by an explicit call to: tool_destroysubwindow (tool , subwindow) struct tool ‘tool; struct toolsw ‘subwindow; 6.2.9. Programmatic Tool Creation This section contains considerations if you are programmatically spawning processes that contain tools. 6. 2. 9.1. Forking the Tool A tool has its own process. The creation of that process does not differ significantly from the normal paradigm for process creation. If it is to be started by a menu command or some other procedural interface, it is appropriate for the creating process to do the fork and return from the procedure call. When the child process dies, the parent process should catch the SIGCHLD signal and clean up. See the wait3(2) system call. SIGCHLD indicates to a parent process that a child process has changed state. Revision G of 15 April 1985 6-15 Suntool: Tools and Subwindows SunWindows Reference Manual 6.2.9.S. Environment Parameters Environment parameters are used to pass well-established values to a tool that is starting up. They have the valuable property that they can communicate information across several layers of processes, not all of which have to be involved. Every tool must be given the name of its parent window. A tool’s parent window is the window in the display tree under which the tool window should be displayed. The environment parame- ter WIND 0 W_PARENT is set to a string that is the device name of the parent window. For a tool, this will usually be the name of the root window of the window system. we_setparentwindow (windevname) char ‘windevname; sets WINDOW _PARENT to windevname. int we_getparentwindow (windevname) char ‘windevname; gets the value of WINDOW_PARENT into windevname. The length of this string should be at least WIN_NAMESIZE characters long, a constant found in . A non-zero return value means that the WIND O W J’ARENT parameter couldn’t be found. The environment parameter DEFAULT_FONT contains the font file name that will be used as the tool’s default (see pf_default). Another parameter, WINDOWJNITIALDATA, describes the screen placement of a tool, and whether it should be open or iconic. WINDOWJNITIALDATA contains the coordinates of two rec- tangles, as well as one flag. The rectangles describe the placement and size of the open and closed window, and the flag is a boolean that is non-zero if the tool should start out iconic. The process that is starting the tool may set WINDOWJNITIALDATA before it forks (wmgr_ forktool does this; see Suntools: User Interface Utilities). After the fork, tool_make interrogates these variables. The routines to do this are in the library /usr/lib/libsunwindow . a. we_setinitdata (rnormal , riconic, if lag) struct rect ‘rnormal, ‘riconic; int iflag; sets the environment variable in the parent process, and we_getinitdata (rnormal , riconic, iflag) struct rect ‘rnormal, ‘riconic; int ‘iflag; reads those values in the child process. A non-zero return value means that the WINDOWJNITIALDATA parameter couldn’t be found. A procedure is provided for unsetting WINDOWJNITIALDATA for tools that are going to provide windows for other processes to run in. This procedure prevents a wayward child process from being confused by the incorrectly set environment variable; we_clearinitdata () 6-16 Revision G of 15 April 1985 SunWindows Reference Manual Suntool: Tools and Subwindows @.3. Tool Processing The main loop of a normal tool is encapsulated inside a call to: tool_select (tool , waitprocessesdie) struct tool *tool; int waitprocessesdie; This procedure is the notification distributer used for event-driven program control flow. When some input event, timeout or signal interrupt is detected inside tool_select, a call to a notification handler is made, paasing in enough information to identify what happened, and to which window. When the handler returns, tool_select awaits another event. The waitprocessesdie argument is discussed below in Child Process Management. 6 . 8 . 1 . Toolio Structure The toolio data structure in each toolsw structure holds what is needed for a subwindow to wait for something to happen in the tool_select call. The tool structure uses the toolio data structure within itself to wait for input too. It is defined in . struct toolio { Int tio_inputmask / int tio_outputmask„ int t io_exceptmask ; struct timeval *tio_timer; int (*tio_handlesigwinch) () ; int (*tio_selected) () ; >; tio_inputmask, tio_outputmask, tio_exceptmask and tio_timer fields are analo- gous to the last four arguments to the select system call. tio_inputmask has the bit “1 «/” set for each file descriptor / on which a window wants to wait for input. Similarly, tio_outputmask and tio_exceptmask indicate an interest in /being ready for writing and having an exceptional condition pending, respectively. There are currently no “exceptional con- ditions” implemented; this field provides compatibility with the select system call. If tio_timer is a non-zero pointer, it specifies a maximum interval to wait for one of the file descriptors in the masks to require attention. If tio_timer is a zero pointer, an infinite timeout is assumed. To effect a poll, the tio_timer argument should be non_zero, pointing to a timeval structure with all zero fields. toolio also contains pointers to the procedures that are called when the tool has received some notification. tio_handlesigwinch addresses the procedure that responds to the SIGWINCH signal. This procedure handles repaint requests and window size changes. The general form for such a procedure is: sigwinch_handler (data) caddr_t data; Such procedures take a single argument data whose type is context-dependent. For a tool this data is a pointer to the tool structure. For a subwindow this data is the ts_data value in the toolsw structure. tio_selected addresses the procedure which responds to notifications from the select sys- tem call. The procedure’s calling sequence is: Revision G of 15 April 1985 6-17 Suntool: Tools and Subwindows SunWindows Reference Manual io__handler (data, caddr_t int int int struct ibits, data; 4 ibits, ♦obits, ♦ebits, timeval obits, ebits, timer) * ‘timer; In such procedures, the data argument is like that of the SIGWINCH handlers described above. The three integer pointers indicate which file descriptors are ready for reads (* ibits), writes (♦obits), or exception-handling (*ebits). If timer is NULL, this window was not waiting on any timeout. If ‘timer points to a valid struct timeval then this window is waiting for a timeout. If both the (*timer) ->tv_sec and (*timer) ->tv_usec are zero, the timeout has just happened for this window and should be serviced. The data in the file descriptor masks is not defined if a timeout has occurred. Before returning from a procedure of this type, the masks and timer must be reset by storing through the pointers passed in the arguments; the values should be consistent with the discussion of the masks and timer pointer above. You may not want to reset the timer if you are using it as a countdown timer, and it still has time remaining on it. 6.3.2. File Descriptor and Timeout Notifications tool_select generates three composite masks by merging the corresponding masks from all of the toolio structures in the tool. The input mask is special in that if all the masks in a partic- ular toolio structure are zero, an entry in the composite input mask is made for the associ- ated window anyway. tool_select also determines the shortest timeout that any of the win- dows is waiting on. The composite masks and shortest timeout are passed to the select sys- tem call. When the select system call returns normally, windows that have a match between their masks and the mask of ready file descriptors that have timed out are notified via their tio_selected procedure. Each tio_selected procedure is called with the complete ready masks, not just the intersection of its own masks and the ready masks. However, a tio_se lected procedure is called with its own window’s timer value. Each window that has been selected as a result of the select system call is notified. The order of notification is not defined. Problems will arise if there are multiple non-cooperating windows waiting on the same device. It should be noted that timers in this implementation are only approximate. When the select system call returns and a timeout hasn’t occurred, the select is assumed to have been instan- taneous. Also, the time taken up with handling notifications is not deducted from the timers. 6.3.3. Window Change Notifications Clients of the tool interface must catch the SIGWINCH signal. A signal catcher can be set up via the signal(3) library call. That catcher is then responsible for notifying the tool package that the signal has arrived. This is done by calling: tool_sigwinch (tool) struct tool ‘tool; This procedure simply sets the TOOL_SIGWINCHPENDING flag in tool. The receipt of any signal 6-18 Revision G of 15 April 1985 SunWindows Reference Manual Suntool: Tools and Subwindows has the side effect of causing the select system call in tool_select to return abnormally. The TOOL_SIGWINCHPENDING flag is noticed and the tool’s tio_handlesigwinch procedure is called. The default tio_handlesigvinch procedure does some processing, which may include changing the subwindow layout, and eventually calls all its subwindows’ tio_handlesigwinch procedures. 6.3.4 ■ Child Process Maintenance tool_select also gathers up dead children processes of the tool. The waitprocessesdie argument to tool_select is provided for tools which have separate processes behind some of their subwindows. Such tools must explicitly catch SIGCHLD, the signal that indicates to a parent process that a child process has changed state. Then the signal handler, parallel to a SIGWINCH catcher and tool_sigwinch, should call: tool_sigchld (tool) struct tool *tool; This call causes tool_select to try to gather up a dead child process via a wait3 system call (see wait(2)). When as many child processes have been gathered up as indicated by the waitprocessesdie argument to tool_select, tool_select returns. 6.3.5. Changing the Tool’s Attributes Tool attributes may be changed even after a tool has been created. tool_set_attributes specifies changes to tool attributes. /* VARARGS */ int too l_set_attributes (tool , id, value, id, value, ... O) struct tool *tool; int id; caddr_t value; tool_set_attributes takes a variable number of attribute identifier/value pairs, terminated by the special attribute identifier 0. A list of valid attributes is available in the section Tool Attributes, id’s are the attribute identifiers, value’s are the attribute values of the preced- ing id. This routine returns 0 if all the arguments are OK, —1 otherwise. All feedback is taken care of, e.g., when setting the label, the name stripe is redisplayed. Repainting is only done once at the end of the tool_set:_attributes call. All arguments passed into tool_set_attributes are copied. Thus, all accesses of attribute values must use tool_get_attribute. caddr_t tool_get_attribute (tool , id) struct tool *tool; int id; tool_get_attribute allows the programmer to determine the value of the attribute identified by id at any time in the life of the tool. The return value of the function is the value of the attribute. If id is not understood then —1 is returned. The returned value is either a 32 bit non-dynamically allocated quantity or a pointer to dynamically allocated storage. The type of the return value depends on the attribute and will usually need to be cast into that type. For pointer values, tool_free_attribute must be called to release the storage allocated during Revision G of 15 April 1985 6-19 Sun tool: Tools and Subwindows SunWindows Reference Manual this call. tool_free_attribute (id, value) int id; caddr_t value; tool_free_attribute releases the storage allocated during tool_get_attribute or tool_find_attribute calls. If id’s value is defined as a non-dynamically allocated quan- tity, then value is not freed and this call does nothing. 6.8.6. Terminating Tool Processing During the time that tool_select is acting as the main loop of the program, a call to: tool_done (tool) struct tool ‘tool; causes the flag TOOL_DONE to be set in tool. tool_select notices this flag, and then returns gracefully. 6.8.7. Replacing Toolio Operations Since the toolio structure contains procedure pointers in variables, it is possible to customize the behavior of a window by replacing the default values. Icons that respond to user inputs or that update their image in response to timer or other events, may be implemented by replacing the tool’s tio_selected procedure. A different subwindow layout scheme may be implemented in a replacement procedure for tio_handlesigwinch. Note that these modifications do not require changes to existing libraries; the address of the sub- stitute routine is simply stored in the appropriate slot at run-time. However, the substitute rou- tine must either do all of the processing handled by the original library routine, or the substitute routine should do its special processing and then call the original library routine. 6-20 Revision G of 15 April 1985 SunWindows Reference Manual Suntool: Tools and Subwindows 6.8.8. Boilerplate Tool Code Here is the boilerplate code for a simple tool. It illustrates the order in which things should be done in a tool. All of the window related calls have been discussed in this chapter. #include #include static struct tool ‘tool; main(argc, argv) int argc; char “argv; { char “tool_attrs = NULL; char *tool_name = argv [0] ; static int sigwinchcatcher () ; argv++ ; argc-- ; /* Pick up command line arguments to modify tool behavior */ if (tool_parse_all (&argc, argv, &tool_attrs, tool_name) == -1) { tool_usage (tool_name) ; exit (1) ; > /* Get application specific args */ while (argc > 0 && “argv == * — * ) { /* Parse switches */ argv++; argc-- ; > /* Create tool window */ tool = tool_make( WIN_LABEL , tool_name, WI N_ATTR_L 1ST, tool_attrs, o) ; if (tool == (struct tool *)NULL) exit (1) ; tool_free_attribute_list (tool_attrs) ; /* . . .Create tool subwindows. . . */ /* Install tool in tree of windows */ (void) signal (SIGWINCH, sigwinchcatcher); tool_install (tool) ; /* Run notifier */ tool_select (tool , 0) ; /* Cleanup */ tool_destroy (tool) ; exit (0) ; > static sigwinchcatcher () ■{ too l_sigwinch (tool) ; }• Revision G of 15 April 1985 &-21 Suntool: Tools and Subwindows SunWindows Reference Manual 6.3.9. Old Style Tool Creation tool_make is the recommended call to use when creating a tool window. tool_create is an out-dated call that used to do this for you. While tool_create still works, it is not recom- mended. Here is tool_create documentation. A tool is created by a call to: struct tool *tool_create (name, flags, normalrect, icon) char ‘name; short flags; struct rect ‘normalrect; struct icon ‘icon; #def ine TOOL_NAMESTRIPE 0x01 #def ine T00L_B0UNDARYMGR 0x02 name is the name of the tool. This is what will be displayed in the tool’s name stripe if TOO L_NAMESTRIPE is set in the flag’s argument. It also appears on the default icon. flags has the flags TO OL_NAMESTRIPE and/or TOOL_BOUNDARYMGR set as those proper- ties are desired. (TOOL_BOUNDARYMGR enables boundaries that the user can move between subwindows.) normalrect describes the initial position and size of the tool in its normal open state in the coordinate system of the tool’s parent, which is typically the window for the screen. icon is a pointer to an icon struct, if the client wants a special icon. normalrect and the icon may be defaulted by passing NULL for their arguments. The default icon is described, along with considerations for making custom icons, in Suntool: User Interface Utilities ; the choice is strictly a matter of convenience vs. ambition. A tool’s starting position should almost always be left NULL; it could be the result of WELGETINITDATA that is going into normalrect. Note, tool_display is an outdated tool operation that has been taken over by tool_set_attributes. During processing, a call to: tool_display (tool) struct tool ‘tool; redisplays the entire tool. This is useful if some change has been made to the image of the tool itself, for instance if its name or its icon’s image have been changed. Normal repaints in response to size changes or damage should not use this procedure. They will be taken care of by SIGWINCH events and their handlers. 6-22 Revision G of 15 April 1985 Chapter 7 Simtool: Subwindow Packages This chapter describes subwindow packages, the building blocks for constructing a tool. It presents a guide for building new subwindow packages of general utility and describes the avail- able standard subwindow packages for use with suntools. Refer to Suntool: Tools and Subwin- dows for a description of the overall structure of tools and the general notion of a subwindow. Subwindows, as presented here, are designed to be independent of the particular framework in which they are used. That is, a subwindow is a merger of window handling and application pro- cessing which should be valid in frameworks other than the tool structure and suntool environ- ment described in the preceding chapter. The design avoids any dependence on those con- structs. Thus, a subwindow package can be used in another user interface system written on top of the sunwindow basic window system. However, subwindow packages all provide a utility for creating a subwindow in the tool context. 7.1. Minimum Standard Subwindow Interface This section describes the minimum programming interface one should define when writing a new subwindow package. A subwindow implementation should provide all the facilities described here. This section presents the arguments to the following standard procedures. Each subwin- dow package need only document any additional arguments passed to its create/ init procedures. There is a set of naming conventions that provides additional consistency between subwindow package interfaces. For the purpose of example, we use proto as the prefix. Other prefixes used in existing subwindow packages include tty, gfx and msg. Each subwindow package has a structure definition that contains all the data required by a single instance of the subwindow. struct protosubwindow { int fsw_windowfd; struct pixwin *fsw_pixwin; }; The structure definition typically has a pixwin for screen access and a window handle for identification as part of this data. The information that the subwindow’s procedures need should be stored in this data structure; this may entail redundantly storing some data that is in the associated containing data structure, such as the toolsw struct. Having an object per subwin- dow allows multiple instantiations of a subwindow package in a single-user process. The follow- ing function creates new instances of a proto-subwindow: struct protosubwindow *protosw_init (windowfd, ...) int windowfd; Revision G of 15 April 1985 7-1 Suntool: Sub-window Packages SunWindows Reference Manual window fd is to be a proto-subwindow. The indicates that many subwindow packages will require additional set-up arguments. This routine typically opens a pixwin, sets its input mask as described in Input to Application Programs, and dynamically allocates and fills the subwindow’s data object. If the returned value is NULL then the operation failed. protosw_done (protosw) struct protosubwindow ‘protosw; destroys subwindow instance data. Once this procedure is called, the protosw pointer should no longer be referenced. protosw_handlesigwinch (protosw) struct protosubwindow ‘protosw; This procedure handles repaint requests and must also detect and deal with changes in the win- dow size. It is called as an eventual result of some other procedure catching a SIGWINCH. protosw_selected (protosw, ibits, obits, ebits, timer) struct protosubwindow ‘protosw; int *ibits. int ‘obits , int *ebits , struct timeval “timer; handles event notifications. Subwindow packages that don’t accept input may not have a pro- cedure of this type. The semantics of this procedure are fully described in the preceding chapter in the section entitled Toolio Structure. struct toolsw *protosw_createtoolsubwindow (tool , name, width, height, ... struct tool ‘tool; char ‘name; short width, height; creates a struct toolsw that is a proto-subwindow. protosw.createtoolsubwindow is only applicable in the tool context. It is often the only call that an application program need make to set up a subwindow of a given type. tool is the handle on the tool that has already been created. name is the name that you want associated with the subwindow. width, and height are the dimensions of the subwindow as wanted by the tool.createsubwindow call. The “...” indicates that many subwindow packages will require additional arguments. These additional arguments should parallel those in protosw_init. If the returned value is NULL then the operation failed. protosw_createtoo lsubwindow takes the wundow file descriptor it gets from tool_createsubwindow, passes it to protosw_init, and stores the resulting pointer in the tool subwindow’s ts_data slot. The addresses of protosw_handlesigwinch and protosw_selected are stored in the appropriate slots of the toolio structure for the tool subwindow, and the address of protosw_done is stored in the tool subwindow’s ts_destroy procedure slot. Of course, most subwindow packages define functions that perform application-specific process- ing; the ones described here are merely the permissible minimum. 7-2 Revision G of 15 April 1985 SunWindows Reference Manual Suntook Subwindow Packages 7.2. Empty Subwindow The empty subwindow package simply serves as a place bolder. It does nothing but paint itself gray. It expects the window it is tending to be taken over by another process as described in Graphics Subwindow. When the other process is done with the empty subwindow package, the caretaker process resumes control. A private data definition that contains instance-specific data defined in is: struct emptysubwindow { int eio_windowfd; struct pixwin *enu.pixwin; }; em_windowfd is the file descriptor of the window that is tended by the empty subwindow. em_pixwin is the structure for accessing the screen. struct toolsw *esw_createtoolsubwindow (tool , name, width, height) struct tool ‘tool; char ‘name; short width, height; sets up an empty subwindow in a tool window. If the returned value is NULL then the operation failed. Since esw_createtoolsubwindow takes care of setting up the empty subwindow, the reader may not be interested in the remainder of this section. struct emptysubwindow *esw_init (windowfd) int windowfd; creates a new instance of an empty subwindow, windowfd is the window to be tended. If the returned value is NULL then the operation failed. esw_handlesigwinch (esw) struct emptysubwindow *esw; handles SIGWINCH signals. If the process invoking this procedure is the current owner of esw— >em_windowfd, gray is painted in the window. If it is not the current owner, it checks to see if the current owner is still alive. If the current owner is dead, this process takes over the windows again and paints gray in the window. esw_done (esw) struct emptysubwindow *esw; destroys the subwindow’s instance data. Processes that take over windows should follow guidelines discussed in Overlapped Windows: Imaging Facilities concerning the use of the win_getowner and win_setowner procedures. Preferably, the graphics subwindow interface described below should be used for this activity. 7.3. Graphics Subwindow The graphics subwindow package is for programs that need a single window in which to draw. Using this subwindow package insulates programmers of this type of program from much of the complexity of the window system. Revision G of 15 April 1985 7-3 Suntool: Subwindow Packages Sun Windows Reference Manual Users of this interface have the additional benefit of being able to invoke their programs from outside the window system. Thus, you can write one program and have it run both inside and outside the window system. This situation is actually an illusion. What really happens when running outside the window system is that the window system is actually started up and that a single window is created in which the graphics subwindow package runs. The graphics subwindow can also manage a retained window for the programmer. The program- mer need not worry about the fact that he is in an overlapping window situation. A backup copy of the bits on the screen is maintained from which to service any repaint requests. Appendix C contains programs based on graphics subwindows. The graphics subwindow can be used in tool building like any of the other subwindow packages described in this chapter. However, the graphics subwindow also provides the ability for a pro- gram to run on top of an existing window by using the blanket window mechanism. The data definition for the instance-specific data defined in is: struct gfxsubwindow -{ int gfx_windowfd; int gfx_f lags; int gfx_reps; struct pixwin *gfx_pixwin; struct rect gfx_rect; caddr_t gfx_takeoverdata; >; #def ine GFX_RESTART OxOl ^define GF X_D AMAGE D 0x02 gfx_windowfd is the file descriptor of the window that is being accessed. gfx_reps are the number of repetitions that continuously running (non-blocking) cyclic programs are to execute. gfx_pixwin is the structure for accessing the screen. gfx_rect is a cached copy of the window’s current self relative dimensions. gfx_takeoverdata is data private to the graphics subwindow package. gfx_flags contains bits that the client program interprets. The GFX_DAMAGED bit is set by the graphics subwindow package whenever a SIGWINCH has been received. In addition, the GFX_RESTART bit is set if the size of the window has changed or the window is not retained. The client program must examine these flags at the times described below. GFX_DAMAGED means that gfxsw_handlesigwinch should be called. This flag should be examined and acted upon before looking at GFX_RESTART. GFX_RESTART is often interpreted by a graphics program to mean that the image should be scaled to a new window size and that the image should be redrawn. Many continuous programs, graphics demos for instance, redraw from the beginning of a cycle. Other event-driven programs, graphics editors and status windows, for example, redraw from their underlying data descriptions. The GFXJtESTART bit needs to be reset to 0 by the client program before actually doing any redrawing. 7.3.1. In a Tool Window A graphics subwindow in a tool context is only applicable for event-driven programs that use the tool_select mechanism. Any subwindow in a tool must use this notification mechanism so that all the windows are able to cooperate in the same process. 7-4 Revision G of 15 April 1985 SunWindows Reference Manual Suntool: Subwindow Packages struct toolsw *gfxsw_createtoolsubwindow (tool , name, width, height, argv) struct tool ‘tool; char ‘name; short width, height; char “argv; sets up a graphics subwindow in a tool window. If argv is not zero, this array of character pointers is processed like a command line in a standard way to determine whether the window should be made retained r” and/or what value should be placed in gfx_reps n ####”. If the returned value is NULL then the operation failed. It is the responsibility of the client to set up toolsw— >ts_io . tio_selected if the client is to process input through the graphics subwindow. It is also the responsibility of the client to replace toolsw— >ts_io . tio_handlesigwinch with the client’s own routine to notify the client when something about his window changes. The client tio_handlesigwinch will call gfxsw_interpretesigwinch described below. gfxsw_getretained (gfxsw) ; struct gfxsubwindow ‘gfxsw; can be called to make a graphics subwindow retained if you choose not to do the standard com- mand line parsing provided by gfxsw.createtoolsubwindow. It should be called immedi- ately after the graphics subwindow is created. Destroying gfxsw— >gfx_prretained has the effect of making the window no longer retained. The procedure; gfxsw_interpretesigwinch (gfxsw) struct gfxsubwindow ‘gfxsw; is called from the client tio_handlesigwinch to give the graphics subwindow package a chance to set the bits in gfxsw— >gfx_f lags. The code in the client tio_handlesigwinch then checks the flags and responds appropriately, perhaps by calling the gfxsw_handlesigwinch procedure that handles SIGWINCH signals: gfxsw_handlesigwinch (gfxsw) struct gfxsubwindow ‘gfxsw; If the window is retained and the window has not changed size, this routine fixes up any part of the image that has been damaged. If the window is retained and the window has changed size, this routine frees the old retained pixrect and allocates one of the new size. If the window is not retained, the damaged list associated with the window is thrown away. The GFX_DAMAGF,D flag is reset to zero in this routine. The procedure: gfxsw_done (gfxsw) struct gfxsubwindow ‘gfxsw; destroys the subwindow’s instance data. 7.3.2. Overlaying an Existing Window The graphics subwindow provides the ability for a program to overlay an existing window. The empty subwindow described above is designed to be overlaid. Revision G of 15 April 1985 7-5 Suntool: Sub-window Packages Sun Windows Reference Manual The following procedure creates a new instance of a graphics subwindow in something other than the tool context: struct gfxsubwindow *gfxsw_init (windowfd, argv) int windowfd; char “argv; windowfd should be zero; the assumption is that there is some indication in the environment as to which window should be overlayed. See ve_getgfxwindov in Window Manipulation for more information. argv is like argv in gfxsw_createtoolsubwindow. In addition, arguments similar to the ones recognized by win_initscreenfromargv are parsed. Thus, the program can be directed to run on a particular screen. If the returned value is NULL then the operation failed. Wnen a screen is created from scratch, window system keyboard and mouse processing are not turned on. gfxsw_setinputmask should be called instead of win_setinputmask when defining window input (see below) in order to enable window system keyboard and mouse pro- cessing. This mechanism is used to allow programs that listen to the standard input to still run when started from outside the window system. gfx_takeoverdata in the returned gfxsubwindow data structure is not zero in this case. The structure of the data that this pointer refers to is private to the implementation of the graphics subwindow. When a graphics subwindow has overlayed another window, various signal catching routines are set up if the corresponding signals have no currently defined handler routines. The gfxsw_catchsigwinch procedure is set up as the signal catcher of SIGWINCH: gfxsw_catchsigwinch () It, in turn, calls gfxsw_interpretesigwinch. The gfxsw_catchsigtstp procedure is set up as the signal catcher of SIGTSTP: gfxsw_catchsigtstp () The graphics subwindow is removed from the display tree. The pixwin of the graphics subwin- dow is reset. SIGSTOP is sent to the the graphics subwindow’s own process. The gfxsw_catchsigcorvt procedure is set up as the signal catcher of SIGCONT: gfxsw_catchsigcont () The graphics subwindow is inserted back into the displays tree (presumably after gfxsw_catchsig-tstp removed it). Continuous programs that never use a select mechanism should examine gfxsw— >gfx_f lags in their main loop. Other programs that would like to use a select mechanism to wait for input/timeout should call: gfxsw_select (gfxsw, selected, ibits, obits, ebits, timer) struct gfxsubwindow ‘gfxsw; int (‘selected) () , ibits, obits, ebits; struct timeval ‘timer; as a substitute for the tool_select. selected is the routine that is called when some input or timeout is noticed. Its calling sequence is exactly like protosw_selected described at the beginning of this chapter. The only difference in the semantics of this routine and protosw_selected is that the gfxsw— >gfx_f lags should be examined and acted upon in selected. selected may be called with no input pending so that you are able to see the 7-6 Revision G of 15 April 1985 SunWindows Reference Manual Suntool: Subwindow Packages flags when they change. ibits, obits, ebits and timer, as well as gfxsw and selected, can be thought of as initializing an internal toolio structure, which is then fed to the tool_select mechanism. A substitute for the tool_done procedure is: gfxsw_selectdone (gfxsw) struct gfxsubwindow *gfxsw; gfxsw_selectdone is called from within the selected procedure passed to gfxsw_select. Programs that are not using the mouse can call: gfxsw_notusingmouse (gfx) struct gfxsubwindow *gfx; In certain cases, when the graphics subwindow is the only window on the display for instance, some efficiency measures can be taken. In particular, pixwin locking overhead can be reduced. gfxsw_setinputmask (gfx, im_set, im_flush, nextwindownumber , usems , usekbd) struct gfxsubwindow *gfx; int nextwindownumber ; struct inputmask *im_set, *im_flush; int usems, usekbd; The calling sequence is essentially that of win_setinputmask. usems being non-zero means that mouse input is wanted and so the mouse is turned on for the screen (if currently off), usekbd being non-zero means that keyboard input is wanted and so the keyboard is turned on for the screen (if currently off). See gfxsw_init (above) for a rationale for using gfxsw_setinputmask instead of win_setinputmask. gfxsw_input interrupts (gfx, ie) struct gfxsubwindow *gfx; struct inputevent *ie; This utility looks at *ie. If *ie is a character that (on a tty) normally does process control (interrupts the process, dumps core, stops the process, terminates the process), it does the similar action. This routine is meant to be a primitive substitute for tty process control while using the window input mechanism. Remember to call gfxsw_done to “give back” the window that was taken over. 7.4. Message Subwindow The message subwindow is an extremely simple facility. If you are not concerned about the size of the client’s object code, or if the client already employs a panel subwindow, you should con- sider using the panel subwindow with a single message item instead of the message subwindow. This is because the panel subwindow provides superior functionality and a cleaner interface than does the message subwindow. Please see the chapter entitled The Panel Subwindow Package for further information on panels. The message subwindow package displays simple ASCII strings. A private data definition that contains instance-specific data defined in < suntool /ms gsw .h> is: Revision G of 15 April 1985 7-7 Suntool: Subwindow Packages SunWindows Reference Manual struct msgsubwindow { int msg_windowfd; char* msg_string; struct pixfont *msg_font; struct rect msg_rectcacha; struct pixwin *msg_pixwin; >; msg_windowfd is the file descriptor of the window that is the message subwindow. msg_string is the string being displayed using msg_font. Only printable characters and blanks are properly dealt with, not carriage returns, line feeds or tabs. The implementation uses msg_rectcache to help determine if the size of the subwindow has changed. msg_pixwin is the structure that accesses the screen. struct toolsw *msgsw_createtoolsubwindow (tool , name, width, height, string, font) struct tool ‘tool; char ‘name; short width, height; char ‘string; struct pixfont ‘font; is the call that sets up a message subwindow in a tool window. string is the string being displayed using font. If the returned value is NULL then the operation failed. Since msgsw_createtool subwindow takes care of the set-up of the message subwindow, the reader may not be interested in the remainder of this section, except for msgsw_setstring. The following function creates a new instance of a message subwindow: struct msgsubwindow *msgsw_init (windowfd, string, font) int windowfd; char ‘string; struct pixfont ‘font; windowfd identifies the window to be used, string is the string being displayed using font. If the returned value is NULL then the operation failed. msgsw_setstring (msgsw, string) struct msgsubwindow ‘msgsw; char ‘string; changes the existing msgsw— >msg_string to string and redisplays the window. msgsw_display (msgsw) struct msgsubwindow ‘msgsw; redisplays the window. msgsw_handlesigwinch (msgsw) struct msgsubwindow ‘msgsw; is called to handle SIGWINCH signals. It repairs the damage to the window if the window hasn’t changed size. If the window has changed size, the string is reformatted into the new size. msgsw_done (msgsw) struct msgsubwindow ‘msgsw; destroy’s the subwindow’s instance data. 7-8 Revision G of 15 April 1985 SunWindows Reference Manual Suntool: Subwindow Packages 7.5. Terminal Emulator Subwindow The terminal emulator subwindow mimics a standard Sun terminal. It accepts most of the same ANSI escape sequences as the Sun terminal (see cons (4s) in the System Interface Manual). However, certain control sequences cause the terminal emulator subwindow to behave differently from the normal Sun terminal. The table following lists these control sequences and their effects. Definitions for the use of the terminal emulator subwindow are in . Note: Only one tty subwindow per process is allowed. Table 7-1: Differences between Sun terminal and SunWindows tty emulator Control seauence Sunovsis Behavior in SunWindows ttu emulator CTRL-G (0x07) Bell Flashes window. ESC |p Black on white No effect. ESC I'd White on black No effect. ESCTOr Enable vertical wrap mode 3 No effect. ESC f s Reset No effect. "ESC" indicates the ASCII escape character (OxlB). struct toolsw *ttysw_createtoolsubwindow (tool , name, width, height) struct tool ‘tool; char ‘name; short width, height; is the call that sets up a terminal emulator subwindow in a tool window. ttysw_createtool subwindow takes care of setting up the terminal emulator subwindow except for the forking of the program. Thus, clients of this routine may want to ignore the remainder of this section except for the discussion of ttysw_fork and perhaps tty sw_becomeconso 1 e. ttysw_createtoolsubwindow returns NULL on failure. caddr_t ttysw_init (windowfd) int windowfd; creates a new instance of a tty subwindow. windowfd is the window that is to be used. ttysw_init returns NULL on failure. ttysw_becomeconsole (ttysw) caddr_t ttysw; sets up the terminal emulator to receive any output directed to the console. This should be called after calling ttysw_init. ttysw_saveparms (ttyfd) int ttyfd; should be called by the screen initialization program, e.g., suntools (1). This saves the characteristics of the terminal ttyfd in an environment variable. Terminal emulation * Note that the zero in this escape sequence may be replaced by an integer, in order to set up jump scrolling. Positive integer arguments do supply the desired effect. Revision G of 15 April 1985 7-9 Suntool: Sub-window Packages SunWIndows Reference Manual processes forked from the screen initialization process will get their characteristics from this environment variable; terminal emulation processes started directly from shells get their charac- teristics from the standard error tty. ttysw_saveparms is needed because a screen initializa- tion program is often started from the console, whose characteristics can change due to console redirection. ttysw_handlesigwinch (ttysw) caddr_t ttysw; is called to handle SIGWINCH signals. On a size change, the terminal emulator’s display space is reformatted. Also, its process group is notified via SIGWINCH that the size available to it is different. Refer to TTY-Based Programs in TTY Subwindows. If there is display damage to be fixed up, the terminal emulator redisplays the image by using character information from its screen description. ttysw_selected (ttysw, ibits, obits, ebits, timer) caddr_t ttysw; int ‘ibits, ‘obits, ‘ebits; struct timeval “timer; reads input and writes output for the terminal emulator. ‘ibits, ‘obits and ‘timer are modified by ttysw_selected. See the general discussion of tio_selected type procedures in Minimum Standard Subwindow Interface. int ttysw_fork (ttysw, argv, inputmask , outputmask , exceptmask) caddr_t ttysw; char “argv; int ‘inputmask, ‘outputmask, ‘exceptmask; forks the program indicated by ‘argv. The identifier of the forked process is returned. If the returned value is —1 then the operation failed and the global variable errno contains the error code. There are the following possibilities: • If ‘argv is NULL, the user SHELL environment value is used. If this environment parameter is not available, /bin/sh is used. ® If ‘argv is c”, this flag and argv [1] are passed to a shell as arguments. The shell then runs argv[l]. The argument list for this case becomes shell -c argv[l] 0. o If ‘argv is not NULL, the program named by argv [O] is run with the arguments given in the rest of argv. The argument list should be NULL terminated. The arguments ‘inputmask, ‘ouputmask, ‘exceptmask are dereferenced by ttysw_fork and set to the values that the terminal eumlator subwindow manager wants to wait on in a subsequent select (2) call. ttysw_done (ttysw) caddr_t ttysw; destroys the subwindow’s instance data. 7-10 Revision G of 15 April 1985 SunWindows Reference Manual Suntool: Sub-window Packages 7.5.1. The Tool Specific TTY Subwindow Type The tool terminal emulator subwindow, called the tty tool subwindow, extends the basic terminal emulator subwindow. A tty tool subwindow is a super class of a straight terminal emulator subwindow. This means that a tty tool subwindow can do what a straight terminal emulator subwindow can, and more. In particular, a tty subwindow knows about tool windows and allows terminal-emulator-based programs to set/get data about the tool window. Also, the user can send window management commands to change the tool window via the keyboard. The only public access to a tty tool subwindow is its create/destroy procedures, ttyt lsv_createtoolsubwindow and ttyt lsw_done. Other than this, think of the subwmdow as a straight terminal emulator subwindow. The following table shows the escape sequences that can be sent to a tty tool subwindow. Do not send these escape sequences to a straight terminal emulator subwindow, because they will be ignored. Revision G of 15 April 1985 7-11 Suntool: Subwindow Packages SunWindows Reference Manual Table 7-2: Escape sequences for tty tool subwindow Description Opens a tool. Closes a tool. Moves the tool with interactive feedback. Moves the tool so that its top left corner is at TOP; LEFT. TOP and LEFT are in pixels. Stretches a tool with interactive feedback. Stretches a tool to WIDTH and HT. WIDTH and HT are in pixels. Exposes a hidden tool. Hides a tool. Refreshes the tool window. Stretches the tool so that its width and height are ROWS and COLS, respectively. Reports if the tool is open or iconic by sending \E [It (open) or \E [2t (close) sequence. Reports the tool’s position by sending the \E [3; TOP; LEFT sequence. Reports the tool’s size in pixels by sending the \E [4; WIDTH; HEIGHT sequence. Reports the tool’s size in characters by sending an \E [8; ROWS; COLSt sequence. Reports the tool’s namestripe by sending an \E1 1 sequence (see below). Sets the tool’s namestripe to . Sets the icon to the icon contained in < file>. Sets the icon label to